From 72f1b998ac385ed2c1f7e57a409b6616afdaf6e2 Mon Sep 17 00:00:00 2001 From: LiuMingYu <734904515@qq.com> Date: Tue, 23 Aug 2016 22:32:28 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E8=BF=9B=E4=B8=80=E6=AD=A5=E6=9B=B4?= =?UTF-8?q?=E6=94=B9=E9=98=BB=E6=96=AD=E5=8F=8A=E4=B8=A5=E9=87=8D=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/robotscs/TestMaxTurnRate.java | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java b/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java index 551fac3..5507bb1 100644 --- a/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java +++ b/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java @@ -40,33 +40,33 @@ public class TestMaxTurnRate extends RobocodeTestBed { if (event.getTurnSnapshot().getTurn() == 26) { final String out = buf.toString(); - Assert.assertTrue(out.contains("1: 0.0, 0.0") | out.contains("1: 0.0, -0.0")); - Assert.assertTrue(out.contains("2: 0.0, -1.0") | out.contains("2: 0.0, -0.999999999")); - Assert.assertTrue(out.contains("3: 0.0, -2.0") | out.contains("3: 0.0, -1.999999999")); - Assert.assertTrue(out.contains("4: 0.0, -3.0") | out.contains("4: 0.0, -2.999999999")); - Assert.assertTrue(out.contains("5: 0.0, -4.0") | out.contains("5: 0.0, -3.999999999")); - Assert.assertTrue(out.contains("6: 0.0, -5.0") | out.contains("6: 0.0, -4.999999999")); - Assert.assertTrue(out.contains("7: 0.0, -6.0") | out.contains("7: 0.0, -5.999999999")); - Assert.assertTrue(out.contains("8: 0.0, -7.0") | out.contains("8: 0.0, -6.999999999")); - Assert.assertTrue(out.contains("9: 0.0, -8.0") | out.contains("9: 0.0, -7.999999999")); - Assert.assertTrue(out.contains("10: 0.0, -9.0") | out.contains("10: 0.0, -8.999999999")); - Assert.assertTrue(out.contains("11: 0.0, -10.0") | out.contains("11: 0.0, -9.999999999")); - Assert.assertTrue(out.contains("12: 0.0, -10.0") | out.contains("12: 0.0, -9.999999999")); - Assert.assertTrue(out.contains("13: 0.0, -10.0") | out.contains("13: 0.0, -9.999999999")); + Assert.assertTrue(out.contains("1: 0.0, 0.0") || out.contains("1: 0.0, -0.0")); + Assert.assertTrue(out.contains("2: 0.0, -1.0") || out.contains("2: 0.0, -0.999999999")); + Assert.assertTrue(out.contains("3: 0.0, -2.0") || out.contains("3: 0.0, -1.999999999")); + Assert.assertTrue(out.contains("4: 0.0, -3.0") || out.contains("4: 0.0, -2.999999999")); + Assert.assertTrue(out.contains("5: 0.0, -4.0") || out.contains("5: 0.0, -3.999999999")); + Assert.assertTrue(out.contains("6: 0.0, -5.0") || out.contains("6: 0.0, -4.999999999")); + Assert.assertTrue(out.contains("7: 0.0, -6.0") || out.contains("7: 0.0, -5.999999999")); + Assert.assertTrue(out.contains("8: 0.0, -7.0") || out.contains("8: 0.0, -6.999999999")); + Assert.assertTrue(out.contains("9: 0.0, -8.0") || out.contains("9: 0.0, -7.999999999")); + Assert.assertTrue(out.contains("10: 0.0, -9.0") || out.contains("10: 0.0, -8.999999999")); + Assert.assertTrue(out.contains("11: 0.0, -10.0") || out.contains("11: 0.0, -9.999999999")); + Assert.assertTrue(out.contains("12: 0.0, -10.0") || out.contains("12: 0.0, -9.999999999")); + Assert.assertTrue(out.contains("13: 0.0, -10.0") || out.contains("13: 0.0, -9.999999999")); - Assert.assertTrue(out.contains("14: 0.0, 0.0") | out.contains("14: 0.0, -0.0")); - Assert.assertTrue(out.contains("15: 0.0, 1.0") | out.contains("15: 0.0, 0.999999999")); - Assert.assertTrue(out.contains("16: 0.0, 2.0") | out.contains("16: 0.0, 1.999999999")); - Assert.assertTrue(out.contains("17: 0.0, 3.0") | out.contains("17: 0.0, 2.999999999")); - Assert.assertTrue(out.contains("18: 0.0, 4.0") | out.contains("18: 0.0, 3.999999999")); - Assert.assertTrue(out.contains("19: 0.0, 5.0") | out.contains("19: 0.0, 4.999999999")); - Assert.assertTrue(out.contains("20: 0.0, 6.0") | out.contains("20: 0.0, 5.999999999")); - Assert.assertTrue(out.contains("21: 0.0, 7.0") | out.contains("21: 0.0, 6.999999999")); - Assert.assertTrue(out.contains("22: 0.0, 8.0") | out.contains("22: 0.0, 7.999999999")); - Assert.assertTrue(out.contains("23: 0.0, 9.0") | out.contains("23: 0.0, 8.999999999")); - Assert.assertTrue(out.contains("24: 0.0, 10.0") | out.contains("24: 0.0, 9.999999999")); - Assert.assertTrue(out.contains("25: 0.0, 10.0") | out.contains("25: 0.0, 9.999999999")); - Assert.assertTrue(out.contains("26: 0.0, 10.0") | out.contains("26: 0.0, 9.999999999")); + Assert.assertTrue(out.contains("14: 0.0, 0.0") || out.contains("14: 0.0, -0.0")); + Assert.assertTrue(out.contains("15: 0.0, 1.0") || out.contains("15: 0.0, 0.999999999")); + Assert.assertTrue(out.contains("16: 0.0, 2.0") || out.contains("16: 0.0, 1.999999999")); + Assert.assertTrue(out.contains("17: 0.0, 3.0") || out.contains("17: 0.0, 2.999999999")); + Assert.assertTrue(out.contains("18: 0.0, 4.0") || out.contains("18: 0.0, 3.999999999")); + Assert.assertTrue(out.contains("19: 0.0, 5.0") || out.contains("19: 0.0, 4.999999999")); + Assert.assertTrue(out.contains("20: 0.0, 6.0") || out.contains("20: 0.0, 5.999999999")); + Assert.assertTrue(out.contains("21: 0.0, 7.0") || out.contains("21: 0.0, 6.999999999")); + Assert.assertTrue(out.contains("22: 0.0, 8.0") || out.contains("22: 0.0, 7.999999999")); + Assert.assertTrue(out.contains("23: 0.0, 9.0") || out.contains("23: 0.0, 8.999999999")); + Assert.assertTrue(out.contains("24: 0.0, 10.0") || out.contains("24: 0.0, 9.999999999")); + Assert.assertTrue(out.contains("25: 0.0, 10.0") || out.contains("25: 0.0, 9.999999999")); + Assert.assertTrue(out.contains("26: 0.0, 10.0") || out.contains("26: 0.0, 9.999999999")); } } } From 80d198777c192c3520399a918046bb897537279e Mon Sep 17 00:00:00 2001 From: LiuMingYu <734904515@qq.com> Date: Tue, 23 Aug 2016 22:35:51 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E6=94=B9=E8=BF=9B=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E9=83=A8=E5=88=86=E7=9A=84=E6=96=87=E6=A1=A3=20=E6=9C=80?= =?UTF-8?q?=E8=BF=91=E5=9C=A8=E6=90=9E=E4=BF=9D=E7=A0=94=E6=9D=90=E6=96=99?= =?UTF-8?q?=20=E6=88=91=E4=BC=9A=E6=8A=93=E7=B4=A7=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E5=81=9A=E5=AE=8C=E5=89=A9=E4=BD=99=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 软件需求规格说明书.doc | Bin 103424 -> 327680 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/软件需求规格说明书.doc b/软件需求规格说明书.doc index c8af5bb6ffb8224b4fa1c8ab57c3a2d3e973f61f..1931f7f5d59d80a840895846c01c0d78aecbd019 100644 GIT binary patch literal 327680 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�@i&Q8jg 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 MR`B{Ar>gk>0NYy$oB#j- From 2bc998a290105e12b71cf44faf37766cc1bdc4b0 Mon Sep 17 00:00:00 2001 From: ALEX11 <438026067@qq.com> Date: Thu, 25 Aug 2016 10:00:27 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.projects/robocode.api/.markers | Bin 597 -> 0 bytes .../.projects/robocode.battle/.markers | Bin 933 -> 0 bytes .../.projects/robocode.core/.markers | Bin 677 -> 0 bytes .../.projects/robocode.host/.markers | Bin 2415 -> 0 bytes .../.projects/robocode.roborumble/.markers | Bin 293 -> 0 bytes .../.projects/robocode.ui.editor/.markers | Bin 1642 -> 0 bytes .../.projects/robocode.ui/.markers | Bin 1066 -> 0 bytes .../.safetable/org.eclipse.core.resources | Bin 1328 -> 0 bytes .../.settings/org.eclipse.jdt.launching.prefs | 2 - .../.settings/org.eclipse.rse.core.prefs | 4 - .../org.eclipse.e4.workbench/workbench.xmi | 2502 ----------------- .../externalLibsTimeStamps | Bin 972 -> 0 bytes .../org.eclipse.jdt.core/savedIndexNames.txt | 29 - .../variablesAndContainers.dat | Bin 19199 -> 0 bytes .../segments.gen | Bin 20 -> 0 bytes .../segments.gen | Bin 20 -> 0 bytes .../segments.gen | Bin 20 -> 0 bytes .../net/sf/robocode/dotnet/host/Module.java | 77 - .../sf/robocode/installer/AutoExtract.java | 382 --- .../test/robotscs/TestMaxTurnRate.java | 72 - .../sf/robocode/installer/AutoExtract.java | 389 --- .../sf/robocode/security/HiddenAccess.java | 290 -- .../battle/events/BattleEventDispatcher.java | 154 - .../net/sf/robocode/core/RobocodeMain.java | 414 --- .../java/net/sf/robocode/host/JavaHost.java | 192 -- .../sf/robocode/host/events/EventManager.java | 572 ---- .../host/proxies/HostingRobotProxy.java | 306 -- .../host/security/RobotClassLoader.java | 424 --- .../sf/robocode/installer/AutoExtract.java | 705 ----- .../roborumble/netengine/FileTransfer.java | 657 ----- .../main/java/tested/robots/AwtAttack.java | 84 - .../tested/robots/ConstructorAwtAttack.java | 68 - .../robots/ConstructorThreadAttack.java | 61 - .../main/java/tested/robots/FileAttack.java | 81 - .../tested/robots/IncludeNamespaceAttack.java | 45 - .../main/java/tested/robots/ThreadAttack.java | 87 - .../java/tested/robots/ThreadGroupAttack.java | 71 - .../main/java/tested/robots/UndeadThread.java | 44 - .../net/sf/robocode/test/helpers/Assert.java | 38 - .../net/sf/robocode/ui/editor/EditWindow.java | 485 ---- .../sf/robocode/ui/editor/WindowMenuItem.java | 291 -- .../net/sf/robocode/ui/WindowManager.java | 632 ----- .../robocode/ui/battle/AwtBattleAdaptor.java | 335 --- .../target/classes/gl4java/GLFont.class | Bin 259 -> 0 bytes .../target/classes/gl4java/GLFunc.class | Bin 259 -> 0 bytes .../classes/net/sf/robocode/api/Module.class | Bin 1817 -> 0 bytes .../sf/robocode/battle/IBattleManagerBase.class | Bin 374 -> 0 bytes .../net/sf/robocode/core/ContainerBase.class | Bin 707 -> 0 bytes .../classes/net/sf/robocode/core/IModule.class | Bin 234 -> 0 bytes .../sf/robocode/gui/IWindowManagerBase.class | Bin 179 -> 0 bytes .../classes/net/sf/robocode/io/FileUtil.class | Bin 6012 -> 0 bytes .../classes/net/sf/robocode/io/Logger.class | Bin 3569 -> 0 bytes .../net/sf/robocode/io/RobocodeProperties.class | Bin 1456 -> 0 bytes .../robocode/manager/IVersionManagerBase.class | Bin 281 -> 0 bytes .../net/sf/robocode/peer/IRobotStatics.class | Bin 234 -> 0 bytes .../repository/CodeSizeCalculator.class | Bin 2049 -> 0 bytes .../repository/IRepositoryManagerBase.class | Bin 337 -> 0 bytes .../sf/robocode/security/HiddenAccess$1.class | Bin 964 -> 0 bytes .../net/sf/robocode/security/HiddenAccess.class | Bin 11107 -> 0 bytes .../robocode/security/IHiddenBulletHelper.class | Bin 205 -> 0 bytes .../robocode/security/IHiddenEventHelper.class | Bin 516 -> 0 bytes .../robocode/security/IHiddenRulesHelper.class | Bin 198 -> 0 bytes .../security/IHiddenSpecificationHelper.class | Bin 648 -> 0 bytes .../robocode/security/IHiddenStatusHelper.class | Bin 211 -> 0 bytes .../robocode/security/IThreadManagerBase.class | Bin 301 -> 0 bytes .../sf/robocode/security/SafeComponent.class | Bin 531 -> 0 bytes .../serialization/ISerializableHelper.class | Bin 453 -> 0 bytes .../robocode/serialization/RbSerializer.class | Bin 16241 -> 0 bytes .../net/sf/robocode/util/StringUtil.class | Bin 1788 -> 0 bytes .../classes/net/sf/robocode/util/UrlUtil.class | Bin 661 -> 0 bytes .../target/classes/robocode/AdvancedRobot.class | Bin 10417 -> 0 bytes .../BattleEndedEvent$SerializableHelper.class | Bin 1957 -> 0 bytes .../classes/robocode/BattleEndedEvent.class | Bin 2413 -> 0 bytes .../BattleResults$SerializableHelper.class | Bin 2462 -> 0 bytes .../target/classes/robocode/BattleResults.class | Bin 3308 -> 0 bytes .../robocode/BattleRules$HiddenHelper.class | Bin 906 -> 0 bytes .../target/classes/robocode/BattleRules.class | Bin 1743 -> 0 bytes .../target/classes/robocode/BorderSentry.class | Bin 114 -> 0 bytes .../robocode/Bullet$HiddenBulletHelper.class | Bin 2776 -> 0 bytes .../target/classes/robocode/Bullet.class | Bin 3323 -> 0 bytes ...ulletHitBulletEvent$SerializableHelper.class | Bin 2027 -> 0 bytes .../classes/robocode/BulletHitBulletEvent.class | Bin 2086 -> 0 bytes .../BulletHitEvent$SerializableHelper.class | Bin 2215 -> 0 bytes .../classes/robocode/BulletHitEvent.class | Bin 2688 -> 0 bytes .../BulletMissedEvent$SerializableHelper.class | Bin 1714 -> 0 bytes .../classes/robocode/BulletMissedEvent.class | Bin 1858 -> 0 bytes .../target/classes/robocode/Condition.class | Bin 1728 -> 0 bytes .../target/classes/robocode/CustomEvent.class | Bin 2246 -> 0 bytes .../DeathEvent$SerializableHelper.class | Bin 1204 -> 0 bytes .../target/classes/robocode/DeathEvent.class | Bin 1666 -> 0 bytes .../target/classes/robocode/Droid.class | Bin 100 -> 0 bytes .../robocode/Event$HiddenEventHelper.class | Bin 1771 -> 0 bytes .../target/classes/robocode/Event.class | Bin 3512 -> 0 bytes .../robocode/GunTurnCompleteCondition.class | Bin 852 -> 0 bytes .../HitByBulletEvent$SerializableHelper.class | Bin 1925 -> 0 bytes .../classes/robocode/HitByBulletEvent.class | Bin 2836 -> 0 bytes .../HitRobotEvent$SerializableHelper.class | Bin 2148 -> 0 bytes .../target/classes/robocode/HitRobotEvent.class | Bin 3158 -> 0 bytes .../HitWallEvent$SerializableHelper.class | Bin 1516 -> 0 bytes .../target/classes/robocode/HitWallEvent.class | Bin 2038 -> 0 bytes .../JuniorRobot$InnerEventHandler.class | Bin 5223 -> 0 bytes .../target/classes/robocode/JuniorRobot.class | Bin 5817 -> 0 bytes .../target/classes/robocode/KeyEvent.class | Bin 546 -> 0 bytes .../KeyPressedEvent$SerializableHelper.class | Bin 2321 -> 0 bytes .../classes/robocode/KeyPressedEvent.class | Bin 1770 -> 0 bytes .../KeyReleasedEvent$SerializableHelper.class | Bin 2327 -> 0 bytes .../classes/robocode/KeyReleasedEvent.class | Bin 1776 -> 0 bytes .../KeyTypedEvent$SerializableHelper.class | Bin 2309 -> 0 bytes .../target/classes/robocode/KeyTypedEvent.class | Bin 1758 -> 0 bytes .../target/classes/robocode/MessageEvent.class | Bin 1810 -> 0 bytes .../MouseClickedEvent$SerializableHelper.class | Bin 2317 -> 0 bytes .../classes/robocode/MouseClickedEvent.class | Bin 1790 -> 0 bytes .../MouseDraggedEvent$SerializableHelper.class | Bin 2317 -> 0 bytes .../classes/robocode/MouseDraggedEvent.class | Bin 1790 -> 0 bytes .../MouseEnteredEvent$SerializableHelper.class | Bin 2317 -> 0 bytes .../classes/robocode/MouseEnteredEvent.class | Bin 1790 -> 0 bytes .../target/classes/robocode/MouseEvent.class | Bin 558 -> 0 bytes .../MouseExitedEvent$SerializableHelper.class | Bin 2311 -> 0 bytes .../classes/robocode/MouseExitedEvent.class | Bin 1784 -> 0 bytes .../MouseMovedEvent$SerializableHelper.class | Bin 2305 -> 0 bytes .../classes/robocode/MouseMovedEvent.class | Bin 1778 -> 0 bytes .../MousePressedEvent$SerializableHelper.class | Bin 2317 -> 0 bytes .../classes/robocode/MousePressedEvent.class | Bin 1790 -> 0 bytes .../MouseReleasedEvent$SerializableHelper.class | Bin 2323 -> 0 bytes .../classes/robocode/MouseReleasedEvent.class | Bin 1796 -> 0 bytes ...ouseWheelMovedEvent$SerializableHelper.class | Bin 2518 -> 0 bytes .../classes/robocode/MouseWheelMovedEvent.class | Bin 1885 -> 0 bytes .../robocode/MoveCompleteCondition.class | Bin 826 -> 0 bytes .../target/classes/robocode/PaintEvent.class | Bin 1417 -> 0 bytes .../robocode/RadarTurnCompleteCondition.class | Bin 842 -> 0 bytes .../classes/robocode/RateControlRobot.class | Bin 2212 -> 0 bytes .../target/classes/robocode/Robocode.class | Bin 461 -> 0 bytes .../robocode/RobocodeFileOutputStream.class | Bin 2271 -> 0 bytes .../classes/robocode/RobocodeFileWriter.class | Bin 958 -> 0 bytes .../target/classes/robocode/Robot.class | Bin 11677 -> 0 bytes .../RobotDeathEvent$SerializableHelper.class | Bin 1685 -> 0 bytes .../classes/robocode/RobotDeathEvent.class | Bin 2007 -> 0 bytes .../RobotStatus$SerializableHelper.class | Bin 3263 -> 0 bytes .../target/classes/robocode/RobotStatus.class | Bin 4731 -> 0 bytes .../RoundEndedEvent$SerializableHelper.class | Bin 1678 -> 0 bytes .../classes/robocode/RoundEndedEvent.class | Bin 2449 -> 0 bytes .../target/classes/robocode/Rules.class | Bin 1810 -> 0 bytes .../ScannedRobotEvent$SerializableHelper.class | Bin 2391 -> 0 bytes .../classes/robocode/ScannedRobotEvent.class | Bin 4955 -> 0 bytes .../SkippedTurnEvent$SerializableHelper.class | Bin 1546 -> 0 bytes .../classes/robocode/SkippedTurnEvent.class | Bin 2041 -> 0 bytes .../target/classes/robocode/StatusEvent.class | Bin 1540 -> 0 bytes .../target/classes/robocode/TeamRobot.class | Bin 1923 -> 0 bytes .../robocode/TurnCompleteCondition.class | Bin 822 -> 0 bytes .../robocode/WinEvent$SerializableHelper.class | Bin 1194 -> 0 bytes .../target/classes/robocode/WinEvent.class | Bin 1654 -> 0 bytes .../robocode/_AdvancedRadiansRobot.class | Bin 3320 -> 0 bytes .../classes/robocode/_AdvancedRobot.class | Bin 3356 -> 0 bytes .../target/classes/robocode/_Robot.class | Bin 2119 -> 0 bytes .../target/classes/robocode/_RobotBase.class | Bin 1636 -> 0 bytes .../robocode/annotation/SafeStatic.class | Bin 392 -> 0 bytes .../robocode/annotation/package-info.class | Bin 125 -> 0 bytes .../robocode/control/BattleSpecification.class | Bin 3929 -> 0 bytes .../control/BattlefieldSpecification.class | Bin 1023 -> 0 bytes .../robocode/control/IRobocodeEngine.class | Bin 715 -> 0 bytes .../robocode/control/RandomFactory.class | Bin 2740 -> 0 bytes .../control/RobocodeEngine$BattleObserver.class | Bin 2338 -> 0 bytes .../robocode/control/RobocodeEngine.class | Bin 7438 -> 0 bytes .../robocode/control/RobocodeListener.class | Bin 485 -> 0 bytes .../classes/robocode/control/RobotResults.class | Bin 3233 -> 0 bytes .../classes/robocode/control/RobotSetup.class | Bin 828 -> 0 bytes .../RobotSpecification$HiddenHelper.class | Bin 1962 -> 0 bytes .../robocode/control/RobotSpecification.class | Bin 3388 -> 0 bytes .../robocode/control/events/BattleAdaptor.class | Bin 2339 -> 0 bytes .../control/events/BattleCompletedEvent.class | Bin 1524 -> 0 bytes .../control/events/BattleErrorEvent.class | Bin 529 -> 0 bytes .../robocode/control/events/BattleEvent.class | Bin 310 -> 0 bytes .../control/events/BattleFinishedEvent.class | Bin 480 -> 0 bytes .../control/events/BattleMessageEvent.class | Bin 539 -> 0 bytes .../control/events/BattlePausedEvent.class | Bin 347 -> 0 bytes .../control/events/BattleResumedEvent.class | Bin 350 -> 0 bytes .../control/events/BattleStartedEvent.class | Bin 819 -> 0 bytes .../control/events/IBattleListener.class | Bin 951 -> 0 bytes .../control/events/RoundEndedEvent.class | Bin 721 -> 0 bytes .../control/events/RoundStartedEvent.class | Bin 745 -> 0 bytes .../control/events/TurnEndedEvent.class | Bin 606 -> 0 bytes .../control/events/TurnStartedEvent.class | Bin 344 -> 0 bytes .../robocode/control/events/package-info.class | Bin 129 -> 0 bytes .../classes/robocode/control/package-info.class | Bin 122 -> 0 bytes .../robocode/control/snapshot/BulletState.class | Bin 2000 -> 0 bytes .../control/snapshot/IBulletSnapshot.class | Bin 492 -> 0 bytes .../control/snapshot/IDebugProperty.class | Bin 194 -> 0 bytes .../control/snapshot/IRobotSnapshot.class | Bin 966 -> 0 bytes .../control/snapshot/IScoreSnapshot.class | Bin 853 -> 0 bytes .../control/snapshot/ITurnSnapshot.class | Bin 440 -> 0 bytes .../robocode/control/snapshot/RobotState.class | Bin 2019 -> 0 bytes .../control/snapshot/package-info.class | Bin 131 -> 0 bytes .../robocode/exception/AbortedException.class | Bin 519 -> 0 bytes .../robocode/exception/DeathException.class | Bin 513 -> 0 bytes .../robocode/exception/DisabledException.class | Bin 516 -> 0 bytes .../exception/EventInterruptedException.class | Bin 560 -> 0 bytes .../robocode/exception/RobotException.class | Bin 507 -> 0 bytes .../robocode/exception/WinException.class | Bin 501 -> 0 bytes .../robocode/exception/package-info.class | Bin 124 -> 0 bytes .../target/classes/robocode/package-info.class | Bin 114 -> 0 bytes .../classes/robocode/robocodeGL/EllipseGL.class | Bin 1490 -> 0 bytes .../classes/robocode/robocodeGL/LabelGL.class | Bin 523 -> 0 bytes .../classes/robocode/robocodeGL/LineGL.class | Bin 1030 -> 0 bytes .../classes/robocode/robocodeGL/PointGL.class | Bin 900 -> 0 bytes .../robocode/robocodeGL/RectangleGL.class | Bin 1497 -> 0 bytes .../robocode/robocodeGL/RenderElement.class | Bin 1077 -> 0 bytes .../robocode/robocodeGL/system/GLRenderer.class | Bin 595 -> 0 bytes .../robotinterfaces/IAdvancedEvents.class | Bin 245 -> 0 bytes .../robotinterfaces/IAdvancedRobot.class | Bin 260 -> 0 bytes .../robocode/robotinterfaces/IBasicEvents.class | Bin 711 -> 0 bytes .../robotinterfaces/IBasicEvents2.class | Bin 234 -> 0 bytes .../robotinterfaces/IBasicEvents3.class | Bin 233 -> 0 bytes .../robocode/robotinterfaces/IBasicRobot.class | Bin 371 -> 0 bytes .../robotinterfaces/IInteractiveEvents.class | Bin 513 -> 0 bytes .../robotinterfaces/IInteractiveRobot.class | Bin 272 -> 0 bytes .../robocode/robotinterfaces/IJuniorRobot.class | Bin 174 -> 0 bytes .../robocode/robotinterfaces/IPaintEvents.class | Bin 175 -> 0 bytes .../robocode/robotinterfaces/IPaintRobot.class | Bin 248 -> 0 bytes .../robocode/robotinterfaces/ITeamEvents.class | Bin 185 -> 0 bytes .../robocode/robotinterfaces/ITeamRobot.class | Bin 247 -> 0 bytes .../robocode/robotinterfaces/package-info.class | Bin 130 -> 0 bytes .../peer/IAdvancedRobotPeer.class | Bin 1784 -> 0 bytes .../robotinterfaces/peer/IBasicRobotPeer.class | Bin 1167 -> 0 bytes .../robotinterfaces/peer/IJuniorRobotPeer.class | Bin 226 -> 0 bytes .../peer/IStandardRobotPeer.class | Bin 377 -> 0 bytes .../robotinterfaces/peer/ITeamRobotPeer.class | Bin 582 -> 0 bytes .../robotinterfaces/peer/package-info.class | Bin 135 -> 0 bytes .../target/classes/robocode/util/Utils.class | Bin 1855 -> 0 bytes .../classes/robocode/util/package-info.class | Bin 119 -> 0 bytes .../robocode.content/target/classes/ReadMe.html | 233 -- .../robocode.content/target/classes/ReadMe.txt | 471 ---- .../target/classes/battles/intro.battle | 8 - .../target/classes/battles/sample.battle | 8 - .../target/classes/desktop/robocode.png | Bin 3918 -> 0 bytes .../classes/desktop/robocodeMeleeRumble.desktop | 9 - .../classes/desktop/robocodeRoboRumble.desktop | 9 - .../classes/desktop/robocodeRobocode.desktop | 9 - .../classes/desktop/robocodeTeamRumble.desktop | 9 - .../classes/desktop/robocodeTwinDuel.desktop | 9 - .../target/classes/desktop/roborumble.png | Bin 3401 -> 0 bytes .../target/classes/license/epl-v10.html | 188 -- .../target/classes/meleerumble.bat | 9 - .../target/classes/meleerumble.command | 13 - .../target/classes/meleerumble.sh | 13 - .../target/classes/robocode.bat | 9 - .../target/classes/robocode.command | 13 - .../target/classes/robocode.ico | Bin 370070 -> 0 bytes .../robocode.content/target/classes/robocode.sh | 13 - .../target/classes/roborumble.bat | 9 - .../target/classes/roborumble.command | 13 - .../target/classes/roborumble.ico | Bin 32038 -> 0 bytes .../target/classes/roborumble.sh | 13 - .../target/classes/roborumble/meleerumble.txt | 244 -- .../classes/roborumble/roborumble.properties | 6 - .../target/classes/roborumble/roborumble.txt | 241 -- .../target/classes/roborumble/teamrumble.txt | 203 -- .../target/classes/roborumble/twinduel.txt | 203 -- .../target/classes/teamrumble.bat | 9 - .../target/classes/teamrumble.command | 13 - .../target/classes/teamrumble.sh | 13 - .../target/classes/templates/newjavafile.tpt | 8 - .../target/classes/templates/newjuniorrobot.tpt | 54 - .../target/classes/templates/newrobot.tpt | 56 - .../editor/Robocode Black Theme.properties | 23 - .../editor/Robocode White Theme.properties | 23 - .../target/classes/twinduel.bat | 9 - .../target/classes/twinduel.command | 13 - .../robocode.content/target/classes/twinduel.sh | 13 - .../sf/robocode/installer/AutoExtract$1.class | Bin 877 -> 0 bytes .../net/sf/robocode/installer/AutoExtract.class | Bin 21469 -> 0 bytes .../target/classes/sample/Corners.class | Bin 2603 -> 0 bytes .../target/classes/sample/Corners.properties | 9 - .../target/classes/sample/Crazy.class | Bin 1729 -> 0 bytes .../target/classes/sample/Crazy.properties | 9 - .../target/classes/sample/Fire.class | Bin 1739 -> 0 bytes .../target/classes/sample/Fire.properties | 9 - .../target/classes/sample/Interactive.class | Bin 3111 -> 0 bytes .../classes/sample/Interactive.properties | 9 - .../sample/Interactive_v2$Direction.class | Bin 1205 -> 0 bytes .../target/classes/sample/Interactive_v2.class | Bin 4106 -> 0 bytes .../classes/sample/Interactive_v2.properties | 8 - .../classes/sample/MyFirstJuniorRobot.class | Bin 871 -> 0 bytes .../sample/MyFirstJuniorRobot.properties | 9 - .../target/classes/sample/MyFirstRobot.class | Bin 923 -> 0 bytes .../classes/sample/MyFirstRobot.properties | 9 - .../target/classes/sample/PaintingRobot.class | Bin 2379 -> 0 bytes .../classes/sample/PaintingRobot.properties | 10 - .../target/classes/sample/RamFire.class | Bin 1544 -> 0 bytes .../target/classes/sample/RamFire.properties | 9 - .../target/classes/sample/SittingDuck.class | Bin 2440 -> 0 bytes .../target/classes/sample/SittingDuck.html | 24 - .../classes/sample/SittingDuck.properties | 9 - .../target/classes/sample/SpinBot.class | Bin 1264 -> 0 bytes .../target/classes/sample/SpinBot.properties | 9 - .../target/classes/sample/Target$1.class | Bin 684 -> 0 bytes .../target/classes/sample/Target.class | Bin 1626 -> 0 bytes .../target/classes/sample/Target.properties | 9 - .../target/classes/sample/TrackFire.class | Bin 1528 -> 0 bytes .../target/classes/sample/TrackFire.properties | 9 - .../target/classes/sample/Tracker.class | Bin 2793 -> 0 bytes .../target/classes/sample/Tracker.properties | 9 - .../target/classes/sample/VelociRobot.class | Bin 1187 -> 0 bytes .../classes/sample/VelociRobot.properties | 9 - .../target/classes/sample/Walls.class | Bin 1596 -> 0 bytes .../target/classes/sample/Walls.properties | 9 - .../target/classes/sample/pandafighter.class | Bin 4510 -> 0 bytes .../target/classes/sample/pandafighter.java | 149 - .../target/classes/sampleex/Alien.class | Bin 3054 -> 0 bytes .../target/classes/sampleex/Alien.properties | 9 - .../AlienComposition$AlienEventHandler.class | Bin 2403 -> 0 bytes .../sampleex/AlienComposition$AlienMain.class | Bin 867 -> 0 bytes .../classes/sampleex/AlienComposition.class | Bin 1466 -> 0 bytes .../target/classes/sampleex/GreyEminence.class | Bin 1111 -> 0 bytes .../classes/sampleex/MasterAndSlave.class | Bin 2086 -> 0 bytes .../classes/sampleex/MasterAndSlave.properties | 9 - .../target/classes/sampleex/MasterBase.class | Bin 2218 -> 0 bytes .../classes/sampleex/ProxyOfGreyEminence.class | Bin 881 -> 0 bytes .../sampleex/ProxyOfGreyEminence.properties | 9 - .../target/classes/sampleex/RegullarMonk.class | Bin 279 -> 0 bytes .../target/classes/sampleex/Slave.class | Bin 817 -> 0 bytes .../samplesentry/BorderGuard$RobotData.class | Bin 1762 -> 0 bytes .../classes/samplesentry/BorderGuard.class | Bin 9295 -> 0 bytes .../classes/samplesentry/BorderGuard.properties | 9 - .../classes/sampleteam/MyFirstDroid.class | Bin 1691 -> 0 bytes .../classes/sampleteam/MyFirstLeader.class | Bin 2363 -> 0 bytes .../target/classes/sampleteam/MyFirstTeam.team | 7 - .../target/classes/sampleteam/Point.class | Bin 612 -> 0 bytes .../target/classes/sampleteam/RobotColors.class | Bin 493 -> 0 bytes ...ngNameIWouldSayTooLongMaybeEventLonger.class | Bin 603 -> 0 bytes .../target/classes/NoPackageShortName.class | Bin 483 -> 0 bytes .../target/classes/robocode/BadNamespace.class | Bin 483 -> 0 bytes .../target/classes/tested/robots/Ahead.class | Bin 382 -> 0 bytes .../classes/tested/robots/AwtAttack$1.class | Bin 790 -> 0 bytes .../classes/tested/robots/AwtAttack.class | Bin 1910 -> 0 bytes .../classes/tested/robots/BadFirePower.class | Bin 1100 -> 0 bytes .../classes/tested/robots/BattleLost.class | Bin 1083 -> 0 bytes .../classes/tested/robots/BattleWin.class | Bin 1693 -> 0 bytes .../classes/tested/robots/BodyTurnRate.class | Bin 1757 -> 0 bytes .../tested/robots/ConstructorAwtAttack$1.class | Bin 856 -> 0 bytes .../tested/robots/ConstructorAwtAttack.class | Bin 1613 -> 0 bytes .../tested/robots/ConstructorHttpAttack.class | Bin 1101 -> 0 bytes .../robots/ConstructorReflectionAttack.class | Bin 1803 -> 0 bytes .../tested/robots/ConstructorSocketAttack.class | Bin 1992 -> 0 bytes .../ConstructorThreadAttack$Attacker.class | Bin 1188 -> 0 bytes .../tested/robots/ConstructorThreadAttack.class | Bin 1577 -> 0 bytes .../classes/tested/robots/CustomEvents$1.class | Bin 688 -> 0 bytes .../classes/tested/robots/CustomEvents$2.class | Bin 688 -> 0 bytes .../classes/tested/robots/CustomEvents$3.class | Bin 766 -> 0 bytes .../classes/tested/robots/CustomEvents.class | Bin 1762 -> 0 bytes .../tested/robots/DecelerationCaveat1.class | Bin 585 -> 0 bytes .../tested/robots/DecelerationCaveat2.class | Bin 586 -> 0 bytes .../tested/robots/DecelerationCaveat3.class | Bin 599 -> 0 bytes .../target/classes/tested/robots/DieFast.class | Bin 386 -> 0 bytes .../classes/tested/robots/EnvAttack.class | Bin 644 -> 0 bytes .../tested/robots/EventPriorityFilter.class | Bin 931 -> 0 bytes .../target/classes/tested/robots/FairPlay.class | Bin 941 -> 0 bytes .../classes/tested/robots/FileAttack.class | Bin 1889 -> 0 bytes .../tested/robots/FileOutputStreamAttack.class | Bin 1214 -> 0 bytes .../classes/tested/robots/FileWriteSize.class | Bin 2098 -> 0 bytes .../target/classes/tested/robots/GunHeat.class | Bin 956 -> 0 bytes .../classes/tested/robots/GunTurnRate.class | Bin 1609 -> 0 bytes .../classes/tested/robots/HttpAttack.class | Bin 1118 -> 0 bytes .../tested/robots/IncludeNamespaceAttack.class | Bin 1111 -> 0 bytes .../tested/robots/InteruptibleEvent.class | Bin 1134 -> 0 bytes .../classes/tested/robots/JuniorEvents.class | Bin 5577 -> 0 bytes .../classes/tested/robots/MaxTurnRate.class | Bin 1381 -> 0 bytes .../classes/tested/robots/MaxVelocity.class | Bin 1356 -> 0 bytes .../tested/robots/PrivateConstructor.class | Bin 309 -> 0 bytes .../robots/RadarTurnRateAndSetAdjust.class | Bin 2151 -> 0 bytes .../target/classes/tested/robots/Random.class | Bin 576 -> 0 bytes .../classes/tested/robots/RateControl.class | Bin 886 -> 0 bytes .../tested/robots/ReflectionAttack.class | Bin 1350 -> 0 bytes .../tested/robots/ReverseDirection.class | Bin 675 -> 0 bytes .../tested/robots/RobotDeathEvents.class | Bin 974 -> 0 bytes .../classes/tested/robots/SkipTurns.class | Bin 1733 -> 0 bytes .../classes/tested/robots/SocketAttack.class | Bin 1613 -> 0 bytes .../target/classes/tested/robots/TestTeam.team | 7 - .../tested/robots/ThreadAttack$Attacker.class | Bin 1589 -> 0 bytes .../classes/tested/robots/ThreadAttack.class | Bin 2124 -> 0 bytes .../tested/robots/ThreadGroupAttack$1.class | Bin 1125 -> 0 bytes .../tested/robots/ThreadGroupAttack.class | Bin 1967 -> 0 bytes .../TooLongNameThisIsReallyTooLongName.class | Bin 559 -> 0 bytes .../classes/tested/robots/UndeadThread.class | Bin 937 -> 0 bytes .../classes/tested/robots/WatchBullets.class | Bin 2194 -> 0 bytes .../TooLongNamespace.class | Bin 567 -> 0 bytes 文档/软件需求规格说明书郭禹良版本0.3.doc | Bin 334848 -> 0 bytes 软件需求规格说明书.doc | Bin 327680 -> 0 bytes 387 files changed, 12049 deletions(-) delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.api/.markers delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.battle/.markers delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.core/.markers delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.host/.markers delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.roborumble/.markers delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.ui.editor/.markers delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.ui/.markers delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.core.prefs delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/1a42e2ddbdd28c4e903ebde7bafa5867/segments.gen delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/26522e0d83a422eed93329ece7565cfc/segments.gen delete mode 100644 workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen delete mode 100644 workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/Module.java delete mode 100644 workspace_robo4/plugins/dotnet/robocode.dotnet.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java delete mode 100644 workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java delete mode 100644 workspace_robo4/plugins/testing/robocode.testing.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java delete mode 100644 workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/HiddenAccess.java delete mode 100644 workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/events/BattleEventDispatcher.java delete mode 100644 workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMain.java delete mode 100644 workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/JavaHost.java delete mode 100644 workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventManager.java delete mode 100644 workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/HostingRobotProxy.java delete mode 100644 workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotClassLoader.java delete mode 100644 workspace_robo4/robocode.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java delete mode 100644 workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/FileTransfer.java delete mode 100644 workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/AwtAttack.java delete mode 100644 workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorAwtAttack.java delete mode 100644 workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorThreadAttack.java delete mode 100644 workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileAttack.java delete mode 100644 workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/IncludeNamespaceAttack.java delete mode 100644 workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadAttack.java delete mode 100644 workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadGroupAttack.java delete mode 100644 workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/UndeadThread.java delete mode 100644 workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/Assert.java delete mode 100644 workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditWindow.java delete mode 100644 workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/WindowMenuItem.java delete mode 100644 workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/WindowManager.java delete mode 100644 workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battle/AwtBattleAdaptor.java delete mode 100644 代码/robocode/robocode.api/target/classes/gl4java/GLFont.class delete mode 100644 代码/robocode/robocode.api/target/classes/gl4java/GLFunc.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/api/Module.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/battle/IBattleManagerBase.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/core/ContainerBase.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/core/IModule.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/gui/IWindowManagerBase.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/io/FileUtil.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/io/Logger.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/io/RobocodeProperties.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/manager/IVersionManagerBase.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/peer/IRobotStatics.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/repository/CodeSizeCalculator.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/repository/IRepositoryManagerBase.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/security/HiddenAccess$1.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/security/HiddenAccess.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenBulletHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenEventHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenRulesHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenSpecificationHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenStatusHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IThreadManagerBase.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/security/SafeComponent.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/serialization/ISerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/serialization/RbSerializer.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/util/StringUtil.class delete mode 100644 代码/robocode/robocode.api/target/classes/net/sf/robocode/util/UrlUtil.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/AdvancedRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BattleEndedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BattleEndedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BattleResults$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BattleResults.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BattleRules$HiddenHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BattleRules.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BorderSentry.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/Bullet$HiddenBulletHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/Bullet.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BulletHitBulletEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BulletHitBulletEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BulletHitEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BulletHitEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BulletMissedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/BulletMissedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/Condition.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/CustomEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/DeathEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/DeathEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/Droid.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/Event$HiddenEventHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/Event.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/GunTurnCompleteCondition.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/HitByBulletEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/HitByBulletEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/HitRobotEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/HitRobotEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/HitWallEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/HitWallEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/JuniorRobot$InnerEventHandler.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/JuniorRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/KeyEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/KeyPressedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/KeyPressedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/KeyReleasedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/KeyReleasedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/KeyTypedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/KeyTypedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MessageEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseClickedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseClickedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseDraggedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseDraggedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseEnteredEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseEnteredEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseExitedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseExitedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseMovedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseMovedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MousePressedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MousePressedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseReleasedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseReleasedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseWheelMovedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MouseWheelMovedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/MoveCompleteCondition.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/PaintEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RadarTurnCompleteCondition.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RateControlRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/Robocode.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RobocodeFileOutputStream.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RobocodeFileWriter.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/Robot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RobotDeathEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RobotDeathEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RobotStatus$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RobotStatus.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RoundEndedEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/RoundEndedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/Rules.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/ScannedRobotEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/ScannedRobotEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/SkippedTurnEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/SkippedTurnEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/StatusEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/TeamRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/TurnCompleteCondition.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/WinEvent$SerializableHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/WinEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/_AdvancedRadiansRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/_AdvancedRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/_Robot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/_RobotBase.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/annotation/SafeStatic.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/annotation/package-info.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/BattleSpecification.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/BattlefieldSpecification.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/IRobocodeEngine.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/RandomFactory.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/RobocodeEngine$BattleObserver.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/RobocodeEngine.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/RobocodeListener.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/RobotResults.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/RobotSetup.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/RobotSpecification$HiddenHelper.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/RobotSpecification.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/BattleAdaptor.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/BattleCompletedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/BattleErrorEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/BattleEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/BattleFinishedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/BattleMessageEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/BattlePausedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/BattleResumedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/BattleStartedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/IBattleListener.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/RoundEndedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/RoundStartedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/TurnEndedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/TurnStartedEvent.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/events/package-info.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/package-info.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/snapshot/BulletState.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/snapshot/IBulletSnapshot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/snapshot/IDebugProperty.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/snapshot/IRobotSnapshot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/snapshot/IScoreSnapshot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/snapshot/ITurnSnapshot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/snapshot/RobotState.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/control/snapshot/package-info.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/exception/AbortedException.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/exception/DeathException.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/exception/DisabledException.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/exception/EventInterruptedException.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/exception/RobotException.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/exception/WinException.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/exception/package-info.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/package-info.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robocodeGL/EllipseGL.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robocodeGL/LabelGL.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robocodeGL/LineGL.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robocodeGL/PointGL.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robocodeGL/RectangleGL.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robocodeGL/RenderElement.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robocodeGL/system/GLRenderer.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IAdvancedEvents.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IAdvancedRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicEvents.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicEvents2.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicEvents3.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IInteractiveEvents.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IInteractiveRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IJuniorRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IPaintEvents.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IPaintRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/ITeamEvents.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/ITeamRobot.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/package-info.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/IAdvancedRobotPeer.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/IBasicRobotPeer.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/IJuniorRobotPeer.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/IStandardRobotPeer.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/ITeamRobotPeer.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/package-info.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/util/Utils.class delete mode 100644 代码/robocode/robocode.api/target/classes/robocode/util/package-info.class delete mode 100644 代码/robocode/robocode.content/target/classes/ReadMe.html delete mode 100644 代码/robocode/robocode.content/target/classes/ReadMe.txt delete mode 100644 代码/robocode/robocode.content/target/classes/battles/intro.battle delete mode 100644 代码/robocode/robocode.content/target/classes/battles/sample.battle delete mode 100644 代码/robocode/robocode.content/target/classes/desktop/robocode.png delete mode 100644 代码/robocode/robocode.content/target/classes/desktop/robocodeMeleeRumble.desktop delete mode 100644 代码/robocode/robocode.content/target/classes/desktop/robocodeRoboRumble.desktop delete mode 100644 代码/robocode/robocode.content/target/classes/desktop/robocodeRobocode.desktop delete mode 100644 代码/robocode/robocode.content/target/classes/desktop/robocodeTeamRumble.desktop delete mode 100644 代码/robocode/robocode.content/target/classes/desktop/robocodeTwinDuel.desktop delete mode 100644 代码/robocode/robocode.content/target/classes/desktop/roborumble.png delete mode 100644 代码/robocode/robocode.content/target/classes/license/epl-v10.html delete mode 100644 代码/robocode/robocode.content/target/classes/meleerumble.bat delete mode 100644 代码/robocode/robocode.content/target/classes/meleerumble.command delete mode 100644 代码/robocode/robocode.content/target/classes/meleerumble.sh delete mode 100644 代码/robocode/robocode.content/target/classes/robocode.bat delete mode 100644 代码/robocode/robocode.content/target/classes/robocode.command delete mode 100644 代码/robocode/robocode.content/target/classes/robocode.ico delete mode 100644 代码/robocode/robocode.content/target/classes/robocode.sh delete mode 100644 代码/robocode/robocode.content/target/classes/roborumble.bat delete mode 100644 代码/robocode/robocode.content/target/classes/roborumble.command delete mode 100644 代码/robocode/robocode.content/target/classes/roborumble.ico delete mode 100644 代码/robocode/robocode.content/target/classes/roborumble.sh delete mode 100644 代码/robocode/robocode.content/target/classes/roborumble/meleerumble.txt delete mode 100644 代码/robocode/robocode.content/target/classes/roborumble/roborumble.properties delete mode 100644 代码/robocode/robocode.content/target/classes/roborumble/roborumble.txt delete mode 100644 代码/robocode/robocode.content/target/classes/roborumble/teamrumble.txt delete mode 100644 代码/robocode/robocode.content/target/classes/roborumble/twinduel.txt delete mode 100644 代码/robocode/robocode.content/target/classes/teamrumble.bat delete mode 100644 代码/robocode/robocode.content/target/classes/teamrumble.command delete mode 100644 代码/robocode/robocode.content/target/classes/teamrumble.sh delete mode 100644 代码/robocode/robocode.content/target/classes/templates/newjavafile.tpt delete mode 100644 代码/robocode/robocode.content/target/classes/templates/newjuniorrobot.tpt delete mode 100644 代码/robocode/robocode.content/target/classes/templates/newrobot.tpt delete mode 100644 代码/robocode/robocode.content/target/classes/theme/editor/Robocode Black Theme.properties delete mode 100644 代码/robocode/robocode.content/target/classes/theme/editor/Robocode White Theme.properties delete mode 100644 代码/robocode/robocode.content/target/classes/twinduel.bat delete mode 100644 代码/robocode/robocode.content/target/classes/twinduel.command delete mode 100644 代码/robocode/robocode.content/target/classes/twinduel.sh delete mode 100644 代码/robocode/robocode.installer/target/classes/net/sf/robocode/installer/AutoExtract$1.class delete mode 100644 代码/robocode/robocode.installer/target/classes/net/sf/robocode/installer/AutoExtract.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Corners.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Corners.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Crazy.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Crazy.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Fire.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Fire.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Interactive.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Interactive.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Interactive_v2$Direction.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Interactive_v2.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Interactive_v2.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/MyFirstJuniorRobot.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/MyFirstJuniorRobot.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/MyFirstRobot.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/MyFirstRobot.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/PaintingRobot.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/PaintingRobot.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/RamFire.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/RamFire.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/SittingDuck.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/SittingDuck.html delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/SittingDuck.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/SpinBot.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/SpinBot.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Target$1.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Target.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Target.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/TrackFire.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/TrackFire.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Tracker.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Tracker.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/VelociRobot.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/VelociRobot.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Walls.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/Walls.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/pandafighter.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sample/pandafighter.java delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/Alien.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/Alien.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/AlienComposition$AlienEventHandler.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/AlienComposition$AlienMain.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/AlienComposition.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/GreyEminence.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/MasterAndSlave.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/MasterAndSlave.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/MasterBase.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/ProxyOfGreyEminence.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/ProxyOfGreyEminence.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/RegullarMonk.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleex/Slave.class delete mode 100644 代码/robocode/robocode.samples/target/classes/samplesentry/BorderGuard$RobotData.class delete mode 100644 代码/robocode/robocode.samples/target/classes/samplesentry/BorderGuard.class delete mode 100644 代码/robocode/robocode.samples/target/classes/samplesentry/BorderGuard.properties delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleteam/MyFirstDroid.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleteam/MyFirstLeader.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleteam/MyFirstTeam.team delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleteam/Point.class delete mode 100644 代码/robocode/robocode.samples/target/classes/sampleteam/RobotColors.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLonger.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/NoPackageShortName.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/robocode/BadNamespace.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/Ahead.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/AwtAttack$1.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/AwtAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/BadFirePower.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/BattleLost.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/BattleWin.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/BodyTurnRate.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorAwtAttack$1.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorAwtAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorHttpAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorReflectionAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorSocketAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorThreadAttack$Attacker.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorThreadAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/CustomEvents$1.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/CustomEvents$2.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/CustomEvents$3.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/CustomEvents.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/DecelerationCaveat1.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/DecelerationCaveat2.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/DecelerationCaveat3.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/DieFast.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/EnvAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/EventPriorityFilter.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/FairPlay.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/FileAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/FileOutputStreamAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/FileWriteSize.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/GunHeat.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/GunTurnRate.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/HttpAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/IncludeNamespaceAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/InteruptibleEvent.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/JuniorEvents.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/MaxTurnRate.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/MaxVelocity.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/PrivateConstructor.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/RadarTurnRateAndSetAdjust.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/Random.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/RateControl.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ReflectionAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ReverseDirection.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/RobotDeathEvents.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/SkipTurns.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/SocketAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/TestTeam.team delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadAttack$Attacker.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadGroupAttack$1.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadGroupAttack.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/TooLongNameThisIsReallyTooLongName.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/UndeadThread.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tested/robots/WatchBullets.class delete mode 100644 代码/robocode/robocode.tests.robots/target/classes/tooLongNamespaceThisIsReallyTooLongNamespace/TooLongNamespace.class delete mode 100644 文档/软件需求规格说明书郭禹良版本0.3.doc delete mode 100644 软件需求规格说明书.doc diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.api/.markers b/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.api/.markers deleted file mode 100644 index cf728b1c9fd1074507ba4551cd70d4804fffd6a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 597 zcma)&!Ac`R5QZz0L$c!0i?`Yrn0W*djG~}fvSA70rKY<~I?i;5s+vfi#N+xb!oJaZ zw?{$5gV@l}#s63H{~rJh;i!^SCzm{zv77TIC&QO^>QlklPljKK}1vQF}6>IKSoiJH8)jRB)m_iYJfiQT2@kT@^|sRoB)mz2OE%y@$vok2s2l@8Nj<_X6>qv2_3d diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.battle/.markers b/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.battle/.markers deleted file mode 100644 index b8400f51d9432364cd49f6e5760f2348385de1b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 933 zcmbW#v5wO~5C-5$f^-2P?wTv;rUL}BJCG34HFrn>K}as5qgZ<<@m}m*Yj>Qx(7_w< z1n>$x0TK-_K@BBu0L(gYib7*y$@Y%?@5uf<05E{3sdt&nou(vH%q6A4=V_&kP0!Ry zrIt7i^UF}`DR*8QyGW<)>Y1`?K|YCL0O-jXj~jis>HH$0yfk&7tt9haPDJ#!X?|*}9rLpw9sWS30@DBE3;KXXF z4j#buCXheThE-OQeAqC!#^*HB0~kCxo=L}-AKw3*z~oY=8{uDPtLjiVPN(t%`1DV; z3%S1$-4?qa#UA2gbAeo#fWgUKF)oPPRwJwF;`SYsNAd+)TmqBQ-B=Dk?y`K@W;y)c zk>wMN{*R?5@*9#DvfAZ1_?N?OIL5YIqtY5_C1Vrf2*t^ctB9jKp(@Raj_@u{sd6$p wc|rLypqWdAu(gY5Z45J-%e=;pGVE=jZG6;?@y(AN#w%a98Q;F@#`x>eZ&+g;5C8xG diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.core/.markers b/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.core/.markers deleted file mode 100644 index 5a5ffb364aadf7e284c9289c6dbcdd895a5ff043..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 677 zcmb`Du};G<5QeV_QVL>aU?K}!6+Z*e3R}zpx;&Q%J>c~s5!oW+g@>sAC zx2Tj(8L(v8mVckW?*Jf%fgqPV5eiRA6w;JpCKpna$ih!H5#f>9lv6Kmel|l{ z$|+J7(g4t^XBbfg$Bw2MDr@E*vzg{q`HZE1fHourdS5?`;dDIej?%lc;i!`mPNZT- zoz%~*;WS^Sh0~Qq50TMP3at-l&&fD4yo~B^TClI~CEc(juFvr!99UE0byeg@A#ego z2=q!FuAkws@<=^xSmqXM*tT~SDeUVQ;z4&@SG;|F`7Gdaquit`xn#B|`sb^4rzHU+ wjCkFfZTF*<`>!=&;TG7;HL<&{7u&AMQ#04Et2G_${WIR%E?(~s-g{HLZ{Y2{K>z>% diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.host/.markers b/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.host/.markers deleted file mode 100644 index 9af950237546736e4e997007c92f4f515903c7dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2415 zcmd6oKW`H;7{;B1khGLCF|eQ)3223?JBg76sWb=zwCP_WHs|~%aeHS+w$qXsHWtLl z0DKn2zz1MrV&*G=5U=y6N-wJ9c7f9+C;RN^eSUtQCycQY+l!5E=|l^Ry4t$fnk3G+ zRPjDP!n88<1))V0Y`Og|^WdC_Dm#J#D4aW&lQOXIDUIwd9~p zzl#odOZVwJP3dh*JD>^-v}KBx6{RQwD|}|vo{`#D?aL~#xuna@w&TXpcuww$ac~#(jD9K6 z#*e6Lr0V!ya1EL}KK~H}#wxQk8qH=CwlG7_8=QuIPjH9ex(LyFZ3hm~Sg92pbx|P= zfD<^bItbE2#sw|aw3-G<%B{T-#;bfi$BW&Z=2cc*wdS%B@UJr&axbXjSsG zPPn4{JdjqMZJwPLIhgLa&JEoZ1`o7SWEbj*NxV$jYi<_UvNzj3*c~^O9%jg-rG}xh z(L+^VdlJ?*#r-^ptJ7^$d>06!$|In;-t z<4xtm&|7C@CW_OPCn!b%OPqm%X_QAkVtLz<<0ztzIQh#UIa7p@T6~))^=g{b;`cyO z=|~d0bebk#obIOrS_mDjg^z==s$t<28~)klhX^g%AzVN?;ULpOwk0X|aTBQNM_$wG zX-!w|1Z%3F-3F9>%GtQ)AGvd%^#8&vqkj~y#rJtqCw=lWkklKtdUjI&Z|D?4muCrG W@XiQ3|LT{#s>byBSHA|T`tTRm(Z%@y diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.roborumble/.markers b/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.roborumble/.markers deleted file mode 100644 index bd2015536ca5f69e68e22c2cc2c2046a0800b654..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293 zcmXYs!A`?442IqIu!1Hbj@rt#>;W`_qn68}P*nD)qA%T4g4GXMZZ>Rjg~ zTm;@~GK1U4BwNuYFloW~0yWG$#fV#~;BvEGuCG)}J{(BB_B5&-K$P@MXw~B3Ns05M z434TJ3pg=7@}nS2+Rwh=bZ{fxr>w*o5SV3PHQFry hzKkCe{b= z#upH8?6dU3Yahi6AHbO=mSjU9abN>s4%y%Lz*&Xc?IS87@<)Ixt8i;bYt50xh(S&VZ*WxGS`qtSsX)u+lke z^o-O-(rMYfvBa*3gq!!o4Y}{N9d^~vzs<7V9Bb#s0d_mU4?`+ezk8iY3Mx zR_8|GUR+_7{jHY!#Sdp^^Kt zUltUyJT2tuFcAlyR1yfS+Om@y|2Kid#ZQDP21*co0-=ki18rg(%n(orM)hk^z`Y3p z=L-s0nHKP9C}3B1lGHr}8B(I-QId~F8wW4m?adkH>dzwc{R!sZ3o_rFW?n8btBb{% zcipOgii8iw32RFW60S}YJ{iU0!b?!xH3)DQgrT`E%6%<3Nv*8Uex%cQPIqh9itNn^ z_Lpd#+>sz%c$fU5_oUtf{%4)0@ZFxR!OXGMxTN>B@0tdIdt^fc4 diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.ui/.markers b/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.ui/.markers deleted file mode 100644 index f4be5ab1765d8630bddc8ebfd4f2c9c95573b324..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1066 zcmb7@!D`z;5QfK6O`OuE(4>LV%l4LBBzkQRh2k`%hseYx_!JoLj-_p-U9r2e$i01y zkoV}J&{rzt5NPSjae}Zf%3OqYM#J|lzW^YFxF zn)VxbR#`GfLOPt~)B_k;T^UX%B82eEaN;+fUtjlsu4s4tgs(Q%c!|ZavQnk2^cR#< zVOgD#VjT0F1e+UOu#qPxLyD6?rqlO)h-WmK%*8DYv&N z_o9(|&(2nt{;?a_#bO=odmHTHM`y5;hdezdaHmv%Lg#WCE(3TUxh5Y?z1s8)r_*US zxBj0sH+a`}>)&*AyS-z9{Y{u;nJA%IO+M~ELYJ&Y<(Shf!v!&yNz2~)q?KfxBpapV i?&CyQj5A$N{ImJ(oIN=F&`oUj*SgqMTWoKqtJr@^At?O- diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources b/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources deleted file mode 100644 index 4683b6c30c08e4b3d5abdcb528870a568ae6ba9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1328 zcmZ?R*xjhShe1S2b=vdAllRFf=Oz}Hq!uZZBqrsg@^UHr=I1FmmZmEh87UZ8SQ#2v znHnoN2Ztya85o-JawX@aCKkD*=9DDH=NF~xr6%WO78IxIrKBd6rt2l=7p2;!CFT?Z z&C%B@DN0SXHNvSSw=$4gIJ;P{G!v!`hxu74B`BujP*#$fn5&muR!ofA^5PP` zvc#Osl*E$E{5%5o7o?=>B^G4rmE`B=6cbPja%)avXZ3-yJTq_DPi@?^Q z1RlsGS;a6P8k(3JnwlG%8(CNw0YeX;MtG=z^jH{~n3)=z85!dY@giVEAx9C8Km;jE u%gjk7B3eMfLWGH^9)u>40};PJgVSN)=bq}_<;NUG(\r\n\r\n\r\n\r\n\r\n\r\n diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.core.prefs b/workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.core.prefs deleted file mode 100644 index 0a60e67..0000000 --- a/workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeuserprofiles=DESKTOP-SHKMAML;Team -eclipse.preferences.version=1 -org.eclipse.rse.systemtype.local.systemType.defaultUserId=Terrans Force -useridperkey=DESKTOP-SHKMAML.Local\=Terrans Force; diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi b/workspace_robo4/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi deleted file mode 100644 index 8c2319f..0000000 --- a/workspace_robo4/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi +++ /dev/null @@ -1,2502 +0,0 @@ - - - - activeSchemeId:org.eclipse.ui.defaultAcceleratorConfiguration - - - - - - topLevel - shellMaximized - - - Minimized - MinimizedByZoom - - - persp.actionSet:org.eclipse.mylyn.context.ui.actionSet - persp.actionSet:org.eclipse.mylyn.doc.actionSet - persp.actionSet:org.eclipse.mylyn.tasks.ui.navigation - persp.actionSet:org.eclipse.ui.cheatsheets.actionSet - persp.actionSet:org.eclipse.rse.core.search.searchActionSet - persp.actionSet:org.eclipse.search.searchActionSet - persp.actionSet:org.eclipse.ui.edit.text.actionSet.annotationNavigation - persp.actionSet:org.eclipse.ui.edit.text.actionSet.navigation - persp.actionSet:org.eclipse.ui.edit.text.actionSet.convertLineDelimitersTo - persp.actionSet:org.eclipse.ui.externaltools.ExternalToolsSet - persp.actionSet:org.eclipse.ui.actionSet.keyBindings - persp.actionSet:org.eclipse.ui.actionSet.openFiles - persp.actionSet:org.eclipse.jst.j2ee.J2eeMainActionSet - persp.actionSet:org.eclipse.jdt.ui.JavaActionSet - persp.actionSet:org.eclipse.debug.ui.launchActionSet - persp.actionSet:org.eclipse.debug.ui.debugActionSet - persp.actionSet:org.eclipse.ui.NavigateActionSet - persp.viewSC:org.eclipse.ui.navigator.ProjectExplorer - persp.viewSC:org.eclipse.wst.server.ui.ServersView - persp.viewSC:org.eclipse.datatools.connectivity.DataSourceExplorerNavigator - persp.viewSC:org.eclipse.ui.views.BookmarkView - persp.viewSC:org.eclipse.ui.views.ContentOutline - persp.viewSC:org.eclipse.ui.views.PropertySheet - persp.viewSC:org.eclipse.ui.views.ResourceNavigator - persp.viewSC:org.eclipse.wst.common.snippets.internal.ui.SnippetsView - persp.viewSC:org.eclipse.ui.views.AllMarkersView - persp.viewSC:org.eclipse.mylyn.tasks.ui.views.tasks - persp.viewSC:org.eclipse.search.ui.views.SearchView - persp.viewSC:org.eclipse.ui.console.ConsoleView - persp.showIn:org.eclipse.ui.navigator.ProjectExplorer - persp.newWizSC:org.eclipse.jpt.jpa.ui.wizard.newJpaProject - persp.perspSC:org.eclipse.jpt.ui.jpaPerspective - persp.perspSC:org.eclipse.debug.ui.DebugPerspective - persp.perspSC:org.eclipse.jdt.ui.JavaPerspective - persp.perspSC:org.eclipse.ui.resourcePerspective - persp.perspSC:org.eclipse.wst.web.ui.webDevPerspective - persp.newWizSC:org.eclipse.jst.j2ee.ui.project.facet.EarProjectWizard - persp.newWizSC:org.eclipse.jst.servlet.ui.project.facet.WebProjectWizard - persp.newWizSC:org.eclipse.jst.ejb.ui.project.facet.EjbProjectWizard - persp.newWizSC:org.eclipse.jst.j2ee.jca.ui.internal.wizard.ConnectorProjectWizard - persp.newWizSC:org.eclipse.jst.j2ee.ui.project.facet.appclient.AppClientProjectWizard - persp.newWizSC:org.eclipse.wst.web.ui.internal.wizards.SimpleWebProjectWizard - persp.newWizSC:org.eclipse.jpt.ui.wizard.newJpaProject - persp.newWizSC:org.eclipse.jst.servlet.ui.internal.wizard.AddServletWizard - persp.newWizSC:org.eclipse.jst.ejb.ui.internal.wizard.AddSessionBeanWizard - persp.newWizSC:org.eclipse.jst.ejb.ui.internal.wizard.AddMessageDrivenBeanWizard - persp.newWizSC:org.eclipse.jpt.ui.wizard.newEntity - persp.newWizSC:org.eclipse.jst.ws.creation.ui.wizard.serverwizard - persp.newWizSC:org.eclipse.ui.wizards.new.folder - persp.newWizSC:org.eclipse.ui.wizards.new.file - persp.actionSet:org.eclipse.wst.server.ui.internal.webbrowser.actionSet - persp.actionSet:org.eclipse.debug.ui.breakpointActionSet - persp.newWizSC:org.eclipse.m2e.core.wizards.Maven2ProjectWizard - persp.actionSet:org.eclipse.wst.ws.explorer.explorer - - - newtablook - - - - - - - - - - newtablook - - - - - - newtablook - - - - - - - - - - - - - - - - - - Maximized - - - - - - - View - categoryTag:Help - - - - View - categoryTag:General - activeOnClose - - ViewMenu - menuContribution:menu - - - - - View - categoryTag:Help - - - - newtablook - org.eclipse.e4.primaryDataStack - EditorStack - - - - - View - categoryTag:General - - ViewMenu - menuContribution:menu - - - - - View - categoryTag:General - - - View - categoryTag:Java - - - View - categoryTag:Java Browsing - - - - View - categoryTag:General - - ViewMenu - menuContribution:menu - - - - - View - categoryTag:General - - - View - categoryTag:Server - - - View - categoryTag:Data Management - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - - View - categoryTag:General - - ViewMenu - menuContribution:menu - - - - - View - categoryTag:Mylyn - - - - toolbarSeparator - - - - Draggable - - - - - - - - - - - - - - - toolbarSeparator - - - - Draggable - - - - - Draggable - - - - - - - - - - - - - - - - - - - Draggable - - - - - - - Draggable - - - - - - Draggable - - - - - - - Draggable - - - - - Draggable - - - - - toolbarSeparator - - - - Draggable - - - - - - - - - - - - toolbarSeparator - - - - toolbarSeparator - - - - Draggable - - - - - stretch - - - glue - - - - glue - - - Draggable - - - - - stretch - - - - Draggable - - - - - TrimStack - - - - - - - - - - - - - - - - - - - - - - - - - locale:zh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - locale:zh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - locale:zh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - locale:zh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - platform:win32 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Editor - - - View - categoryTag:Ant - - - View - categoryTag:Data Management - - - View - categoryTag:Data Management - - - View - categoryTag:Data Management - - - View - categoryTag:Debug - - - View - categoryTag:Debug - - - View - categoryTag:Debug - - - View - categoryTag:Debug - - - View - categoryTag:Debug - - - View - categoryTag:Debug - - - View - categoryTag:Debug - - - View - categoryTag:Git - - - View - categoryTag:Git - - - View - categoryTag:Git - - - View - categoryTag:Git - - - View - categoryTag:General - - - View - categoryTag:Help - - - View - categoryTag:Debug - - - View - categoryTag:Java - - - View - categoryTag:Java - - - View - categoryTag:Java - - - View - categoryTag:Java Browsing - - - View - categoryTag:Java Browsing - - - View - categoryTag:Java Browsing - - - View - categoryTag:Java Browsing - - - View - categoryTag:Java - - - View - categoryTag:General - - - View - categoryTag:Java - - - View - categoryTag:Java - - - View - categoryTag:JPA - - - View - categoryTag:JPA - - - View - categoryTag:JavaServer Faces - - - View - categoryTag:JavaServer Faces - - - View - categoryTag:Web Services - - - View - categoryTag:Maven - - - View - categoryTag:Maven - - - View - categoryTag:Mylyn - - - View - categoryTag:Mylyn - - - View - categoryTag:Mylyn - - - View - categoryTag:API Tools - - - View - categoryTag:Plug-in Development - - - View - categoryTag:Plug-in Development - - - View - categoryTag:Plug-in Development - - - View - categoryTag:Plug-in Development - - - View - categoryTag:Plug-in Development - - - View - categoryTag:Remote Systems - - - View - categoryTag:Remote Systems - - - View - categoryTag:Remote Systems - - - View - categoryTag:Remote Systems - - - View - categoryTag:Remote Systems - - - View - categoryTag:Remote Systems - - - View - categoryTag:Remote Systems - - - View - categoryTag:Remote Systems - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:CVS - - - View - categoryTag:CVS - - - View - categoryTag:Team - - - View - categoryTag:Team - - - View - categoryTag:Terminal - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:Help - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:General - - - View - categoryTag:Debug - - - View - categoryTag:JavaScript - - - View - categoryTag:JavaScript - - - View - categoryTag:JavaScript - - - View - categoryTag:JavaScript - - - View - categoryTag:JavaScript - - - View - categoryTag:Server - - - View - categoryTag:XML - - - View - categoryTag:XML - - - View - categoryTag:XML - - - View - categoryTag:XML - - - View - categoryTag:XML - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps b/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps deleted file mode 100644 index f5666298b590a888c66b2f99be77b3cd4794bc6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 972 zcmb7@y-or_5XZ*{FtM{Gp|ZGL4iMu~Y+Z*@J*@U@S!&<5!3_ zmOg~Of$$IJMIsTJOhuDK&f0lS*wIEs zng%??h?`SRx~`@6kdF_e&XBvzO%lf@%ohZ(P|ZFrmjTnkH8prgNlOkRp+cm8S)RE? zmY*#;lVZ~D{^ARE)3x)vp^EtAEHc-fgw8ljaCh}>*s-{M(hU;rOhpA~_@3wq?t3kl zl~}G;T;)C?4^*9F-;Spn`Vwm$(mmxN#i-Hs;2m=5Q540>=gXxPSWB-QoA5#tniwz| z!V8?F8_IYGP0^NwCQ1TFYI{MK6=o}T&xN>0_NMv`Tl1L=v=jk)A`&rW^zd;6rSufp z6l5@(-t_157&g=E|Mt~3Qgl>eV%X}>GjBU8-L-#Z>f*_H12?@3`&^RVSL^4HpF?WQ JRD1iH`2};=LB{|9 diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt b/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt deleted file mode 100644 index f84b816..0000000 --- a/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt +++ /dev/null @@ -1,29 +0,0 @@ -INDEX VERSION 1.126+E:\2016Spring\robocodefiles\download\app\workspace_robo4\.metadata\.plugins\org.eclipse.jdt.core -3253539546.index -240634369.index -3357244662.index -3837392347.index -1270703585.index -743580145.index -4213330522.index -2815204631.index -972965919.index -649753860.index -2097671088.index -2394798482.index -1886545541.index -2420224983.index -9299668.index -2806151389.index -2816454019.index -2169288515.index -3228954160.index -2122446671.index -2936589608.index -1812437159.index -2690281349.index -3090911769.index -844486800.index -195189658.index -2555277089.index -4256357263.index diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat b/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat deleted file mode 100644 index 0facbcd4b9baf082511caf207f299df748e6ab44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19199 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 H#FhRJzcsAQ diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/1a42e2ddbdd28c4e903ebde7bafa5867/segments.gen b/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/1a42e2ddbdd28c4e903ebde7bafa5867/segments.gen deleted file mode 100644 index e9fa6008becd133f1cac4c5cec7f4311c6576acc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20 QcmezW|NlP*2w;ZM07=&b0ssI2 diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/26522e0d83a422eed93329ece7565cfc/segments.gen b/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/26522e0d83a422eed93329ece7565cfc/segments.gen deleted file mode 100644 index e9fa6008becd133f1cac4c5cec7f4311c6576acc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20 QcmezW|NlP*2w;ZM07=&b0ssI2 diff --git a/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen b/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen deleted file mode 100644 index e9fa6008becd133f1cac4c5cec7f4311c6576acc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20 QcmezW|NlP*2w;ZM07=&b0ssI2 diff --git a/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/Module.java b/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/Module.java deleted file mode 100644 index e538d7a..0000000 --- a/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/Module.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.dotnet.host; - - -import net.sf.robocode.core.*; -import net.sf.robocode.dotnet.repository.items.handlers.DotNetPropertiesHandler; -import net.sf.robocode.dotnet.repository.root.handlers.DllHandler; -import net.sf.robocode.manager.IVersionManagerBase; -import net.sf.robocode.io.Logger; -import net.sf.jni4net.Bridge; - -import java.io.File; -import java.util.List; - - -/** - * @author Pavel Savara (original) - */ -public class Module extends BaseModule { - static { - // .NET proxies and their interfaces must be loaded in system class loader in order to call native methods - Init(); - } - - private static void Init() { - try { - - String libsDir; - final String version = ContainerBase.getComponent(IVersionManagerBase.class).getVersionN(); - - final java.security.CodeSource source = Module.class.getProtectionDomain().getCodeSource(); - final File file = new File(source.getLocation().toURI()).getCanonicalFile(); - - if (file.getName().equals("classes")) { - libsDir = file.getParent(); - } else if (file.getName().endsWith(".jar")) { - libsDir = file.getParent(); - } else { - throw new Error("Can't find " + file); - } - - final String nhost = libsDir + "/robocode.dotnet.nhost-" + version + ".dll"; - final String ncontrol = libsDir + "/robocode.control.dll"; - - Bridge.init(new File(libsDir)); - // Bridge.setVerbose(true); - // Bridge.setDebug(true); - Bridge.SetSystemClassLoader(Container.engineLoader); - Bridge.LoadAndRegisterAssemblyFrom(new File(ncontrol)); - Bridge.LoadAndRegisterAssemblyFrom(new File(nhost)); - - Container.cache.addComponent("DllItemHandler", DllHandler.class); - Container.cache.addComponent("CsPropertiesHandler", DotNetPropertiesHandler.class); - Container.cache.addComponent("VbPropertiesHandler", DotNetPropertiesHandler.class); - Container.cache.addComponent("DotNetPropertiesHandler", DotNetPropertiesHandler.class); - - // .NET proxies - Container.cache.addComponent("robocode.host.cs", DotNetHost.class); - Container.cache.addComponent("robocode.host.vb", DotNetHost.class); - Container.cache.addComponent("robocode.host.dotnet", DotNetHost.class); - - } catch (RuntimeException e) { - Logger.logError(e); - throw new Error("Can't initialize .NET Robocode", e); - } - } - - public void afterLoaded(List allModules) { - net.sf.robocode.dotnet.nhost.ModuleN.InitN(); - } -} diff --git a/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java b/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java deleted file mode 100644 index 852475f..0000000 --- a/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java +++ /dev/null @@ -1,382 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.installer; - - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.*; -import java.net.URL; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarInputStream; - - -/** - * Installer for Robocode. - * - * @author Mathew A. Nelsen (original) - * @author Flemming N. Larsen (contributor) - */ -public class AutoExtract implements ActionListener { - private JDialog licenseDialog; - private boolean accepted; - private final String[] spinner = { "-", "\\", "|", "/"}; - private String message = ""; - private static File installDir; - private static final String javaVersion = System.getProperty("java.version"); - - private boolean acceptLicense() { - String licenseText = ""; - - InputStream is; - - try { - JarFile extractJar = new JarFile("extract.jar"); - - is = extractJar.getInputStream(extractJar.getJarEntry("license/cpl-v10.html")); - } catch (IOException e) { - return true; - } - if (is == null) { - return true; - } - - BufferedReader r = new BufferedReader(new InputStreamReader(is)); - - try { - String line = r.readLine(); - - while (line != null) { - licenseText += line; - line = r.readLine(); - } - return acceptReject(licenseText); - - } catch (IOException e) { - System.err.println("Could not read line from license file: " + e); - } - return true; - } - - private boolean acceptReject(String text) { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - licenseDialog = new JDialog(); - licenseDialog.setTitle("License Agreement"); - licenseDialog.setModal(true); - licenseDialog.setLocation((screenSize.width - 500) / 2, (screenSize.height - 400) / 2); - licenseDialog.setSize(500, 400); - JTextPane t = new JTextPane(); - - t.setContentType("text/html"); - t.setText(text); - t.setFont(new Font("Dialog", Font.PLAIN, 12)); - t.setEditable(false); - - JScrollPane s = new JScrollPane(); - - s.setViewportView(t); - - licenseDialog.getContentPane().setLayout(new BorderLayout()); - licenseDialog.getContentPane().add(s, BorderLayout.CENTER); - - JPanel p = new JPanel(); - - p.setLayout(new BorderLayout()); - JButton b1 = new JButton("Accept"); - JButton b2 = new JButton("Cancel"); - - p.add(b1, BorderLayout.WEST); - p.add(b2, BorderLayout.EAST); - - b1.addActionListener(this); - b2.addActionListener(this); - - licenseDialog.getContentPane().add(p, BorderLayout.SOUTH); - - licenseDialog.setVisible(true); - - return accepted; - } - - public void actionPerformed(ActionEvent e) { - accepted = e.getActionCommand().equals("Accept"); - licenseDialog.dispose(); - licenseDialog = null; - } - - private boolean extract(File dest) { - JDialog statusDialog = new JDialog(); - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - int width = 500; - int height = 100; - - statusDialog.setTitle("Installing"); - statusDialog.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2); - statusDialog.setSize(width, height); - JLabel status = new JLabel(); - - statusDialog.getContentPane().setLayout(new BorderLayout()); - statusDialog.getContentPane().add(status, BorderLayout.CENTER); - - statusDialog.setVisible(true); - - FileOutputStream fos; - String entryName; - - byte buf[] = new byte[2048]; - - final String name = AutoExtract.class.getName().replaceAll("\\.", "/") + ".class"; - String urlJar = AutoExtract.class.getClassLoader().getResource(name).toString(); - final String src = urlJar.substring("jar:file:/".length(), urlJar.indexOf("!/")); - - if (src.indexOf('!') > -1) { - final String message = src - + "\nContains an exclamation point. Please move the file to a different directory."; - - JOptionPane.showMessageDialog(null, message); - System.err.println(message); - System.exit(0); - } - JarInputStream jarIS = null; - try { - final URL url = new URL("file:/" + src); - InputStream is = url.openStream(); - jarIS = new JarInputStream(is); - - JarEntry entry = jarIS.getNextJarEntry(); - - while (entry != null) { - int spin = 0; - - entryName = entry.getName(); - if (entry.isDirectory()) { - if (!entryName.startsWith("net")) { - File dir = new File(dest, entry.getName()); - - if (!dir.exists() && !dir.mkdirs()) { - System.out.println("Can't create dir " + dir); - } - } - } else { - if (!entryName.equals(name)) { - status.setText(entryName + " " + spinner[spin++]); - - File out = new File(dest, entry.getName()); - File parentDirectory = new File(out.getParent()); - - if (!parentDirectory.exists() && !parentDirectory.mkdirs()) { - System.out.println("Can't create dir " + parentDirectory); - } - fos = new FileOutputStream(out); - - int index = 0; - int num; - int count = 0; - - while ((num = jarIS.read(buf, 0, 2048)) != -1) { - fos.write(buf, 0, num); - index += num; - count++; - if (count > 80) { - status.setText(entryName + " " + spinner[spin++] + " (" + index + " bytes)"); - if (spin > 3) { - spin = 0; - } - count = 0; - } - } - fos.close(); - - if (entryName.length() > 3 && entryName.substring(entryName.length() - 3).equals(".sh")) { - if (File.separatorChar == '/') { - Runtime.getRuntime().exec("chmod 755 " + out.toString()); - } - } - - status.setText(entryName + " " + spinner[spin] + " (" + index + " bytes)"); - } - } - entry = jarIS.getNextJarEntry(); - } - statusDialog.dispose(); - message = "Installation successful"; - return true; - } catch (IOException e) { - message = "Installation failed" + e; - return false; - } finally { - if (jarIS != null) { - try { - jarIS.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - public static void main(String argv[]) { - // Verify that the Java version is version 6 (1.6.0) or newer - if (javaVersion.startsWith("1.") && javaVersion.charAt(2) < '5') { - final String message = "Robocode requires Java 6 (1.6.0) or newer.\n" - + "Your system is currently running Java " + javaVersion + ".\n" - + "If you have not installed (or activated) at least\n" + "JRE 6 or JDK 6, please do so."; - - JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); - System.err.println(message); - System.exit(0); - } - - // Set native look and feel - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (RuntimeException t) {// For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF - } - - File suggestedDir; - - AutoExtract extractor = new AutoExtract(); - - if (extractor.acceptLicense()) { - if (argv.length == 1) { - suggestedDir = new File(argv[0]); - } else if (File.separatorChar == '\\') { - suggestedDir = new File("c:\\robocode\\"); - } else { - suggestedDir = new File(System.getProperty("user.home") + File.separator + "robocode" + File.separator); - } - - boolean done = false; - - while (!done) { - int rc = JOptionPane.showConfirmDialog(null, - "Robocode plugin will be installed in:\n" + suggestedDir + "\nIs this ok?", "Installing Robocode", - JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); - - if (rc == JOptionPane.YES_OPTION) { - installDir = suggestedDir; - done = true; - } else if (rc == JOptionPane.NO_OPTION) { - Object r = JOptionPane.showInputDialog(null, "Please type in the installation directory", - "Installation Directory", JOptionPane.PLAIN_MESSAGE, null, null, suggestedDir); - - if (r == null) { - JOptionPane.showMessageDialog(null, "Installation cancelled."); - System.exit(0); - } else { - suggestedDir = new File(((String) r).trim()); - } - } else if (rc == JOptionPane.CANCEL_OPTION) { - JOptionPane.showMessageDialog(null, "Installation cancelled."); - System.exit(0); - } - } - if (!installDir.exists()) { - int rc = JOptionPane.showConfirmDialog(null, - installDir.getPath() + "\ndoes not exist. Would you like to create it?", "Installing Robocode", - JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - - if (rc == JOptionPane.YES_OPTION) { - if (!installDir.exists() && !installDir.mkdirs()) { - System.out.println("Can't create dir " + installDir); - } - } else { - JOptionPane.showMessageDialog(null, "Installation cancelled."); - System.exit(0); - } - } - boolean rv = extractor.extract(installDir); - - if (!rv) { - JOptionPane.showMessageDialog(null, extractor.message); - } - } else { - JOptionPane.showMessageDialog(null, "Installation cancelled."); - } - - // Delete the class file with the installer and it's parent folders in the robocode home dir - if (installDir != null) { - String installerPath = AutoExtract.class.getName().replaceAll("\\.", "/") + "$1.class"; - - deleteFileAndParentDirsIfEmpty(new File(installDir, installerPath)); - } - - System.exit(0); - } - - private static boolean deleteDir(File dir) { - if (dir.isDirectory()) { - for (File file : dir.listFiles()) { - if (file.isDirectory()) { - // Skip directories ending with ".data" - if (file.getName().endsWith(".data")) { - continue; - } - try { - // Test for symlink and ignore. - // Robocode won't create one, but just in case a user does... - if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) { - deleteDir(file); - if (file.exists() && !file.delete()) { - System.err.println("Can't delete: " + file); - } - } else { - System.out.println("Warning: " + file + " may be a symlink. It has been ignored"); - } - } catch (IOException e) { - System.out.println( - "Warning: Cannot determine canonical file for " + file + ". It has been ignored"); - } - } else { - if (file.exists() && !file.delete()) { - System.err.println("Can't delete: " + file); - } - } - } - return dir.delete(); - } - return false; - } - - /** - * Deletes a file and afterwards deletes the parent directories that are empty. - * - * @param file the file or directory to delete - * @return true if success - */ - private static boolean deleteFileAndParentDirsIfEmpty(final File file) { - boolean wasDeleted = false; - - if (file != null && file.exists()) { - if (file.isDirectory()) { - wasDeleted = deleteDir(file); - } else { - wasDeleted = file.delete(); - - File parent = file; - - while (wasDeleted && (parent = parent.getParentFile()) != null) { - // Delete parent directory, but only if it is empty - File[] files = parent.listFiles(); - - if (files != null && files.length == 0) { - wasDeleted = deleteDir(parent); - } else { - wasDeleted = false; - } - } - } - } - return wasDeleted; - } -} diff --git a/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java b/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java deleted file mode 100644 index 5507bb1..0000000 --- a/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.test.robotscs; - - -import net.sf.robocode.test.helpers.Assert; -import net.sf.robocode.test.helpers.RobocodeTestBed; - -import robocode.control.events.TurnEndedEvent; - - -/** - * @author Flemming N. Larsen (original) - */ -public class TestMaxTurnRate extends RobocodeTestBed { - - StringBuffer buf = new StringBuffer(); - - @Override - public String getRobotNames() { - return "tested.robotscs.MaxTurnRate,SampleCs.Target"; - } - - @Override - public String getInitialPositions() { - return "(50,50,0), (150,50,0)"; // Make sure the robots do not collide! - } - - @Override - public void onTurnEnded(TurnEndedEvent event) { - super.onTurnEnded(event); - - buf.append(event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot()); - - if (event.getTurnSnapshot().getTurn() == 26) { - final String out = buf.toString(); - - Assert.assertTrue(out.contains("1: 0.0, 0.0") || out.contains("1: 0.0, -0.0")); - Assert.assertTrue(out.contains("2: 0.0, -1.0") || out.contains("2: 0.0, -0.999999999")); - Assert.assertTrue(out.contains("3: 0.0, -2.0") || out.contains("3: 0.0, -1.999999999")); - Assert.assertTrue(out.contains("4: 0.0, -3.0") || out.contains("4: 0.0, -2.999999999")); - Assert.assertTrue(out.contains("5: 0.0, -4.0") || out.contains("5: 0.0, -3.999999999")); - Assert.assertTrue(out.contains("6: 0.0, -5.0") || out.contains("6: 0.0, -4.999999999")); - Assert.assertTrue(out.contains("7: 0.0, -6.0") || out.contains("7: 0.0, -5.999999999")); - Assert.assertTrue(out.contains("8: 0.0, -7.0") || out.contains("8: 0.0, -6.999999999")); - Assert.assertTrue(out.contains("9: 0.0, -8.0") || out.contains("9: 0.0, -7.999999999")); - Assert.assertTrue(out.contains("10: 0.0, -9.0") || out.contains("10: 0.0, -8.999999999")); - Assert.assertTrue(out.contains("11: 0.0, -10.0") || out.contains("11: 0.0, -9.999999999")); - Assert.assertTrue(out.contains("12: 0.0, -10.0") || out.contains("12: 0.0, -9.999999999")); - Assert.assertTrue(out.contains("13: 0.0, -10.0") || out.contains("13: 0.0, -9.999999999")); - - Assert.assertTrue(out.contains("14: 0.0, 0.0") || out.contains("14: 0.0, -0.0")); - Assert.assertTrue(out.contains("15: 0.0, 1.0") || out.contains("15: 0.0, 0.999999999")); - Assert.assertTrue(out.contains("16: 0.0, 2.0") || out.contains("16: 0.0, 1.999999999")); - Assert.assertTrue(out.contains("17: 0.0, 3.0") || out.contains("17: 0.0, 2.999999999")); - Assert.assertTrue(out.contains("18: 0.0, 4.0") || out.contains("18: 0.0, 3.999999999")); - Assert.assertTrue(out.contains("19: 0.0, 5.0") || out.contains("19: 0.0, 4.999999999")); - Assert.assertTrue(out.contains("20: 0.0, 6.0") || out.contains("20: 0.0, 5.999999999")); - Assert.assertTrue(out.contains("21: 0.0, 7.0") || out.contains("21: 0.0, 6.999999999")); - Assert.assertTrue(out.contains("22: 0.0, 8.0") || out.contains("22: 0.0, 7.999999999")); - Assert.assertTrue(out.contains("23: 0.0, 9.0") || out.contains("23: 0.0, 8.999999999")); - Assert.assertTrue(out.contains("24: 0.0, 10.0") || out.contains("24: 0.0, 9.999999999")); - Assert.assertTrue(out.contains("25: 0.0, 10.0") || out.contains("25: 0.0, 9.999999999")); - Assert.assertTrue(out.contains("26: 0.0, 10.0") || out.contains("26: 0.0, 9.999999999")); - } - } -} diff --git a/workspace_robo4/plugins/testing/robocode.testing.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java b/workspace_robo4/plugins/testing/robocode.testing.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java deleted file mode 100644 index e993cf8..0000000 --- a/workspace_robo4/plugins/testing/robocode.testing.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java +++ /dev/null @@ -1,389 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.installer; - - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.*; -import java.net.URL; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarInputStream; - - -/** - * Installer for Robocode. - * - * @author Mathew A. Nelsen (original) - * @author Flemming N. Larsen (contributor) - */ -public class AutoExtract implements ActionListener { - private JDialog licenseDialog; - private boolean accepted; - private final String[] spinner = { "-", "\\", "|", "/"}; - private String message = ""; - private static final String javaVersion = System.getProperty("java.version"); - - /** - * AutoExtract constructor. - */ - public AutoExtract() { - super(); - } - - private boolean acceptLicense() { - String licenseText = ""; - - InputStream is; - - try { - JarFile extractJar = new JarFile("extract.jar"); - - is = extractJar.getInputStream(extractJar.getJarEntry("license/cpl-v10.html")); - } catch (IOException e) { - return true; - } - if (is == null) { - return true; - } - - BufferedReader r = new BufferedReader(new InputStreamReader(is)); - - try { - String line = r.readLine(); - - while (line != null) { - licenseText += line; - line = r.readLine(); - } - return acceptReject(licenseText); - - } catch (IOException e) { - System.err.println("Could not read line from license file: " + e); - } - return true; - } - - private boolean acceptReject(String text) { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - licenseDialog = new JDialog(); - licenseDialog.setTitle("License Agreement"); - licenseDialog.setModal(true); - licenseDialog.setLocation((screenSize.width - 500) / 2, (screenSize.height - 400) / 2); - licenseDialog.setSize(500, 400); - JTextPane t = new JTextPane(); - - t.setContentType("text/html"); - t.setText(text); - t.setFont(new Font("Dialog", Font.PLAIN, 12)); - t.setEditable(false); - - JScrollPane s = new JScrollPane(); - - s.setViewportView(t); - - licenseDialog.getContentPane().setLayout(new BorderLayout()); - licenseDialog.getContentPane().add(s, BorderLayout.CENTER); - - JPanel p = new JPanel(); - - p.setLayout(new BorderLayout()); - JButton b1 = new JButton("Accept"); - JButton b2 = new JButton("Cancel"); - - p.add(b1, BorderLayout.WEST); - p.add(b2, BorderLayout.EAST); - - b1.addActionListener(this); - b2.addActionListener(this); - - licenseDialog.getContentPane().add(p, BorderLayout.SOUTH); - - licenseDialog.setVisible(true); - - return accepted; - } - - public void actionPerformed(ActionEvent e) { - accepted = e.getActionCommand().equals("Accept"); - licenseDialog.dispose(); - licenseDialog = null; - } - - private boolean extract(File dest) { - JDialog statusDialog = new JDialog(); - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - int width = 500; - int height = 100; - - statusDialog.setTitle("Installing"); - statusDialog.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2); - statusDialog.setSize(width, height); - JLabel status = new JLabel(); - - statusDialog.getContentPane().setLayout(new BorderLayout()); - statusDialog.getContentPane().add(status, BorderLayout.CENTER); - - statusDialog.setVisible(true); - - FileOutputStream fos; - String entryName; - - byte buf[] = new byte[2048]; - - final String name = AutoExtract.class.getName().replaceAll("\\.", "/") + ".class"; - String urlJar = AutoExtract.class.getClassLoader().getResource(name).toString(); - final String src = urlJar.substring("jar:file:/".length(), urlJar.indexOf("!/")); - - if (src.indexOf('!') > -1) { - final String message = src - + "\nContains an exclamation point. Please move the file to a different directory."; - - JOptionPane.showMessageDialog(null, message); - System.err.println(message); - System.exit(0); - } - JarInputStream jarIS = null; - try { - final URL url = new URL("file:/" + src); - InputStream is = url.openStream(); - jarIS = new JarInputStream(is); - - JarEntry entry = jarIS.getNextJarEntry(); - - while (entry != null) { - int spin = 0; - - entryName = entry.getName(); - if (entry.isDirectory()) { - if (!entryName.startsWith("net")) { - File dir = new File(dest, entry.getName()); - - if (!dir.exists() && !dir.mkdirs()) { - System.out.println("Can't create dir " + dir); - } - } - } else { - if (!entryName.equals(name)) { - status.setText(entryName + " " + spinner[spin++]); - - File out = new File(dest, entry.getName()); - File parentDirectory = new File(out.getParent()); - - if (!parentDirectory.exists() && !parentDirectory.mkdirs()) { - System.out.println("Can't create dir " + parentDirectory); - } - fos = new FileOutputStream(out); - - int index = 0; - int num; - int count = 0; - - while ((num = jarIS.read(buf, 0, 2048)) != -1) { - fos.write(buf, 0, num); - index += num; - count++; - if (count > 80) { - status.setText(entryName + " " + spinner[spin++] + " (" + index + " bytes)"); - if (spin > 3) { - spin = 0; - } - count = 0; - } - } - fos.close(); - - if (entryName.length() > 3 && entryName.substring(entryName.length() - 3).equals(".sh")) { - if (File.separatorChar == '/') { - Runtime.getRuntime().exec("chmod 755 " + out.toString()); - } - } - - status.setText(entryName + " " + spinner[spin] + " (" + index + " bytes)"); - } - } - entry = jarIS.getNextJarEntry(); - } - statusDialog.dispose(); - message = "Installation successful"; - return true; - } catch (IOException e) { - message = "Installation failed" + e; - return false; - } finally { - if (jarIS != null) { - try { - jarIS.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - public static void main(String argv[]) { - // Verify that the Java version is version 6 (1.6.0) or newer - if (javaVersion.startsWith("1.") && javaVersion.charAt(2) < '5') { - final String message = "Robocode requires Java 6 (1.6.0) or newer.\n" - + "Your system is currently running Java " + javaVersion + ".\n" - + "If you have not installed (or activated) at least\n" + "JRE 6 or JDK 6, please do so."; - - JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); - System.err.println(message); - System.exit(0); - } - - // Set native look and feel - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (RuntimeException t) {// For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF - } - - File installDir = null; - File suggestedDir; - - AutoExtract extractor = new AutoExtract(); - - if (extractor.acceptLicense()) { - if (argv.length == 1) { - suggestedDir = new File(argv[0]); - } else if (File.separatorChar == '\\') { - suggestedDir = new File("c:\\robocode\\"); - } else { - suggestedDir = new File(System.getProperty("user.home") + File.separator + "robocode" + File.separator); - } - - boolean done = false; - - while (!done) { - int rc = JOptionPane.showConfirmDialog(null, - "Robocode plugin will be installed in:\n" + suggestedDir + "\nIs this ok?", "Installing Robocode", - JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); - - if (rc == JOptionPane.YES_OPTION) { - installDir = suggestedDir; - done = true; - } else if (rc == JOptionPane.NO_OPTION) { - Object r = JOptionPane.showInputDialog(null, "Please type in the installation directory", - "Installation Directory", JOptionPane.PLAIN_MESSAGE, null, null, suggestedDir); - - if (r == null) { - JOptionPane.showMessageDialog(null, "Installation cancelled."); - System.exit(0); - } else { - suggestedDir = new File(((String) r).trim()); - } - } else if (rc == JOptionPane.CANCEL_OPTION) { - JOptionPane.showMessageDialog(null, "Installation cancelled."); - System.exit(0); - } - } - if (!installDir.exists()) { - int rc = JOptionPane.showConfirmDialog(null, - installDir.getPath() + "\ndoes not exist. Would you like to create it?", "Installing Robocode", - JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - - if (rc == JOptionPane.YES_OPTION) { - if (!installDir.exists() && !installDir.mkdirs()) { - System.out.println("Can't create dir " + installDir); - } - } else { - JOptionPane.showMessageDialog(null, "Installation cancelled."); - System.exit(0); - } - } - boolean rv = extractor.extract(installDir); - - if (!rv) { - JOptionPane.showMessageDialog(null, extractor.message); - } - } else { - JOptionPane.showMessageDialog(null, "Installation cancelled."); - } - - // Delete the class file with the installer and it's parent folders in the robocode home dir - if (installDir != null) { - String installerPath = AutoExtract.class.getName().replaceAll("\\.", "/") + "$1.class"; - - deleteFileAndParentDirsIfEmpty(new File(installDir, installerPath)); - } - - System.exit(0); - } - - private static boolean deleteDir(File dir) { - if (dir.isDirectory()) { - for (File file : dir.listFiles()) { - if (file.isDirectory()) { - // Skip directories ending with ".data" - if (file.getName().endsWith(".data")) { - continue; - } - try { - // Test for symlink and ignore. - // Robocode won't create one, but just in case a user does... - if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) { - deleteDir(file); - if (file.exists() && !file.delete()) { - System.err.println("Can't delete: " + file); - } - } else { - System.out.println("Warning: " + file + " may be a symlink. It has been ignored"); - } - } catch (IOException e) { - System.out.println( - "Warning: Cannot determine canonical file for " + file + ". It has been ignored"); - } - } else { - if (file.exists() && !file.delete()) { - System.err.println("Can't delete: " + file); - } - } - } - return dir.delete(); - } - return false; - } - - /** - * Deletes a file and afterwards deletes the parent directories that are empty. - * - * @param file the file or directory to delete - * @return true if success - */ - private static boolean deleteFileAndParentDirsIfEmpty(final File file) { - boolean wasDeleted = false; - - if (file != null && file.exists()) { - if (file.isDirectory()) { - wasDeleted = deleteDir(file); - } else { - wasDeleted = file.delete(); - - File parent = file; - - while (wasDeleted && (parent = parent.getParentFile()) != null) { - // Delete parent directory, but only if it is empty - File[] files = parent.listFiles(); - - if (files != null && files.length == 0) { - wasDeleted = deleteDir(parent); - } else { - wasDeleted = false; - } - } - } - } - return wasDeleted; - } -} diff --git a/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/HiddenAccess.java b/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/HiddenAccess.java deleted file mode 100644 index 184001c..0000000 --- a/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/HiddenAccess.java +++ /dev/null @@ -1,290 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.security; - - -import net.sf.robocode.core.ContainerBase; -import net.sf.robocode.io.Logger; -import net.sf.robocode.peer.IRobotStatics; -import robocode.BattleRules; -import robocode.Bullet; -import robocode.Event; -import robocode.RobotStatus; -import robocode.control.RobotSpecification; -import robocode.control.events.IBattleListener; -import robocode.robotinterfaces.IBasicRobot; - -import java.awt.*; -import java.io.File; -import java.io.FilenameFilter; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLDecoder; -import java.util.ArrayList; - - -/** - * Helpers for accessing hidden methods on events. - * - * @author Pavel Savara (original) - */ -public class HiddenAccess { - private static IHiddenEventHelper eventHelper; - private static IHiddenBulletHelper bulletHelper; - private static IHiddenSpecificationHelper specificationHelper; - private static IHiddenStatusHelper statusHelper; - private static IHiddenRulesHelper rulesHelper; - private static Method initContainer; - private static Method initContainerRe; - private static Method cleanup; - private static Method robocodeMain; - private static boolean initialized; - private static boolean foundCore = false; - - public static void init() { - if (initialized) { - return; - } - Method method; - - try { - method = Event.class.getDeclaredMethod("createHiddenHelper"); - method.setAccessible(true); - eventHelper = (IHiddenEventHelper) method.invoke(null); - method.setAccessible(false); - - method = Bullet.class.getDeclaredMethod("createHiddenHelper"); - method.setAccessible(true); - bulletHelper = (IHiddenBulletHelper) method.invoke(null); - method.setAccessible(false); - - method = RobotSpecification.class.getDeclaredMethod("createHiddenHelper"); - method.setAccessible(true); - specificationHelper = (IHiddenSpecificationHelper) method.invoke(null); - method.setAccessible(false); - - method = RobotStatus.class.getDeclaredMethod("createHiddenSerializer"); - method.setAccessible(true); - statusHelper = (IHiddenStatusHelper) method.invoke(null); - method.setAccessible(false); - - method = BattleRules.class.getDeclaredMethod("createHiddenHelper"); - method.setAccessible(true); - rulesHelper = (IHiddenRulesHelper) method.invoke(null); - method.setAccessible(false); - - ClassLoader loader = getClassLoader(); - Class main = loader.loadClass("net.sf.robocode.core.RobocodeMainBase"); - - initContainer = main.getDeclaredMethod("initContainer"); - initContainer.setAccessible(true); - - initContainerRe = main.getDeclaredMethod("initContainerForRobocodeEngine", File.class, IBattleListener.class); - initContainerRe.setAccessible(true); - - cleanup = main.getDeclaredMethod("cleanupForRobocodeEngine"); - cleanup.setAccessible(true); - - robocodeMain = main.getDeclaredMethod("robocodeMain", Object.class); - robocodeMain.setAccessible(true); - - initialized = true; - } catch (NoSuchMethodException e) { - Logger.logError(e); - } catch (InvocationTargetException e) { - Logger.logError(e); - } catch (IllegalAccessException e) { - Logger.logError(e); - } catch (ClassNotFoundException e) { - Logger.logError(e); - if (!foundCore) { - Logger.logError("Can't find robocode.core-1.x.jar module near to robocode.jar"); - Logger.logError("Class path: " + System.getProperty("robocode.class.path", null)); - } - System.exit(-1); - } catch (MalformedURLException e) { - Logger.logError(e); - } catch (MyException e) { - Logger.logError(e); - throw e; - } - - } - - private static ClassLoader getClassLoader() throws MalformedURLException { - // if other modules are .jar next to robocode.jar on same path, we will create classloader which will load them - // otherwise we rely on that they are already on classpath - StringBuilder classPath = new StringBuilder(System.getProperty("java.class.path", null)); - ClassLoader loader = ClassLoader.getSystemClassLoader(); - String path = HiddenAccess.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - - try { - path = URLDecoder.decode(path, "UCS2"); - } catch (UnsupportedEncodingException e) { - path = new File(".", "libs/robocode.jar").toString(); - } - final int i = path.lastIndexOf("robocode.jar"); - - if (i > 0) { - loader = createClassLoader(classPath, loader, path.substring(0, i)); - } - System.setProperty("robocode.class.path", classPath.toString()); - return loader; - } - - private static ClassLoader createClassLoader(StringBuilder classPath, ClassLoader loader, String dir) throws MalformedURLException { - - File dirf = new File(dir); - ArrayList urls = new ArrayList(); - - final File[] files = dirf.listFiles(new FilenameFilter() { - public boolean accept(File dir, String name) { - final String test = name.toLowerCase(); - - return test.endsWith(".jar") && !test.endsWith("robocode.jar"); - } - }); - - if (files != null) { - for (File file : files) { - final String name = file.toString().toLowerCase(); - - if (name.contains("robocode.core")) { - foundCore = true; - urls.add(file.toURI().toURL()); - } - if (name.contains("picocontainer")) { - urls.add(file.toURI().toURL()); - } - if (name.contains("codesize")) { - urls.add(file.toURI().toURL()); - } - classPath.append(File.pathSeparator); - classPath.append(file.toString()); - } - } - return new URLClassLoader(urls.toArray(new URL[urls.size()]), loader); - } - - public static boolean isCriticalEvent(Event e) { - return eventHelper.isCriticalEvent(e); - } - - public static void setEventTime(Event e, long newTime) { - eventHelper.setTime(e, newTime); - } - - public static void setEventPriority(Event e, int newPriority) { - eventHelper.setPriority(e, newPriority); - } - - public static void dispatch(Event event, IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { - eventHelper.dispatch(event, robot, statics, graphics); - } - - public static void setDefaultPriority(Event e) { - eventHelper.setDefaultPriority(e); - } - - public static byte getSerializationType(Event e) { - return eventHelper.getSerializationType(e); - } - - public static void update(Bullet bullet, double x, double y, String victimName, boolean isActive) { - bulletHelper.update(bullet, x, y, victimName, isActive); - } - - public static RobotSpecification createSpecification(Object fileSpecification, String name, String author, String webpage, String version, String robocodeVersion, String jarFile, String fullClassName, String description) { - return specificationHelper.createSpecification(fileSpecification, name, author, webpage, version, - robocodeVersion, jarFile, fullClassName, description); - } - - public static Object getFileSpecification(RobotSpecification specification) { - return specificationHelper.getFileSpecification(specification); - } - - public static String getRobotTeamName(RobotSpecification specification) { - return specificationHelper.getTeamName(specification); - } - - public static void setTeamId(RobotSpecification specification, String teamName) { - specificationHelper.setTeamName(specification, teamName); - } - - public static RobotStatus createStatus(double energy, double x, double y, double bodyHeading, double gunHeading, double radarHeading, double velocity, - double bodyTurnRemaining, double radarTurnRemaining, double gunTurnRemaining, double distanceRemaining, double gunHeat, int others, - int numSentries, int roundNum, int numRounds, long time) { - return statusHelper.createStatus(energy, x, y, bodyHeading, gunHeading, radarHeading, velocity, - bodyTurnRemaining, radarTurnRemaining, gunTurnRemaining, distanceRemaining, gunHeat, others, numSentries, - roundNum, numRounds, time); - } - - public static BattleRules createRules(int battlefieldWidth, int battlefieldHeight, int numRounds, double gunCoolingRate, long inactivityTime, boolean hideEnemyNames, int sentryBorderSize) { - return rulesHelper.createRules(battlefieldWidth, battlefieldHeight, numRounds, gunCoolingRate, inactivityTime, - hideEnemyNames, sentryBorderSize); - } - - public static boolean isSafeThread() { - final IThreadManagerBase threadManager = ContainerBase.getComponent(IThreadManagerBase.class); - - return threadManager != null && threadManager.isSafeThread(); - } - - public static void initContainerForRobotEngine(File robocodeHome, IBattleListener listener) { - init(); - try { - initContainerRe.invoke(null, robocodeHome, listener); - } catch (IllegalAccessException e) { - Logger.logError(e); - } catch (InvocationTargetException e) { - Logger.logError(e.getCause()); - Logger.logError(e); - } - } - - public static void initContainer() { - init(); - try { - initContainer.invoke(null); - } catch (IllegalAccessException e) { - Logger.logError(e); - } catch (InvocationTargetException e) { - Logger.logError(e.getCause()); - Logger.logError(e); - } - } - - public static void cleanup() { - init(); - try { - cleanup.invoke(null); - } catch (IllegalAccessException e) { - Logger.logError(e); - } catch (InvocationTargetException e) { - Logger.logError(e.getCause()); - Logger.logError(e); - } - } - - public static void robocodeMain(final String[] args) { - init(); - try { - robocodeMain.invoke(null, (Object) args); - } catch (IllegalAccessException e) { - Logger.logError(e); - } catch (InvocationTargetException e) { - Logger.logError(e.getCause()); - Logger.logError(e); - } - } - -} diff --git a/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/events/BattleEventDispatcher.java b/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/events/BattleEventDispatcher.java deleted file mode 100644 index 9155e67..0000000 --- a/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/events/BattleEventDispatcher.java +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.battle.events; - - -import static net.sf.robocode.io.Logger.logError; - -import net.sf.robocode.io.Logger; -import robocode.control.events.*; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - - -/** - * @author Flemming N. Larsen (original) - * @author Pavel Savara (original) - * - * @since 1.6.1 - */ -public class BattleEventDispatcher implements IBattleListener { - // This list is guaranteed to be thread-safe, which is necessary as it will be accessed - // by both the battle thread and battle manager thread. If this list is not thread-safe - // then ConcurentModificationExceptions will occur from time to time. - private final List listeners = new CopyOnWriteArrayList(); - - public BattleEventDispatcher() {} - - public void addListener(IBattleListener listener) { - assert (listener != null); - - listeners.add(listener); - } - - public void removeListener(IBattleListener listener) { - assert (listener != null); - listeners.remove(listener); - } - - public void onBattleStarted(BattleStartedEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onBattleStarted(event); - } catch (RuntimeException ex) { - logError("onBattleStarted " + listener.getClass(), ex); - } - } - } - - public void onBattleCompleted(BattleCompletedEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onBattleCompleted(event); - } catch (RuntimeException ex) { - logError("onBattleCompleted " + listener.getClass(), ex); - } - } - } - - public void onBattleFinished(BattleFinishedEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onBattleFinished(event); - } catch (RuntimeException ex) { - logError("onBattleFinished " + listener.getClass(), ex); - } - } - } - - public void onBattlePaused(BattlePausedEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onBattlePaused(event); - } catch (RuntimeException ex) { - logError("onBattlePaused " + listener.getClass(), ex); - } - } - } - - public void onBattleResumed(BattleResumedEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onBattleResumed(event); - } catch (RuntimeException ex) { - logError("onBattleResumed " + listener.getClass(), ex); - } - } - } - - public void onRoundStarted(RoundStartedEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onRoundStarted(event); - } catch (RuntimeException ex) { - logError("onRoundStarted " + listener.getClass(), ex); - } - } - } - - public void onRoundEnded(RoundEndedEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onRoundEnded(event); - } catch (RuntimeException ex) { - logError("onRoundEnded " + listener.getClass(), ex); - } - } - } - - public void onTurnStarted(TurnStartedEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onTurnStarted(event); - } catch (RuntimeException ex) { - logError("onTurnStarted " + listener.getClass(), ex); - } - } - } - - public void onTurnEnded(TurnEndedEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onTurnEnded(event); - } catch (RuntimeException ex) { - logError("onTurnEnded " + listener.getClass(), ex); - } - } - } - - public void onBattleMessage(BattleMessageEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onBattleMessage(event); - } catch (RuntimeException ex) { - logError("onBattleMessage " + listener.getClass(), ex); - } - } - } - - public void onBattleError(BattleErrorEvent event) { - for (IBattleListener listener : listeners) { - try { - listener.onBattleError(event); - } catch (RuntimeException ex) { - Logger.realErr.println(listener.getClass() + " " + ex.getMessage()); - } - } - } -} diff --git a/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMain.java b/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMain.java deleted file mode 100644 index 3ba5a93..0000000 --- a/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMain.java +++ /dev/null @@ -1,414 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.core; - - -import net.sf.robocode.battle.BattleResultsTableModel; -import net.sf.robocode.battle.IBattleManager; -import net.sf.robocode.host.ICpuManager; -import net.sf.robocode.host.IHostManager; -import net.sf.robocode.io.FileUtil; -import net.sf.robocode.io.Logger; -import net.sf.robocode.io.RobocodeProperties; -import net.sf.robocode.recording.BattleRecordFormat; -import net.sf.robocode.recording.IRecordManager; -import net.sf.robocode.repository.IRepositoryManager; -import net.sf.robocode.serialization.SerializableOptions; -import net.sf.robocode.settings.ISettingsManager; -import net.sf.robocode.sound.ISoundManager; -import net.sf.robocode.ui.IWindowManager; -import net.sf.robocode.util.StringUtil; -import net.sf.robocode.version.IVersionManager; -import robocode.control.events.*; - -import java.awt.Toolkit; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; - - -/** - * Robocode - A programming game involving battling AI tanks.
- * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * - * @see
robocode.sourceforge.net - * - * @author Mathew A. Nelson (original) - * @author Flemming N. Larsen (contributor) - * @author Pavel Savara (contributor) - */ -public final class RobocodeMain extends RobocodeMainBase { - - private final Setup setup; - private final BattleObserver battleObserver = new BattleObserver(); - final private ISettingsManager properties; - final private IHostManager hostManager; - final private IWindowManager windowManager; - final private ISoundManager soundManager; - final private IBattleManager battleManager; - final private IRecordManager recordManager; - final private IVersionManager versionManager; - - private static class Setup { - boolean minimize; - boolean exitOnComplete; - String battleFilename; - String recordFilename; - String recordXmlFilename; - String replayFilename; - String resultsFilename; - int tps; - } - - public RobocodeMain(ISettingsManager properties, - IHostManager hostManager, - IWindowManager windowManager, - ISoundManager soundManager, - IBattleManager battleManager, - IRecordManager recordManager, - IVersionManager versionManager - ) { - setup = new Setup(); - this.properties = properties; - this.hostManager = hostManager; - this.windowManager = windowManager; - this.soundManager = soundManager; - this.battleManager = battleManager; - this.recordManager = recordManager; - this.versionManager = versionManager; - } - - public RobocodeMain(ISettingsManager properties, - IHostManager hostManager, - IWindowManager windowManager, - IBattleManager battleManager, - IRecordManager recordManager, - IVersionManager versionManager - ) { - this(properties, hostManager, windowManager, null, battleManager, recordManager, versionManager); - } - - public RobocodeMain(ISettingsManager properties, - IHostManager hostManager, - IBattleManager battleManager, - IRecordManager recordManager, - IVersionManager versionManager - ) { - this(properties, hostManager, null, battleManager, recordManager, versionManager); - } - - public void run() { - Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - @Override - public void uncaughtException(Thread thread, Throwable t) { - t.printStackTrace(); - } - }); - - try { - hostManager.initSecurity(); - - // Set the Look and Feel (LAF) - if (windowManager != null && windowManager.isGUIEnabled()) { - windowManager.init(); - } - properties.setOptionsBattleDesiredTPS(setup.tps); - - battleManager.addListener(battleObserver); - - if (windowManager != null && windowManager.isGUIEnabled()) { - if (!setup.minimize && setup.battleFilename == null && soundManager != null) { - soundManager.playThemeMusic(); - windowManager.showSplashScreen(); - } - windowManager.showRobocodeFrame(true, setup.minimize); - - // Play the intro battle if a battle file is not specified and this is the first time Robocode is being run - - if (setup.battleFilename == null && versionManager.isLastRunVersionChanged()) { - properties.saveProperties(); - windowManager.runIntroBattle(); - } - } - - final boolean enableCLIRecording = (setup.recordFilename != null || setup.recordXmlFilename != null); - - // Note: At this point the GUI should be opened (if enabled) before starting the battle from a battle file - if (setup.battleFilename != null) { - if (setup.replayFilename != null) { - System.err.println("You cannot run both a battle and replay a battle record in the same time."); - System.exit(8); - } - - setup.exitOnComplete = true; - - battleManager.setBattleFilename(setup.battleFilename); - if (new File(battleManager.getBattleFilename()).exists()) { - battleManager.startNewBattle(battleManager.loadBattleProperties(), false, enableCLIRecording); - } else { - System.err.println("The specified battle file '" + setup.battleFilename + "' was not found"); - System.exit(8); - } - } else if (setup.replayFilename != null) { - setup.exitOnComplete = true; - if (setup.replayFilename.toLowerCase().endsWith("xml.zip")) { - recordManager.loadRecord(setup.replayFilename, BattleRecordFormat.XML_ZIP); - } else { - recordManager.loadRecord(setup.replayFilename, BattleRecordFormat.BINARY_ZIP); - } - - if (new File(setup.replayFilename).exists()) { - battleManager.replay(); - } else { - System.err.println("The specified battle record file '" + setup.replayFilename + "' was not found"); - System.exit(8); - } - } - } catch (RuntimeException e) { - Logger.logError(e); - } - } - - public void loadSetup(String[] args) { - - final String nosecMessage = "Robocode is running without a security manager.\n" - + "Robots have full access to your system.\n" + "You should only run robots which you trust!"; - final String exMessage = "Robocode is running in experimental mode.\n" - + "Robots have access to their IRobotPeer interfaces.\n" + "You should only run robots which you trust!"; - - if (RobocodeProperties.isSecurityOff()) { - Logger.logWarning(nosecMessage); - } - if (System.getProperty("EXPERIMENTAL", "false").equals("true")) { - Logger.logWarning(exMessage); - } - - setup.tps = properties.getOptionsBattleDesiredTPS(); - - // Disable canonical file path cache under Windows as it causes trouble when returning - // paths with differently-capitalized file names. - if (System.getProperty("os.name").toLowerCase().startsWith("windows ")) { - System.setProperty("sun.io.useCanonCaches", "false"); - } - - // Initialize the system property so the AWT does not use headless mode meaning that the - // GUI (Awt and Swing) is enabled per default when running starting Robocode. - // It might be set to true later, if the -nodisplay option is set (in the setEnableGUI method). - // Read more about headless mode here: - // http://java.sun.com/developer/technicalArticles/J2SE/Desktop/headless/ - System.setProperty("java.awt.headless", "false"); - - for (int i = 0; i < args.length; i++) { - String currentArg = args[i]; - if (currentArg.equalsIgnoreCase("-cwd") && (i < args.length + 1)) { - changeDirectory(args[i + 1]); - i++; - } else if (currentArg.equalsIgnoreCase("-battle") && (i < args.length + 1)) { - setup.battleFilename = args[i + 1]; - i++; - } else if (currentArg.equalsIgnoreCase("-record") && (i < args.length + 1)) { - setup.recordFilename = args[i + 1]; - i++; - } else if (currentArg.equalsIgnoreCase("-recordXML") && (i < args.length + 1)) { - setup.recordXmlFilename = args[i + 1]; - i++; - } else if (currentArg.equalsIgnoreCase("-replay") && (i < args.length + 1)) { - setup.replayFilename = args[i + 1]; - i++; - } else if (currentArg.equalsIgnoreCase("-results") && (i < args.length + 1)) { - setup.resultsFilename = args[i + 1]; - i++; - } else if (currentArg.equalsIgnoreCase("-tps") && (i < args.length + 1)) { - setup.tps = Integer.parseInt(args[i + 1]); - if (setup.tps < 1) { - Logger.logError("tps must be > 0"); - System.exit(8); - } - i++; - } else if (currentArg.equalsIgnoreCase("-minimize")) { - setup.minimize = true; - } else if (currentArg.equalsIgnoreCase("-nodisplay")) { - if (windowManager != null) { - windowManager.setEnableGUI(false); - } - if (soundManager != null) { - soundManager.setEnableSound(false); - } - setup.tps = 10000; // set TPS to maximum - } else if (currentArg.equalsIgnoreCase("-nosound")) { - if (soundManager != null) { - soundManager.setEnableSound(false); - } - } else if (currentArg.equals("-?") || currentArg.equalsIgnoreCase("-help")) { - printUsage(); - System.exit(0); - } else { - Logger.logError("Not understood: " + currentArg); - printUsage(); - System.exit(8); - } - } - File robotsDir = FileUtil.getRobotsDir(); - - if (robotsDir == null) { - System.err.println("No valid robot directory is specified"); - System.exit(8); - } else if (!(robotsDir.exists() && robotsDir.isDirectory())) { - System.err.println('\'' + robotsDir.getAbsolutePath() + "' is not a valid robot directory"); - System.exit(8); - } - - // The Default Toolkit must be set as soon as we know if we are going to use headless mode or not. - // That is if the toolkit must be headless or not (GUI on/off). If we are running in headless mode - // from this point, a HeadlessException will be thrown if we access a AWT/Swing component. - // Read more about headless mode here: - // http://java.sun.com/developer/technicalArticles/J2SE/Desktop/headless/ - Toolkit.getDefaultToolkit(); - } - - private void changeDirectory(String robocodeDir) { - try { - FileUtil.setCwd(new File(robocodeDir)); - } catch (IOException e) { - System.err.println(robocodeDir + " is not a valid directory to start Robocode in."); - System.exit(8); - } - } - - private void printUsage() { - System.out.print( - "Usage: robocode [-?] [-help] [-cwd path] [-battle filename [-results filename]\n" - + " [-record filename] [-recordXML filename] [-replay filename]\n" - + " [-tps tps] [-minimize] [-nodisplay] [-nosound]\n\n" + "where options include:\n" - + " -? or -help Prints out the command line usage of Robocode\n" - + " -cwd Change the current working directory\n" - + " -battle Run the battle specified in a battle file\n" - + " -results Save results to the specified text file\n" - + " -record Record the battle into the specified file as binary\n" - + " -recordXML Record the battle into the specified file as XML\n" - + " -replay Replay the specified battle record\n" - + " -tps Set the TPS > 0 (Turns Per Second)\n" - + " -minimize Run minimized when Robocode starts\n" - + " -nodisplay Run with the display / GUI disabled\n" - + " -nosound Run with sound disabled\n\n" + "Java Properties include:\n" - + " -DWORKINGDIRECTORY= Set the working directory\n" - + " -DROBOTPATH= Set the robots directory (default is 'robots')\n" - + " -DBATTLEPATH= Set the battles directory (default is 'battles')\n" - + " -DNOSECURITY=true|false Enable/disable Robocode's security manager\n" - + " -Ddebug=true|false Enable/disable debugging used for preventing\n" - + " robot timeouts and skipped turns, and allows an\n" - + " an unlimited painting buffer when debugging robots\n" - + " -DlogMessages=true|false Log messages and warnings will be disabled\n" - + " -DlogErrors=true|false Log errors will be disabled\n" - + " -DEXPERIMENTAL=true|false Enable/disable access to peer in robot interfaces\n" - + " -DPARALLEL=true|false Enable/disable parallel processing of robots turns\n" - + " -DRANDOMSEED= Set seed for deterministic behavior of random\n" - + " numbers\n"); - } - - private void printResultsData(BattleCompletedEvent event) { - // Do not print out if no result file has been specified and the GUI is enabled - if ((setup.resultsFilename == null && (!setup.exitOnComplete || windowManager.isGUIEnabled()))) { - return; - } - - PrintStream out = null; - FileOutputStream fos = null; - - try { - if (setup.resultsFilename == null) { - out = Logger.realOut; - } else { - File f = new File(setup.resultsFilename); - - try { - fos = new FileOutputStream(f); - out = new PrintStream(fos); - } catch (IOException e) { - Logger.logError(e); - } - } - if (out != null) { - BattleResultsTableModel resultsTable = new BattleResultsTableModel(event.getSortedResults(), - event.getBattleRules().getNumRounds()); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - resultsTable.print(new PrintStream(baos)); - out.append(StringUtil.toBasicLatin(baos.toString())); - } - } finally { - FileUtil.cleanupStream(out); - FileUtil.cleanupStream(fos); - } - } - - private class BattleObserver extends BattleAdaptor { - boolean isReplay; - - @Override - public void onBattleStarted(BattleStartedEvent event) { - isReplay = event.isReplay(); - } - - @Override - public void onBattleCompleted(BattleCompletedEvent event) { - if (!isReplay) { - printResultsData(event); - } - if (setup.recordFilename != null) { - recordManager.saveRecord(setup.recordFilename, BattleRecordFormat.BINARY_ZIP, - new SerializableOptions(false)); - } - if (setup.recordXmlFilename != null) { - recordManager.saveRecord(setup.recordXmlFilename, BattleRecordFormat.XML, new SerializableOptions(false)); - } - } - - @Override - public void onBattleMessage(BattleMessageEvent event) { - if (System.getProperty("logMessages", "true").equalsIgnoreCase("true")) { - Logger.realOut.println(event.getMessage()); - } - } - - @Override - public void onBattleError(BattleErrorEvent event) { - if (System.getProperty("logErrors", "true").equalsIgnoreCase("true")) { - Logger.realErr.println(event.getError()); - } - } - } - - public void cleanup() { - final IWindowManager windowManager = Container.getComponent(IWindowManager.class); - - if (windowManager != null) { - windowManager.cleanup(); - } - Container.getComponent(IBattleManager.class).cleanup(); - Container.getComponent(IHostManager.class).cleanup(); - } - - public void initForRobocodeEngine(IBattleListener listener) { - final IWindowManager windowManager = Container.getComponent(IWindowManager.class); - - if (windowManager != null) { - windowManager.setSlave(true); - windowManager.setEnableGUI(false); - } - Container.getComponent(IHostManager.class).initSecurity(); - if (listener != null) { - Container.getComponent(IBattleManager.class).addListener(listener); - } - Container.getComponent(ICpuManager.class).getCpuConstant(); - Container.getComponent(IRepositoryManager.class).reload(versionManager.isLastRunVersionChanged()); - } -} diff --git a/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/JavaHost.java b/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/JavaHost.java deleted file mode 100644 index 7dde1e9..0000000 --- a/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/JavaHost.java +++ /dev/null @@ -1,192 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.host; - - -import net.sf.robocode.host.security.RobotClassLoader; -import net.sf.robocode.host.proxies.*; -import net.sf.robocode.peer.IRobotStatics; -import net.sf.robocode.repository.IRobotItem; -import net.sf.robocode.repository.RobotType; -import static net.sf.robocode.io.Logger.logError; -import net.sf.robocode.io.Logger; -import net.sf.robocode.peer.IRobotPeer; -import net.sf.robocode.security.HiddenAccess; -import robocode.Droid; -import robocode.Robot; -import robocode.BorderSentry; -import robocode.control.RobotSpecification; -import robocode.robotinterfaces.*; - -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseWheelEvent; -import java.awt.*; -import java.security.AccessControlException; -import java.lang.reflect.Method; - - -/** - * @author Pavel Savara (original) - */ -public class JavaHost implements IHost { - public IRobotClassLoader createLoader(IRobotItem robotItem) { - return new RobotClassLoader(robotItem.getClassPathURL(), robotItem.getFullClassName()); - } - - public IHostingRobotProxy createRobotProxy(IHostManager hostManager, RobotSpecification robotSpecification, IRobotStatics statics, IRobotPeer peer) { - IHostingRobotProxy robotProxy; - final IRobotItem specification = (IRobotItem) HiddenAccess.getFileSpecification(robotSpecification); - - if (specification.isTeamRobot()) { - robotProxy = new TeamRobotProxy(specification, hostManager, peer, (RobotStatics) statics); - } else if (specification.isAdvancedRobot()) { - robotProxy = new AdvancedRobotProxy(specification, hostManager, peer, (RobotStatics) statics); - } else if (specification.isStandardRobot()) { - robotProxy = new StandardRobotProxy(specification, hostManager, peer, (RobotStatics) statics); - } else if (specification.isJuniorRobot()) { - robotProxy = new JuniorRobotProxy(specification, hostManager, peer, (RobotStatics) statics); - } else { - throw new AccessControlException("Unknown robot type"); - } - return robotProxy; - } - - public String[] getReferencedClasses(IRobotItem robotItem) { - IRobotClassLoader loader = null; - - try { - loader = createLoader(robotItem); - loader.loadRobotMainClass(true); - return loader.getReferencedClasses(); - - } catch (ClassNotFoundException e) { - Logger.logError(e); - return new String[0]; - } finally { - if (loader != null) { - loader.cleanup(); - } - } - } - - public RobotType getRobotType(IRobotItem robotItem, boolean resolve, boolean message) { - IRobotClassLoader loader = null; - - try { - loader = createLoader(robotItem); - Class robotClass = loader.loadRobotMainClass(resolve); - - if (robotClass == null || java.lang.reflect.Modifier.isAbstract(robotClass.getModifiers())) { - // this class is not robot - return RobotType.INVALID; - } - return checkInterfaces(robotClass, robotItem); - - } catch (RuntimeException t) { - if (message) { - logError("Got an error with " + robotItem.getFullClassName() + ": " + t); // just message here - if (t.getMessage() != null && t.getMessage().contains("Bad version number in .class file")) { - logError( - "Maybe robot was compiled with a newer Java version the Java version used for running Robocode?"); - } - } - return RobotType.INVALID; - } finally { - if (loader != null) { - loader.cleanup(); - } - } - } - - private RobotType checkInterfaces(Class robotClass, IRobotItem robotItem) { - boolean isJuniorRobot = false; - boolean isStandardRobot = false; - boolean isInteractiveRobot = false; - boolean isPaintRobot = false; - boolean isAdvancedRobot = false; - boolean isTeamRobot = false; - boolean isDroid = false; - boolean isSentryRobot = false; - - if (IAdvancedRobot.class.isAssignableFrom(robotClass)) { // Note: must be checked first - isAdvancedRobot = true; - } - if (Robot.class.isAssignableFrom(robotClass) && !isAdvancedRobot) { - isStandardRobot = true; - } - if (IJuniorRobot.class.isAssignableFrom(robotClass)) { // Note: Must be checked before checking for standard robot - isJuniorRobot = true; - if (isAdvancedRobot) { - throw new AccessControlException( - robotItem.getFullClassName() + ": Junior robot should not implement IAdvancedRobot interface."); - } - } - if (IBasicRobot.class.isAssignableFrom(robotClass)) { - if (!(isAdvancedRobot || isJuniorRobot)) { - isStandardRobot = true; - } - } - if (ITeamRobot.class.isAssignableFrom(robotClass)) { - isTeamRobot = true; - } - if (Droid.class.isAssignableFrom(robotClass)) { - isDroid = true; - } - if (BorderSentry.class.isAssignableFrom(robotClass)) { - isSentryRobot = true; - } - - if (IInteractiveRobot.class.isAssignableFrom(robotClass)) { - // in this case we make sure that robot don't waste time - if (checkMethodOverride(robotClass, Robot.class, "getInteractiveEventListener") - || checkMethodOverride(robotClass, Robot.class, "onKeyPressed", KeyEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onKeyReleased", KeyEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onKeyTyped", KeyEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onMouseClicked", MouseEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onMouseEntered", MouseEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onMouseExited", MouseEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onMousePressed", MouseEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onMouseReleased", MouseEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onMouseMoved", MouseEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onMouseDragged", MouseEvent.class) - || checkMethodOverride(robotClass, Robot.class, "onMouseWheelMoved", MouseWheelEvent.class) - ) { - isInteractiveRobot = true; - } - } - - if (IPaintRobot.class.isAssignableFrom(robotClass)) { - if (checkMethodOverride(robotClass, Robot.class, "getPaintEventListener") - || checkMethodOverride(robotClass, Robot.class, "onPaint", Graphics2D.class) - ) { - isPaintRobot = true; - } - } - - return new RobotType(isJuniorRobot, isStandardRobot, isInteractiveRobot, isPaintRobot, isAdvancedRobot, - isTeamRobot, isDroid, isSentryRobot); - } - - private boolean checkMethodOverride(Class robotClass, Class knownBase, String name, Class... parameterTypes) { - if (knownBase.isAssignableFrom(robotClass)) { - final Method getInteractiveEventListener; - - try { - getInteractiveEventListener = robotClass.getMethod(name, parameterTypes); - } catch (NoSuchMethodException e) { - return false; - } - if (getInteractiveEventListener.getDeclaringClass().equals(knownBase)) { - return false; - } - } - return true; - } - -} diff --git a/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventManager.java b/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventManager.java deleted file mode 100644 index 5621c87..0000000 --- a/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventManager.java +++ /dev/null @@ -1,572 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.host.events; - - -import net.sf.robocode.host.proxies.BasicRobotProxy; -import net.sf.robocode.security.HiddenAccess; -import robocode.*; -import robocode.exception.EventInterruptedException; -import robocode.robotinterfaces.IBasicRobot; - -import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; - - -// XXX Remember to update the .NET version whenever a change is made to this class! - -/** - * This class is used for managing the event queue for a robot. - * - * @author Mathew A. Nelson (original) - * @author Flemming N. Larsen (contributor) - * @author Matthew Reeder (contributor) - * @author Robert D. Maupin (contributor) - * @author Nathaniel Troutman (contributor) - * @author Pavel Savara (contributor) - */ -public final class EventManager implements IEventManager { - - private final static int MAX_PRIORITY = 100; - public final static int MAX_EVENT_STACK = 2; - public final static int MAX_QUEUE_SIZE = 256; - - private final List customEvents = new CopyOnWriteArrayList(); - private final EventQueue eventQueue; - - private final boolean[] interruptible = new boolean[MAX_PRIORITY + 1]; - private Event currentTopEvent; - private int currentTopEventPriority; - private ScannedRobotEvent dummyScannedRobotEvent; - private Map eventNames; - - private IBasicRobot robot; - private BasicRobotProxy robotProxy; - - /** - * Constructs a new EventManager. - * - * @param robotProxy the robot proxy that this event manager applies to. - */ - public EventManager(BasicRobotProxy robotProxy) { - this.robotProxy = robotProxy; - eventQueue = new EventQueue(); - - registerEventNames(); - reset(); - } - - /** - * Adds an event to the event queue. - * @param event is the event to add to the event queue. - */ - public void add(Event event) { - if (!HiddenAccess.isCriticalEvent(event)) { - final int priority = getEventPriority(event.getClass().getName()); - HiddenAccess.setEventPriority(event, priority); - } - addImpl(event); - } - - /** - * Internal method for adding an event to the event queue. - * @param event is the event to add to the event queue. - */ - private void addImpl(Event event) { - if (eventQueue != null) { - if (eventQueue.size() > MAX_QUEUE_SIZE) { - robotProxy.println( - "Not adding to " + robotProxy.getStatics().getName() + "'s queue, exceeded " + MAX_QUEUE_SIZE - + " events in queue."); - } else { - HiddenAccess.setEventTime(event, getTime()); - eventQueue.add(event); - } - } - } - - /** - * Adds an custom event to the event queue based on a condition. - * @param condition is the condition that must be met in order to trigger the custom event. - */ - public void addCustomEvent(Condition condition) { - customEvents.add(condition); - } - - /** - * Removes all events from the event queue. - * @param includingSystemEvents {@code true} if system events must be removed as well; - * {@code false} if system events should stay on the event queue. - */ - public void clearAllEvents(boolean includingSystemEvents) { - eventQueue.clear(includingSystemEvents); - // customEvents.clear(); // Custom event should not be cleared here - } - - /** - * Cleans up the event queue. - *

- * This method should be called when the event queue is no longer needed, - * i.e. before it must be garbage collected. - */ - public void cleanup() { - // Remove all events - reset(); - - // Remove all references to robots - robot = null; - robotProxy = null; - } - - /** - * Returns a list containing all events currently in the robot's queue. - */ - public List getAllEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - events.add(e); - } - } - return events; - } - - /** - * Returns a list containing all BulletHitBulletEvents currently in the robot's queue. - */ - public List getBulletHitBulletEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof BulletHitBulletEvent) { - events.add((BulletHitBulletEvent) e); - } - } - } - return events; - } - - /** - * Returns a list containing all BulletHitEvents currently in the robot's queue. - */ - public List getBulletHitEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof BulletHitEvent) { - events.add((BulletHitEvent) e); - } - } - } - return events; - } - - /** - * Returns a list containing all BulletMissedEvents currently in the robot's queue. - */ - public List getBulletMissedEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof BulletMissedEvent) { - events.add((BulletMissedEvent) e); - } - } - } - return events; - } - - /** - * Returns a list containing all HitByBulletEvents currently in the robot's queue. - */ - public List getHitByBulletEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof HitByBulletEvent) { - events.add((HitByBulletEvent) e); - } - } - } - return events; - } - - /** - * Returns a list containing all HitRobotEvents currently in the robot's queue. - */ - public List getHitRobotEvents() { - List events = new ArrayList(); - - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof HitRobotEvent) { - events.add((HitRobotEvent) e); - } - } - } - return events; - } - - /** - * Returns a list containing all HitWallEvents currently in the robot's queue. - */ - public List getHitWallEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof HitWallEvent) { - events.add((HitWallEvent) e); - } - } - } - return events; - } - - /** - * Returns a list containing all RobotDeathEvents currently in the robot's queue. - */ - public List getRobotDeathEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof RobotDeathEvent) { - events.add((RobotDeathEvent) e); - } - } - } - return events; - } - - /** - * Returns a list containing all ScannedRobotEvents currently in the robot's queue. - */ - public List getScannedRobotEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof ScannedRobotEvent) { - events.add((ScannedRobotEvent) e); - } - } - } - return events; - } - - /** - * Returns a list containing all MessageEvents currently in the robot's queue. - */ - public List getMessageEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof MessageEvent) { - events.add((MessageEvent) e); - } - } - } - return events; - } - - /** - * Returns a list containing all StatusEvents currently in the robot's queue. - */ - public List getStatusEvents() { - List events = new ArrayList(); - synchronized (eventQueue) { - for (Event e : eventQueue) { - if (e instanceof StatusEvent) { - events.add((StatusEvent) e); - } - } - } - return events; - } - - /** - * Returns the priority of the current top event. - */ - public int getCurrentTopEventPriority() { - return currentTopEventPriority; - } - - /** - * Returns the current top event. - */ - public Event getCurrentTopEvent() { - return currentTopEvent; - } - - /** - * Checks if events with a specific event priority are interruptible. - * @param priority is the event priority that must be checked. - * @see #setInterruptible(int, boolean) - */ - public boolean isInterruptible(int priority) { - return interruptible[priority]; - } - - /** - * Sets the robot that will receive events dispatched from the event queue. - * @param robot is the robot that will receive event dispatched from the event queue. - */ - public void setRobot(IBasicRobot robot) { - this.robot = robot; - } - - /** - * Returns the priority of a ScannedRobotEvent. - */ - public int getScannedRobotEventPriority() { - return dummyScannedRobotEvent.getPriority(); - } - - /** - * Returns the current time/turn of the battle round. - */ - public long getTime() { - return robotProxy.getTimeImpl(); - } - - /** - * This is the heart of the event manager, which processes the events for a robot. - */ - public void processEvents() { - // Remove old events - eventQueue.clear(getTime() - MAX_EVENT_STACK); - - // Process custom events - for (Condition customEvent : customEvents) { - boolean conditionSatisfied = callUserCode(customEvent); - if (conditionSatisfied) { - addImpl(new CustomEvent(customEvent)); - } - } - - // Sort the events based on the time and priority of the events - eventQueue.sort(); - - // Process event queue here - Event currentEvent; - while ((currentEvent = (eventQueue.size() > 0) ? eventQueue.get(0) : null) != null - && currentEvent.getPriority() >= currentTopEventPriority) { - - if (currentEvent.getPriority() == currentTopEventPriority) { - if (currentTopEventPriority > Integer.MIN_VALUE && isInterruptible(currentTopEventPriority)) { - setInterruptible(currentTopEventPriority, false); // we're going to restart it, so reset. - - // We are already in an event handler, took action, and a new event was generated. - // So we want to break out of the old handler to process it here. - throw new EventInterruptedException(currentEvent.getPriority()); - } - break; - } - - int oldTopEventPriority = currentTopEventPriority; - - currentTopEventPriority = currentEvent.getPriority(); - currentTopEvent = currentEvent; - - eventQueue.remove(currentEvent); - try { - dispatch(currentEvent); - - setInterruptible(currentTopEventPriority, false); - - } catch (EventInterruptedException e) { - currentTopEvent = null; - } catch (RuntimeException e) { - currentTopEvent = null; - throw e; - } catch (MyException e) { - currentTopEvent = null; - throw e; - } finally { - currentTopEventPriority = oldTopEventPriority; - } - } - } - - /** - * Checks if the user's condition for a custom event is satisfied. - * @param condition is the condition to check. - * @return {@code true} if the condition is satisfied; {@code false} otherwise. - */ - private boolean callUserCode(Condition condition) { - boolean conditionSatisfied; - robotProxy.setTestingCondition(true); - try { - conditionSatisfied = condition.test(); - } finally { - robotProxy.setTestingCondition(false); - } - return conditionSatisfied; - } - - /** - * Dispatches an event for a robot. - *

- * Too old events will not be dispatched and a critical event is always dispatched. - * - * @param event the event to dispatch to the robot. - */ - private void dispatch(Event event) { - if (robot != null && event != null) { - try { - // skip too old events - if ((event.getTime() > getTime() - MAX_EVENT_STACK) || HiddenAccess.isCriticalEvent(event)) { - HiddenAccess.dispatch(event, robot, robotProxy.getStatics(), robotProxy.getGraphicsImpl()); - } - } catch (Exception ex) { - robotProxy.println("SYSTEM: " + ex.getClass().getName() + " occurred on " + event.getClass().getName()); - ex.printStackTrace(robotProxy.getOut()); - } - } - } - - /** - * Removes the custom event with the specified condition from the event queue. - * @param condition is the condition of the custom event to remove. - */ - public void removeCustomEvent(Condition condition) { - customEvents.remove(condition); - } - - /** - * Removes all custom events from the event queue. - */ - public void resetCustomEvents() { - customEvents.clear(); - } - - /** - * Resets this event manager by removing all events from the event queue. - */ - public synchronized void reset() { - currentTopEventPriority = Integer.MIN_VALUE; - clearAllEvents(true); - customEvents.clear(); - } - - /** - * Changes the interruptible flag for events with a specific priority. - * When an event is interrupted, events with the same priority are allowed to restart the event handler. - * - * @param priority is the priority of the event to set the interruptible flag for. - * @param isInterruptable {@code true} if events with the specified priority must be interruptible - * allowing events with the same priority to restart the event handler. - * {@code false} if events with the specified priority must not be interruptible - * disallowing events with the same priority to restart the event handler. - */ - public void setInterruptible(int priority, boolean isInterruptable) { - if (priority >= 0 && priority < MAX_PRIORITY) { - interruptible[priority] = isInterruptable; - } - } - - /** - * Returns the priority of events belonging to a specific class. - * @param eventClass is a string with the full class name of the event type to get the priority from. - * @return the event priority of the specified event class. - * @see robocode.Event#getPriority() - */ - public int getEventPriority(String eventClass) { - if (eventClass == null) { - return -1; - } - final Event event = eventNames.get(eventClass); - if (event == null) { - return -1; - } - return event.getPriority(); - } - - /** - * Sets the event priority of events belonging to a specific class. - * @param eventClass is a string with the full class name of the event type to set the priority for. - * @param priority is the new priority - */ - public void setEventPriority(String eventClass, int priority) { - if (eventClass == null) { - return; - } - final Event event = eventNames.get(eventClass); - if (event == null) { - robotProxy.println("SYSTEM: Unknown event class: " + eventClass); - return; - } - if (HiddenAccess.isCriticalEvent(event)) { - robotProxy.println("SYSTEM: You may not change the priority of a system event."); - } - HiddenAccess.setEventPriority(event, priority); - } - - /** - * Registers the full and simple class names of all events used by {@link #getEventPriority(String)} and - * {@link #setEventPriority(String, int)} and sets the default priority of each event class. - */ - private void registerEventNames() { - eventNames = new HashMap(); - dummyScannedRobotEvent = new ScannedRobotEvent(null, 0, 0, 0, 0, 0, false); - registerEventNames(new BattleEndedEvent(false, null)); - registerEventNames(new BulletHitBulletEvent(null, null)); - registerEventNames(new BulletHitEvent(null, 0, null)); - registerEventNames(new BulletMissedEvent(null)); - registerEventNames(new DeathEvent()); - registerEventNames(new HitByBulletEvent(0, null)); - registerEventNames(new HitRobotEvent(null, 0, 0, false)); - registerEventNames(new HitWallEvent(0)); - registerEventNames(new KeyPressedEvent(null)); - registerEventNames(new KeyReleasedEvent(null)); - registerEventNames(new KeyTypedEvent(null)); - registerEventNames(new MessageEvent(null, null)); - registerEventNames(new MouseClickedEvent(null)); - registerEventNames(new MouseDraggedEvent(null)); - registerEventNames(new MouseEnteredEvent(null)); - registerEventNames(new MouseExitedEvent(null)); - registerEventNames(new MouseMovedEvent(null)); - registerEventNames(new MousePressedEvent(null)); - registerEventNames(new MouseReleasedEvent(null)); - registerEventNames(new MouseWheelMovedEvent(null)); - registerEventNames(new PaintEvent()); - registerEventNames(new RobotDeathEvent(null)); - registerEventNames(new RoundEndedEvent(0, 0, 0)); - registerEventNames(dummyScannedRobotEvent); - registerEventNames(new SkippedTurnEvent(0)); - registerEventNames(new StatusEvent(null)); - registerEventNames(new WinEvent()); - - // same as any line above but for custom event - final DummyCustomEvent customEvent = new DummyCustomEvent(); - eventNames.put("robocode.CustomEvent", customEvent); // full name with package name - eventNames.put("CustomEvent", customEvent); // only the class name - } - - /** - * Registers the full and simple class name of the specified event and sets the default - * priority of the event class. - * @param event an event belonging to the event class to register the class name for etc. - */ - private void registerEventNames(Event event) { - if (!HiddenAccess.isCriticalEvent(event)) { - HiddenAccess.setDefaultPriority(event); - } - final Class type = event.getClass(); - eventNames.put(type.getName(), event); // full name with package name - eventNames.put(type.getSimpleName(), event); // only the class name - } - - /** - * A dummy CustomEvent used only for registering the class name. - */ - @SuppressWarnings("serial") - private static final class DummyCustomEvent extends CustomEvent { - public DummyCustomEvent() { - super(null); - } - } -} diff --git a/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/HostingRobotProxy.java b/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/HostingRobotProxy.java deleted file mode 100644 index 9fdb31e..0000000 --- a/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/HostingRobotProxy.java +++ /dev/null @@ -1,306 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.host.proxies; - - -import net.sf.robocode.host.events.EventManager; -import net.sf.robocode.host.io.RobotFileSystemManager; -import net.sf.robocode.host.io.RobotOutputStream; -import net.sf.robocode.host.security.RobotThreadManager; -import net.sf.robocode.host.*; -import static net.sf.robocode.io.Logger.logError; -import static net.sf.robocode.io.Logger.logMessage; -import net.sf.robocode.peer.BadBehavior; -import net.sf.robocode.peer.ExecCommands; -import net.sf.robocode.peer.IRobotPeer; -import net.sf.robocode.repository.IRobotItem; -import net.sf.robocode.core.Container; -import robocode.RobotStatus; -import robocode.exception.AbortedException; -import robocode.exception.DeathException; -import robocode.exception.DisabledException; -import robocode.exception.WinException; -import robocode.robotinterfaces.IBasicRobot; -import robocode.robotinterfaces.peer.IBasicRobotPeer; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - - -// XXX Remember to update the .NET version whenever a change is made to this class! - -/** - * @author Pavel Savara (original) - */ -abstract class HostingRobotProxy implements IHostingRobotProxy, IHostedThread { - - private final IRobotItem robotSpecification; - - protected EventManager eventManager; - private final IHostManager hostManager; - protected RobotThreadManager robotThreadManager; - protected RobotFileSystemManager robotFileSystemManager; - private IThreadManager threadManager; - - private IBasicRobot robot; - protected final IRobotPeer peer; - protected IRobotClassLoader robotClassLoader; - - protected final RobotStatics statics; - protected RobotOutputStream out; - - private final Set securityViolations = Collections.synchronizedSet(new HashSet()); - - HostingRobotProxy(IRobotItem robotSpecification, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { - this.peer = peer; - this.statics = statics; - this.hostManager = hostManager; - this.robotSpecification = robotSpecification; - - robotClassLoader = getHost(robotSpecification).createLoader(robotSpecification); - robotClassLoader.setRobotProxy(this); - - out = new RobotOutputStream(); - robotThreadManager = new RobotThreadManager(this); - - loadClassBattle(); - - robotFileSystemManager = new RobotFileSystemManager(this, hostManager.getRobotFilesystemQuota(), - robotSpecification.getWritableDirectory(), robotSpecification.getReadableDirectory(), - robotSpecification.getRootPath()); - - robotFileSystemManager.initialize(); - } - - private JavaHost getHost(IRobotItem robotSpecification) { - return (JavaHost) Container.cache.getComponent("robocode.host." + robotSpecification.getPlatform().toLowerCase()); - } - - public void cleanup() { - robot = null; - - // Remove the file system and the manager - robotFileSystemManager = null; - if (out != null) { - out.close(); - out = null; - } - - if (robotThreadManager != null) { - robotThreadManager.cleanup(); - } - robotThreadManager = null; - - // Cleanup and remove class manager - if (robotClassLoader != null) { - robotClassLoader.cleanup(); - robotClassLoader = null; - } - } - - public RobotOutputStream getOut() { - return out; - } - - public void println(String s) { - out.println(s); - } - - private void println(Throwable ex) { - ex.printStackTrace(out); - } - - public RobotStatics getStatics() { - return statics; - } - - public RobotFileSystemManager getRobotFileSystemManager() { - return robotFileSystemManager; - } - - public ClassLoader getRobotClassloader() { - return (ClassLoader) robotClassLoader; - } - - // ----------- - // battle driven methods - // ----------- - - protected abstract void initializeRound(ExecCommands commands, RobotStatus status); - - public void startRound(ExecCommands commands, RobotStatus status) { - initializeRound(commands, status); - threadManager = ((HostManager) hostManager).getThreadManager(); - robotThreadManager.start(threadManager); - } - - public void forceStopThread() { - if (!robotThreadManager.forceStop()) { - peer.punishBadBehavior(BadBehavior.UNSTOPPABLE); - peer.setRunning(false); - } - } - - public void waitForStopThread() { - if (!robotThreadManager.waitForStop()) { - peer.punishBadBehavior(BadBehavior.UNSTOPPABLE); - peer.setRunning(false); - } - } - - private void loadClassBattle() { - try { - robotClassLoader.loadRobotMainClass(true); - } catch (RuntimeException e) { - println("SYSTEM: Could not load " + statics.getName() + " : "); - println(e); - drainEnergy(); - } - } - - private boolean loadRobotRound() { - robot = null; - try { - threadManager.setLoadingRobot(this); - robot = robotClassLoader.createRobotInstance(); - if (robot == null) { - println("SYSTEM: Skipping robot: " + statics.getName()); - return false; - } - robot.setOut(out); - robot.setPeer((IBasicRobotPeer) this); - eventManager.setRobot(robot); - } catch (IllegalAccessException e) { - println("SYSTEM: Unable to instantiate this robot: " + e); - println("SYSTEM: Is your constructor marked public?"); - println(e); - robot = null; - logError(e); - return false; - } catch (RuntimeException e) { - println("SYSTEM: An error occurred during initialization of " + statics.getName()); - println("SYSTEM: " + e); - println(e); - robot = null; - logError(e); - return false; - } finally { - threadManager.setLoadingRobot(null); - } - return true; - } - - protected abstract void executeImpl(); - - public void run() { - // Only initialize AWT if we are not running in headless mode. - // Bugfix [2833271] IllegalThreadStateException with the AWT-Shutdown thread. - // Read more about headless mode here: - // http://java.sun.com/developer/technicalArticles/J2SE/Desktop/headless/ - if (System.getProperty("java.awt.headless", "true").equals("false")) { - robotThreadManager.initAWT(); - } - - if (robotSpecification.isValid() && loadRobotRound()) { - try { - if (robot != null) { - peer.setRunning(true); - - // Process all events for the first turn. - // This is done as the first robot status event must occur before the robot - // has started running. - eventManager.processEvents(); - - // Call user code - callUserCode(); - } - while (peer.isRunning()) { - executeImpl(); - } - } catch (WinException e) {// Do nothing - } catch (AbortedException e) {// Do nothing - } catch (DeathException e) { - println("SYSTEM: " + statics.getName() + " has died"); - } catch (DisabledException e) { - drainEnergy(); - - String msg = e.getMessage(); - if (msg == null) { - msg = ""; - } else { - msg = ": " + msg; - } - println("SYSTEM: Robot disabled: " + msg); - logMessage("Robot disabled: " + statics.getName()); - } catch (Exception e) { - drainEnergy(); - println(e); - logMessage(statics.getName() + ": Exception: " + e); // without stack here - } catch (ThreadDeath e) { - drainEnergy(); - println(e); - logMessage(statics.getName() + " stopped successfully."); - throw e; // must be re-thrown in order to stop the thread - } catch (RuntimeException t) { - drainEnergy(); - println(t); - logMessage(statics.getName() + ": Throwable: " + t); // without stack here - } finally { - waitForBattleEndImpl(); - } - } else { - drainEnergy(); - peer.punishBadBehavior(BadBehavior.CANNOT_START); - waitForBattleEndImpl(); - } - - peer.setRunning(false); - - // If battle is waiting for us, well, all done! - synchronized (this) { - notifyAll(); - } - } - - private void callUserCode() { - Runnable runnable = robot.getRobotRunnable(); - if (runnable != null) { - runnable.run(); - } - } - - protected abstract void waitForBattleEndImpl(); - - public void drainEnergy() { - peer.drainEnergy(); - } - - public void punishSecurityViolation(String message) { - // Prevent unit tests of failing if multiple threads are calling this method in the same time. - // We only want the a specific type of security violation logged once so we only get one error - // per security violation. - synchronized (securityViolations) { - String key = message; - - if (key.startsWith("Preventing Thread-")) { - key = key.replaceAll("\\d+", "X"); - } - if (!securityViolations.contains(key)) { - securityViolations.add(key); - logError(message); - println("SYSTEM: " + message); - - if (securityViolations.size() == 1) { - peer.drainEnergy(); - peer.punishBadBehavior(BadBehavior.SECURITY_VIOLATION); - } - } - } - } -} diff --git a/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotClassLoader.java b/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotClassLoader.java deleted file mode 100644 index 0993839..0000000 --- a/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotClassLoader.java +++ /dev/null @@ -1,424 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.host.security; - - -import net.sf.robocode.core.Container; -import net.sf.robocode.host.IHostedThread; -import net.sf.robocode.host.IRobotClassLoader; -import net.sf.robocode.io.FileUtil; -import net.sf.robocode.io.Logger; -import net.sf.robocode.io.RobocodeProperties; -import net.sf.robocode.io.URLJarCollector; -import robocode.robotinterfaces.IBasicRobot; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLConnection; -import java.nio.ByteBuffer; -import java.security.*; -import java.security.cert.Certificate; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - - -/** - * This class loader is used by robots. It isolates classes which belong to robot and load them locally. - * General java classes or robocode.api classes are loaded by parent loader and shared with Robocode engine. - * Attempts to load classes of Robocode engine are blocked. - * - * @author Mathew A. Nelson (original) - * @author Flemming N. Larsen (contributor) - * @author Matthew Reeder (contributor) - * @author Robert D. Maupin (contributor) - * @author Nathaniel Troutman (contributor) - */ -public class RobotClassLoader extends URLClassLoader implements IRobotClassLoader { - - static final String UNTRUSTED_URL = "http://robocode.sf.net/untrusted"; - - private static final PermissionCollection EMPTY_PERMISSIONS = new Permissions(); - - private final String fullClassName; - - private ClassLoader parent; - private CodeSource codeSource; - - private IHostedThread robotProxy; - private Class robotClass; - - // Names on classes referenced from the robot class - private Set referencedClasses = new HashSet(); - - // Cached names on found system classes - private Set foundSystemClasses = new HashSet(); - - // Cached warning messages - private String[] staticRobotInstanceWarning; - - public RobotClassLoader(URL robotClassPath, String robotFullClassName) { - super(new URL[] { robotClassPath}, Container.systemLoader); - fullClassName = robotFullClassName; - parent = getParent(); - try { - codeSource = new CodeSource(new URL(UNTRUSTED_URL), (Certificate[]) null); - } catch (MalformedURLException ignored) {} - } - - public void setRobotProxy(Object robotProxy) { - this.robotProxy = (IHostedThread) robotProxy; - } - - public synchronized void addURL(URL url) { - super.addURL(url); - } - - public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (name.startsWith("java.lang")) { - // we always delegate java.lang stuff to parent loader - return super.loadClass(name, resolve); - } - if (RobocodeProperties.isSecurityOn()) { - testPackages(name); - } - if (!name.startsWith("robocode")) { - Class result = loadRobotClassLocaly(name, resolve); - if (result != null) { - // yes, it is in robot's class path - // we loaded it locally - return result; - } - } - - // it is robot API - // or java class - // or security is off - // so we delegate to parent class loader - return parent.loadClass(name); - } - - private void testPackages(String name) throws ClassNotFoundException { - if (name.startsWith("net.sf.robocode")) { - String message = "Robots are not allowed to reference Robocode engine in package: net.sf.robocode"; - - punishSecurityViolation(message); - throw new ClassNotFoundException(message); - } - if (name.startsWith("robocode.control")) { - String message = "Robots are not allowed to reference Robocode engine in package: robocode.control"; - - punishSecurityViolation(message); - throw new ClassNotFoundException(message); - } - if (RobocodeProperties.isSecurityOn() && name.startsWith("javax.swing")) { - String message = "Robots are not allowed to reference Robocode engine in package: javax.swing"; - - punishSecurityViolation(message); - throw new ClassNotFoundException(message); - } - } - - private Class loadRobotClassLocaly(String name, boolean resolve) throws ClassNotFoundException { - Class result = findLoadedClass(name); - if (result == null) { - ByteBuffer resource = findLocalResource(name); - if (resource != null) { - result = defineClass(name, resource, codeSource); - if (resolve) { - resolveClass(result); - } - ClassAnalyzer.getReferencedClasses(resource, referencedClasses); - } - } - return result; - } - - // this whole fun is there to be able to provide defineClass with bytes - // we need to call defineClass to be able to set codeSource to untrustedLocation - private ByteBuffer findLocalResource(final String name) { - return AccessController.doPrivileged(new PrivilegedAction() { - public ByteBuffer run() { - // try to find it in robot's class path - // this is URL, don't change to File.pathSeparator - String path = name.replace('.', '/').concat(".class"); - URL url = findResource(path); - ByteBuffer result = null; - InputStream is = null; - BufferedInputStream bis = null; - - if (url != null) { - try { - URLConnection connection = URLJarCollector.openConnection(url); - - is = connection.getInputStream(); - bis = new BufferedInputStream(is); - - result = ByteBuffer.allocate(1024 * 8); - boolean done = false; - - do { - do { - int res = bis.read(result.array(), result.position(), result.remaining()); - - if (res == -1) { - done = true; - break; - } - result.position(result.position() + res); - } while (result.remaining() != 0); - result.flip(); - if (!done) { - result = ByteBuffer.allocate(result.capacity() * 2).put(result); - } - } while (!done); - - } catch (IOException e) { - Logger.logError(e); - return null; - } finally { - FileUtil.cleanupStream(bis); - FileUtil.cleanupStream(is); - } - } - return result; - } - }); - } - - private void punishSecurityViolation(String message) { - if (robotProxy != null) { - robotProxy.punishSecurityViolation(message); - } - } - - protected PermissionCollection getPermissions(CodeSource codesource) { - if (RobocodeProperties.isSecurityOn()) { - return EMPTY_PERMISSIONS; - } - return super.getPermissions(codesource); - } - - public String[] getReferencedClasses() { - return referencedClasses.toArray(new String[referencedClasses.size()]); - } - - public synchronized Class loadRobotMainClass(boolean resolve) throws ClassNotFoundException { - try { - if (robotClass == null) { - robotClass = loadClass(fullClassName, resolve); - - if (!IBasicRobot.class.isAssignableFrom(robotClass)) { - // that's not robot - return null; - } - if (resolve) { - // resolve methods to see more referenced classes - robotClass.getMethods(); - - // iterate thru dependencies until we didn't found any new - HashSet clone; - - do { - clone = new HashSet(referencedClasses); - for (String reference : clone) { - testPackages(reference); - if (!isSystemClass(reference)) { - loadClass(reference, true); - } - } - } while (referencedClasses.size() != clone.size()); - } - } else { - warnIfStaticRobotInstanceFields(); - } - } catch (RuntimeException e) { - robotClass = null; - throw new ClassNotFoundException(e.getMessage(), e); - } - return robotClass; - } - - public IBasicRobot createRobotInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException { - loadRobotMainClass(true); - return (IBasicRobot) robotClass.newInstance(); - } - - public void cleanup() { - // Bug fix [2930266] - Robot static data isn't being GCed after battle - for (String className : getReferencedClasses()) { - cleanStaticReferences(className); - } - - parent = null; - codeSource = null; - robotProxy = null; - robotClass = null; - referencedClasses = null; - foundSystemClasses = null; - } - - /** - * Cleans all static field references on a class. - * - * @param className the name of the class containing the static references to clean. - */ - private void cleanStaticReferences(String className) { - if (isSystemClass(className)) { - return; - } - Class type = null; - try { - type = loadRobotClassLocaly(className, false); - if (type != null) { - for (Field field : getAllFields(new ArrayList(), type)) { - if (isStaticReference(field)) { - cleanStaticReference(field); - } - } - } - } catch (RuntimeException t) { - Logger.logError(t); - } - } - - private void warnIfStaticRobotInstanceFields() { - if (staticRobotInstanceWarning == null) { - List staticRobotReferences = new ArrayList(); - - for (String className : getReferencedClasses()) { // Bug fix [3028102] - ConcurrentModificationException - if (isSystemClass(className)) { - continue; - } - Class type = null; - try { - type = loadRobotClassLocaly(className, false); - } catch (RuntimeException t) { - continue; - } - if (type != null) { - for (Field field : getAllFields(new ArrayList(), type)) { - if (isStaticReference(field) && IBasicRobot.class.isAssignableFrom(field.getType()) - && field.getAnnotation(robocode.annotation.SafeStatic.class) == null) { - staticRobotReferences.add(field); - } - } - } - } - if (staticRobotReferences.size() > 0) { - StringBuilder buf = new StringBuilder(); - - buf.append("Warning: ").append(fullClassName).append( - " uses static reference to a robot with the following field(s):"); - - for (Field field : staticRobotReferences) { - buf.append("\n\t").append(field.getDeclaringClass().getName()).append('.').append(field.getName()).append(", which points to a ").append( - field.getType().getName()); - } - - staticRobotInstanceWarning = new String[] { - buf.toString(), - "Static references to robots can cause unwanted behaviour with the robot using these.", - "Please change static robot references to non-static references and recompile the robot."}; - } else { - staticRobotInstanceWarning = new String[] {}; // Signal that there is no warnings to cache - } - } else if (staticRobotInstanceWarning.length == 0) { - return; // Return, as no warnings should be written out in the robot console - } - - // Write out warnings to the robot console - if (robotProxy != null) { - for (String line : staticRobotInstanceWarning) { - robotProxy.getOut().println("SYSTEM: " + line); - } - } - } - - /** - * Cleans a static field reference class, even when it is 'private static final' - * - * @param field the field to clean, if it is a static reference. - */ - private void cleanStaticReference(Field field) { - if (field.getName().startsWith("const__")) { - // Ignore 'const__' fields used with e.g. the Clojure language - return; - } - field.setAccessible(true); - try { - // In order to set a 'private static field', we need to fix the modifier, i.e. use magic! ;-) - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - int modifiers = modifiersField.getInt(field); - modifiersField.setInt(field, modifiers & ~Modifier.FINAL); // Remove the FINAL modifier - field.set(null, null); - - } catch (RuntimeException ignore) {} - } - - /** - * Gets all fields of a class (public, protected, private) and the ones inherited from all super classes. - * @param fields the list where the fields will be added as a result of calling this method. - * @param type the class to retrieve all the fields from - * @return the list specified as input parameter containing all the retrieved fields - */ - private List getAllFields(List fields, Class type) { - if (type == null || isSystemClass(type.getName())) { - return fields; - } - try { - for (Field field: type.getDeclaredFields()) { - fields.add(field); - } - } catch (RuntimeException ignore) {// NoClassDefFoundError does occur with some robots, e.g. sgp.Drunken [1.12] - // We ignore all exceptions and errors here so we can proceed to retrieve - // field from super classes. - } - if (type.getSuperclass() != null) { - fields = getAllFields(fields, type.getSuperclass()); - } - return fields; - } - - /** - * Checks if a specified class name is a Java system class or internal Robocode class. - * @param className the class name to check. - * @return true if the class name is a system class; false otherwise. - */ - private boolean isSystemClass(String className) { - boolean isSystemClass = foundSystemClasses.contains(className); - if (!isSystemClass) { - try { - if (findSystemClass(className) != null) { - foundSystemClasses.add(className); - isSystemClass = true; - } - } catch (ClassNotFoundException ignore) {} - } - return isSystemClass; - } - - /** - * Checks if a specified field is a static reference. - * - * @param field the field to check. - * @return true if the field is static reference; false otherwise. - */ - private static boolean isStaticReference(Field field) { - return Modifier.isStatic(field.getModifiers()) - && !(field.getType().isPrimitive() || field.isEnumConstant() || field.isSynthetic()); - } -} diff --git a/workspace_robo4/robocode.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java b/workspace_robo4/robocode.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java deleted file mode 100644 index e4c6d0a..0000000 --- a/workspace_robo4/robocode.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java +++ /dev/null @@ -1,705 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.installer; - - -import javax.swing.*; - -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.*; -import java.net.URL; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.jar.JarInputStream; - - -/** - * Installer for Robocode. - * - * @author Mathew A. Nelsen (original) - * @author Flemming N. Larsen (contributor) - */ -public class AutoExtract implements ActionListener { - private JDialog licenseDialog; - private boolean accepted; - private static final String[] SPINNER = { "-", "\\", "|", "/"}; - private String message = ""; - private static File installDir; - private static final String osName = System.getProperty("os.name"); - private static final double osVersion = doubleValue(System.getProperty("os.version")); - private static final String javaVersion = System.getProperty("java.version"); - - private static double doubleValue(String s) { - s = s.replaceAll("[^.0-9]", ""); // Remove invalid characters, e.g. "3.0-ARCH" become "3.0" - - int p = s.indexOf("."); - - if (p >= 0) { - p = s.indexOf(".", p + 1); - } - if (p >= 0) { - s = s.substring(0, p); - } - - double d = 0.0; - - try { - d = Double.parseDouble(s); - } catch (NumberFormatException e) { - e.printStackTrace(System.err); - } - - return d; - } - - private boolean acceptLicense() { - StringBuffer licenseText = new StringBuffer(); - - InputStream is; - - try { - JarFile extractJar = new JarFile("extract.jar"); - - is = extractJar.getInputStream(extractJar.getJarEntry("license/cpl-v10.html")); - } catch (IOException e) { - return true; - } - if (is == null) { - return true; - } - - InputStreamReader isr = null; - BufferedReader br = null; - - try { - isr = new InputStreamReader(is); - br = new BufferedReader(isr); - - String line = br.readLine(); - - while (line != null) { - licenseText.append(line); - line = br.readLine(); - } - return acceptReject(licenseText.toString()); - - } catch (IOException e) { - System.err.println("Could not read line from license file: " + e); - } finally { - if (br != null) { - try { - br.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - if (isr != null) { - try { - isr.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - return true; - } - - private boolean acceptReject(String text) { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - licenseDialog = new JDialog(); - licenseDialog.setTitle("License Agreement"); - licenseDialog.setModal(true); - licenseDialog.setLocation((screenSize.width - 500) / 2, (screenSize.height - 400) / 2); - licenseDialog.setSize(500, 400); - JTextPane t = new JTextPane(); - - t.setContentType("text/html"); - t.setText(text); - t.setFont(new Font("Dialog", Font.PLAIN, 12)); - t.setEditable(false); - - JScrollPane s = new JScrollPane(); - - s.setViewportView(t); - - licenseDialog.getContentPane().setLayout(new BorderLayout()); - licenseDialog.getContentPane().add(s, BorderLayout.CENTER); - - JPanel p = new JPanel(); - - p.setLayout(new BorderLayout()); - JButton b1 = new JButton("Accept"); - JButton b2 = new JButton("Cancel"); - - p.add(b1, BorderLayout.WEST); - p.add(b2, BorderLayout.EAST); - - b1.addActionListener(this); - b2.addActionListener(this); - - licenseDialog.getContentPane().add(p, BorderLayout.SOUTH); - - licenseDialog.setVisible(true); - - return accepted; - } - - public void actionPerformed(ActionEvent e) { - accepted = e.getActionCommand().equals("Accept"); - licenseDialog.dispose(); - licenseDialog = null; - } - - private boolean extract(File installDir) { - JDialog statusDialog = new JDialog(); - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - int width = 500; - int height = 100; - - statusDialog.setTitle("Installing"); - statusDialog.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2); - statusDialog.setSize(width, height); - JLabel status = new JLabel(); - - statusDialog.getContentPane().setLayout(new BorderLayout()); - statusDialog.getContentPane().add(status, BorderLayout.CENTER); - - statusDialog.setVisible(true); - - FileOutputStream fos; - String entryName; - - byte buf[] = new byte[2048]; - - final String name = AutoExtract.class.getName().replaceAll("\\.", "/") + ".class"; - String urlJar = AutoExtract.class.getClassLoader().getResource(name).toString(); - final String src = urlJar.substring("jar:file:/".length(), urlJar.indexOf("!/")); - - if (src.indexOf('!') > -1) { - message = src + "\nContains an exclamation point. Please move the file to a different directory."; - JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); - return false; - } - JarInputStream jarIS = null; - - try { - final URL url = new URL("file:/" + src); - InputStream is = url.openStream(); - - jarIS = new JarInputStream(is); - - JarEntry entry; - - while ((entry = jarIS.getNextJarEntry()) != null) { - int spin = 0; - - entryName = entry.getName(); - if (entry.isDirectory()) { - if (!entryName.startsWith("net") && !(entryName.equals("desktop") && isFreeBSD())) { - File dir = new File(installDir, entry.getName()); - if (!dir.exists() && !dir.mkdirs()) { - System.err.println("Can't create dir: " + dir); - } - } - } else if (!entryName.equals(name)) { - - // Skip .bat, .sh, and .command files depending on which OS Robocode is installed - - final String entryNameLC = entryName.toLowerCase(); - - boolean skipEntry = false; - - final boolean isBatFile = entryNameLC.length() > ".bat".length() && entryNameLC.endsWith(".bat"); - final boolean isShFile = entryNameLC.length() > ".sh".length() && entryNameLC.endsWith(".sh"); - final boolean isCommandFile = entryNameLC.length() > ".command".length() - && entryNameLC.endsWith(".command"); - final boolean isDesktopFile = entryNameLC.startsWith("desktop/"); - - // Unix systems and Mac OS X - if (File.separatorChar == '/') { - // Skip .bat files under Unix and Mac OS X - // Skip .command files under Unix - skipEntry = isBatFile || (isCommandFile && !isMacOSX()) || (isDesktopFile && !isFreeBSD()); - } else { - // Under Windows the .sh and .command files are skipped - skipEntry = isShFile || isCommandFile || isDesktopFile; - } - - // If we are not skipping the entry, then copy from our .jar into the installation dir - if (!skipEntry) { - status.setText(entryName + " " + SPINNER[spin++]); - - File out = new File(installDir, entryName); - - File parentDirectory = new File(out.getParent()); - if (!parentDirectory.exists() && !parentDirectory.mkdirs()) { - System.err.println("Can't create dir: " + parentDirectory); - } - fos = new FileOutputStream(out); - - int index = 0; - int num; - int count = 0; - - while ((num = jarIS.read(buf, 0, 2048)) != -1) { - fos.write(buf, 0, num); - index += num; - count++; - if (count > 80) { - status.setText(entryName + " " + SPINNER[spin++] + " (" + index + " bytes)"); - if (spin > 3) { - spin = 0; - } - count = 0; - } - } - fos.close(); - - // Set file permissions for .sh and .command files under Unix and Mac OS X - if (File.separatorChar == '/') { - if (isShFile || isCommandFile) { - // Grant read and execute access for everyone and also write access for the owner of the file - Runtime.getRuntime().exec("chmod 755 " + out.toString()); - } - } - - status.setText(entryName + " " + SPINNER[spin] + " (" + index + " bytes)"); - } - } - } - statusDialog.dispose(); - return true; - } catch (IOException e) { - message = "Installation failed: " + e; - JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); - return false; - } finally { - if (jarIS != null) { - try { - jarIS.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - public static void main(String argv[]) { - String suggestedDirName; - - if (argv.length == 1) { - suggestedDirName = argv[0]; - } else if (isWindowsOS()) { - suggestedDirName = "C:\\robocode\\"; - } else { - suggestedDirName = System.getProperty("user.home") + File.separator + "robocode" + File.separator; - } - - String message; - - if (install(new File(suggestedDirName))) { - message = "Installation successful"; - } else { - message = "Installation cancelled"; - } - - // Delete the class file with the installer and it's parent folders in the robocode home dir - if (installDir != null) { - String installerPath = AutoExtract.class.getName().replaceAll("\\.", "/") + "$1.class"; - - deleteFileAndParentDirsIfEmpty(new File(installDir, installerPath)); - } - - JOptionPane.showMessageDialog(null, message); - } - - private static boolean install(File suggestedDir) { - // Verify that the Java version is version 6 (1.6.0) or newer - if (javaVersion.startsWith("1.") && javaVersion.charAt(2) < '5') { - final String message = "Robocode requires Java 6 (1.6.0) or newer.\n" - + "Your system is currently running Java " + javaVersion + ".\n" - + "If you have not installed (or activated) at least\n" + "JRE 6 or JDK 6, please do so."; - - JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); - System.err.println(message); - return false; - } - - // Set native look and feel - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (RuntimeException t) {// For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF - } - - AutoExtract extractor = new AutoExtract(); - - if (extractor.acceptLicense()) { - boolean done = false; - - while (!done) { - int rc = JOptionPane.showConfirmDialog(null, - "Robocode will be installed in:\n" + suggestedDir + "\nIs this ok?", "Installing Robocode", - JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); - - if (rc == JOptionPane.YES_OPTION) { - installDir = suggestedDir; - done = true; - } else if (rc == JOptionPane.NO_OPTION) { - Object r = JOptionPane.showInputDialog(null, "Please type in the installation directory", - "Installation Directory", JOptionPane.PLAIN_MESSAGE, null, null, suggestedDir); - - if (r != null) { - suggestedDir = new File(((String) r).trim()); - } else { - return false; - } - } else if (rc == JOptionPane.CANCEL_OPTION) { - return false; - } - } - if (!installDir.exists() && !installDir.mkdirs()) { - System.err.println("Can't create dir: " + installDir); - return false; - } - deleteOldLibs(installDir); - - // The .robotcache has been renamed to .data - File robotsCacheDir = new File(installDir, "robots/.robotcache"); - File robotsDataDir = new File(installDir, "robots/.data"); - - if (robotsCacheDir.exists()) { - // Rename ".robotcache" into ".data" - robotsCacheDir.renameTo(robotsDataDir); - } - - // Fix problem with .data starting with a underscore dir by - // renaming files containing ".data/_" into ".data" - if (robotsDataDir.exists()) { - File underScoreDir = new File(robotsDataDir, "_"); - String[] list = underScoreDir.list(); - - if (list != null) { - for (String fileName : list) { - File file = new File(underScoreDir, fileName); - - file.renameTo(new File(robotsDataDir, fileName)); - } - underScoreDir.delete(); - } - } - - // Create shortcuts and file associations - if (extractor.extract(installDir)) { - extractor.createShortcuts(installDir, "robocode.bat", "Robocode", "Robocode"); - extractor.createFileAssociations(installDir); - return true; - } - } - return false; - } - - private static void deleteOldLibs(File installDir) { - File libs = new File(installDir, "libs"); - - if (libs.exists()) { - final File[] del = libs.listFiles(new FilenameFilter() { - - public boolean accept(File dir, String name) { - String test = name.toLowerCase(); - - return test.endsWith(".jar") || test.endsWith(".dll"); - } - }); - - for (File d : del) { - if (!d.delete()) { - System.err.println("Can't delete: " + d); - } - } - } - } - - private static boolean deleteDir(File dir) { - if (dir.isDirectory()) { - for (File file : dir.listFiles()) { - if (file.isDirectory()) { - // Skip directories ending with ".data" - if (file.getName().endsWith(".data")) { - continue; - } - try { - // Test for symlink and ignore. - // Robocode won't create one, but just in case a user does... - if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) { - deleteDir(file); - if (file.exists() && !file.delete()) { - System.err.println("Can't delete: " + file); - } - } else { - System.out.println("Warning: " + file + " may be a symlink. It has been ignored"); - } - } catch (IOException e) { - System.out.println( - "Warning: Cannot determine canonical file for " + file + ". It has been ignored"); - } - } else { - if (file.exists() && !file.delete()) { - System.err.println("Can't delete: " + file); - } - } - } - return dir.delete(); - } - return false; - } - - private void createShortcuts(File installDir, String runnable, String folder, String name) { - if (osName.toLowerCase().indexOf("win") == 0) { - if (createWindowsShortcuts(installDir, runnable, folder, name) == false) { - JOptionPane.showMessageDialog(null, - message + "\n" + "To start Robocode, enter the following at a command prompt:\n" + "cd " - + installDir.getAbsolutePath() + "\n" + "robocode.bat"); - } - } else if (osName.toLowerCase().indexOf("mac") == 0) { - if (osVersion >= 10.1) { - JOptionPane.showMessageDialog(null, - message + "\n" + "To start Robocode, browse to " + installDir + " then double-click robocode.sh\n"); - } else { - JOptionPane.showMessageDialog(null, - message + "\n" + "To start Robocode, enter the following at a command prompt:\n" - + installDir.getAbsolutePath() + "/robocode.sh"); - } - } else { - JOptionPane.showMessageDialog(null, - message + "\n" + "To start Robocode, enter the following at a command prompt:\n" - + installDir.getAbsolutePath() + "/robocode.sh"); - } - } - - private boolean createWindowsShortcuts(File installDir, String runnable, String folder, String name) { - int rc = JOptionPane.showConfirmDialog(null, - "Would you like to install a shortcut to Robocode in the Start menu? (Recommended)", "Create Shortcuts", - JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - - if (rc != JOptionPane.YES_OPTION) { - return false; - } - - final String command = getWindowsCmd() + " cscript.exe "; - - try { - File shortcutMaker = new File(installDir, "makeshortcut.vbs"); - PrintStream out = new PrintStream(new FileOutputStream(shortcutMaker)); - - out.println("WScript.Echo(\"Creating shortcuts...\")"); - out.println("Set Shell = CreateObject (\"WScript.Shell\")"); - out.println("Set fso = CreateObject(\"Scripting.FileSystemObject\")"); - out.println("ProgramsPath = Shell.SpecialFolders(\"Programs\")"); - out.println("if (not(fso.folderExists(ProgramsPath + \"\\\\" + folder + "\"))) Then"); - out.println(" fso.CreateFolder(ProgramsPath + \"\\\\" + folder + "\")"); - out.println("End If"); - out.println("Set link = Shell.CreateShortcut(ProgramsPath + \"\\\\" + folder + "\\\\" + name + ".lnk\")"); - out.println("link.Arguments = \"\""); - out.println("link.Description = \"" + name + "\""); - out.println("link.HotKey = \"\""); - out.println("link.IconLocation = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + "robocode.ico,0\""); - out.println("link.TargetPath = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + runnable + "\""); - out.println("link.WindowStyle = 1"); - out.println("link.WorkingDirectory = \"" + escaped(installDir.getAbsolutePath()) + "\""); - out.println("link.Save()"); - out.println("DesktopPath = Shell.SpecialFolders(\"Desktop\")"); - out.println("Set link = Shell.CreateShortcut(DesktopPath + \"\\\\" + name + ".lnk\")"); - out.println("link.Arguments = \"\""); - out.println("link.Description = \"" + name + "\""); - out.println("link.HotKey = \"\""); - out.println("link.IconLocation = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + "robocode.ico,0\""); - out.println("link.TargetPath = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + runnable + "\""); - out.println("link.WindowStyle = 1"); - out.println("link.WorkingDirectory = \"" + escaped(installDir.getAbsolutePath()) + "\""); - out.println("link.Save()"); - out.println("WScript.Echo(\"Shortcuts created.\")"); - - out.close(); - - Process p = Runtime.getRuntime().exec(command + " makeshortcut.vbs", null, installDir); - int rv = p.waitFor(); - - if (rv != 0) { - System.err.println("Can't create shortcut: " + shortcutMaker); - return false; - } - JOptionPane.showMessageDialog(null, - message + "\n" + "A Robocode program group has been added to your Start menu\n" - + "A Robocode icon has been added to your desktop."); - if (!shortcutMaker.delete()) { - System.err.println("Can't delete: " + shortcutMaker); - } - return true; - } catch (IOException e) { - e.printStackTrace(System.err); - } catch (InterruptedException e) { - e.printStackTrace(System.err); - } - - return false; - } - - private void createFileAssociations(File installDir) { - if (isWindowsOS()) { - createWindowsFileAssociations(installDir); - } - } - - private void createWindowsFileAssociations(File installDir) { - int rc = JOptionPane.showConfirmDialog(null, - "Would you like to create file associations for Robocode in\n" - + "the Windows Registry for the file extensions .battle and .br?\n" - + "Please notice that you might need to grant permission to add\n" - + "the file associations in the Registry, and you must be an\n" - + "administrator or granted permission to change the registry.", - "Create File Associations", - JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE); - - if (rc != JOptionPane.YES_OPTION) { - return; - } - - File file = null; - PrintStream out = null; - - try { - file = new File(installDir + "\\FileAssoc.reg"); - - out = new PrintStream(new FileOutputStream(file)); - - String installPath = installDir.getAbsolutePath(); - - out.print( - createWindowsRegistryFileAssociation(installPath, ".battle", "Robocode.BattleSpecification", - "Robocode Battle Specification", "-battle")); - out.print( - createWindowsRegistryFileAssociation(installPath, ".br", "Robocode.BattleRecord", "Robocode Battle Record", - "-replay")); - - out.close(); - out = null; - - Process p = Runtime.getRuntime().exec(getWindowsCmd() + file.getAbsolutePath(), null, null); - int rv; - - try { - rv = p.waitFor(); - if (rv != 0) { - System.err.println("Could not create association(s)"); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (out != null) { - out.close(); - } - if (file != null) { - if (!file.delete()) { - System.err.println("Could not delete the file: " + file); - } - } - } - } - - private static String createWindowsRegistryFileAssociation(String installDir, String fileExt, String progId, String description, String robocodeCmdParam) { - StringBuffer sb = new StringBuffer(); - - final String HKCR = "[HKEY_CLASSES_ROOT\\"; - - sb.append("REGEDIT4\n"); - sb.append(HKCR).append(fileExt).append("]\n"); - sb.append("@=\"").append(progId).append("\"\n"); - sb.append(HKCR).append(progId).append("]\n"); - sb.append("@=\"").append(description).append("\"\n"); - sb.append(HKCR).append(progId).append("\\shell]\n"); - sb.append(HKCR).append(progId).append("\\shell\\open]\n"); - sb.append(HKCR).append(progId).append("\\shell\\open\\command]\n"); - sb.append("@=\"").append(getWindowsCmd()).append("\\\"cd \\\"").append(installDir.replaceAll("[\\\\]", "\\\\\\\\")).append("\\\" && robocode.bat ").append(robocodeCmdParam).append( - " \\\"%1\\\"\\\"\"\n"); - - return sb.toString(); - } - - private static String escaped(String s) { - StringBuffer eascaped = new StringBuffer(); - - for (int i = 0; i < s.length(); i++) { - if (s.charAt(i) == '\\') { - eascaped.append('\\'); - } - eascaped.append(s.charAt(i)); - } - return eascaped.toString(); - } - - private static boolean isWindowsOS() { - return osName.startsWith("Windows "); - } - - private static boolean isMacOSX() { - return osName.startsWith("Mac OS X"); - } - - private static boolean isFreeBSD() { - return osName.equals("FreeBSD"); - } - - private static String getWindowsCmd() { - String os = System.getProperty("os.name"); - - return ((os.equals("Windows 95") || os.equals("Windows 95") || os.equals("Windows ME")) - ? "command.com" - : "cmd.exe") - + " /C "; - } - - /** - * Deletes a file and afterwards deletes the parent directories that are empty. - * - * @param file the file or directory to delete - * @return true if success - */ - private static boolean deleteFileAndParentDirsIfEmpty(final File file) { - boolean wasDeleted = false; - - if (file != null && file.exists()) { - if (file.isDirectory()) { - wasDeleted = deleteDir(file); - } else { - wasDeleted = file.delete(); - - File parent = file; - - while (wasDeleted && (parent = parent.getParentFile()) != null) { - // Delete parent directory, but only if it is empty - File[] files = parent.listFiles(); - - if (files != null && files.length == 0) { - wasDeleted = deleteDir(parent); - } else { - wasDeleted = false; - } - } - } - } - return wasDeleted; - } -} diff --git a/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/FileTransfer.java b/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/FileTransfer.java deleted file mode 100644 index 09004c4..0000000 --- a/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/FileTransfer.java +++ /dev/null @@ -1,657 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.roborumble.netengine; - - -import java.io.*; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; -import java.util.Properties; -import java.util.zip.GZIPInputStream; -import java.util.zip.InflaterInputStream; - -import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; - - -/** - * Utility class for downloading files from the net and copying files. - * - * @author Flemming N. Larsen (original) - */ -public class FileTransfer { - - private final static int DEFAULT_CONNECTION_TIMEOUT = 10000; // 10 seconds - private final static int DEFAULT_READ_TIMEOUT = 10000; // 10 seconds - private final static int DEFAULT_SESSION_TIMEOUT = 10000; // 10 seconds - - private static int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; - private static int readTimeout = DEFAULT_READ_TIMEOUT; - private static int sessionTimeout = DEFAULT_SESSION_TIMEOUT; - - static { - readProperties(); - } - - /** - * Represents the download status returned when downloading files. - */ - public enum DownloadStatus { - OK, // The download was succesful - COULD_NOT_CONNECT, // Connection problem - FILE_NOT_FOUND, // The file to download was not found - } - - - /** - * Daemon worker thread containing a 'finish' flag for waiting and notifying when the thread has finished it's job. - */ - private static class WorkerThread extends Thread { - - final Object monitor = new Object(); - - volatile boolean isFinished; - - public WorkerThread(String name) { - super(name); - setDaemon(true); - } - - void notifyFinish() { - // Notify that this thread is finish - synchronized (monitor) { - isFinished = true; - monitor.notifyAll(); - } - } - } - - /* - * Returns a session id for keeping a session on a HTTP site. - * - * @param url is the url of the HTTP site. - * - * @return a session id for keeping a session on a HTTP site or null if no session is available. - */ - public static String getSessionId(String url) { - HttpURLConnection conn = null; - - try { - // Open connection - conn = FileTransfer.connectToHttpInputConnection(new URL(url)); - if (conn == null) { - throw new IOException("Could not open connection to '" + url + "'"); - } - - // Get a session id if available - final GetSessionIdThread sessionIdThread = new GetSessionIdThread(conn); - - sessionIdThread.start(); - - // Wait for the session id - synchronized (sessionIdThread.monitor) { - while (!sessionIdThread.isFinished) { - try { - sessionIdThread.monitor.wait(sessionTimeout); - sessionIdThread.interrupt(); - } catch (InterruptedException e) { - // Immediately reasserts the exception by interrupting the caller thread itself - Thread.currentThread().interrupt(); - - return null; - } - } - } - - // Return the session id - return sessionIdThread.sessionId; - - } catch (final IOException e) { - return null; - } finally { - // Make sure the connection is disconnected. - // This will cause threads using the connection to throw an exception - // and thereby terminate if they were hanging. - if (conn != null) { - conn.disconnect(); - } - } - } - - /** - * Worker thread used for getting the session id of an already open HTTP connection. - */ - private final static class GetSessionIdThread extends WorkerThread { - - // The resulting session id to read out - String sessionId; - - final HttpURLConnection conn; - - GetSessionIdThread(HttpURLConnection conn) { - super("FileTransfer: Get session ID"); - this.conn = conn; - } - - @Override - public void run() { - try { - // Get the cookie value - final String cookieVal = conn.getHeaderField("Set-Cookie"); - - // Extract the session id from the cookie value - if (cookieVal != null) { - sessionId = cookieVal.substring(0, cookieVal.indexOf(";")); - } - } catch (final Exception e) { - sessionId = null; - } - // Notify that this thread is finish - notifyFinish(); - } - } - - /** - * Downloads a file from a HTTP site. - * - * @param url is the url of the HTTP site to download the file from. - * @param filename is the filename of the destination file. - * @param sessionId is an optional session id if the download is session based. - * @return the download status, which is DownloadStatus.OK if the download completed successfully; otherwise an - * error occurred. - */ - public static DownloadStatus download(String url, String filename, String sessionId) { - HttpURLConnection conn = null; - - try { - // Create connection - conn = connectToHttpInputConnection(new URL(url), sessionId); - if (conn == null) { - throw new IOException("Could not open connection to: " + url); - } - - // Begin the download - final DownloadThread downloadThread = new DownloadThread(conn, filename); - - downloadThread.start(); - - // Wait for the download to complete - synchronized (downloadThread.monitor) { - while (!downloadThread.isFinished) { - try { - downloadThread.monitor.wait(); - } catch (InterruptedException e) { - return DownloadStatus.COULD_NOT_CONNECT; - } - } - } - - // Return the download status - return downloadThread.status; - - } catch (final IOException e) { - return DownloadStatus.COULD_NOT_CONNECT; - } finally { - // Make sure the connection is disconnected. - // This will cause threads using the connection to throw an exception - // and thereby terminate if they were hanging. - try { - if (conn != null) { - conn.disconnect(); - } - } catch (RuntimeException ignore) {// we expect this, right ? - } - } - } - - /** - * Worker thread used for downloading a file from an already open HTTP connection. - */ - private final static class DownloadThread extends WorkerThread { - - // The download status to be read out - DownloadStatus status = DownloadStatus.COULD_NOT_CONNECT; // Default error - - final HttpURLConnection conn; - final String filename; - - InputStream in; - OutputStream out; - - DownloadThread(HttpURLConnection conn, String filename) { - super("FileTransfer: Download"); - this.conn = conn; - this.filename = filename; - } - - @Override - public void run() { - try { - // Start getting the response code - final GetResponseCodeThread responseThread = new GetResponseCodeThread(conn); - - responseThread.start(); - - // Wait for the response to finish - synchronized (responseThread.monitor) { - while (!responseThread.isFinished) { - try { - responseThread.monitor.wait(sessionTimeout); - responseThread.interrupt(); - } catch (InterruptedException e) { - notifyFinish(); - return; - } - } - } - - final int responseCode = responseThread.responseCode; - - if (responseCode == -1) { - // Terminate if we did not get the response code - notifyFinish(); - return; - - } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) { - // Terminate if the HTTP page containing the file was not found - status = DownloadStatus.FILE_NOT_FOUND; - notifyFinish(); - return; - - } else if (responseCode != HttpURLConnection.HTTP_OK) { - // Generally, terminate if did not receive a OK response - notifyFinish(); - return; - } - - // Start getting the size of the file to download - final GetContentLengthThread contentLengthThread = new GetContentLengthThread(conn); - - contentLengthThread.start(); - - // Wait for the file size - synchronized (contentLengthThread.monitor) { - while (!contentLengthThread.isFinished) { - try { - contentLengthThread.monitor.wait(sessionTimeout); - contentLengthThread.interrupt(); - } catch (InterruptedException e) { - notifyFinish(); - return; - } - } - } - - final int size = contentLengthThread.contentLength; - - if (size == -1) { - // Terminate if we did not get the content length - notifyFinish(); - return; - } - - // Get the input stream from the connection - in = getInputStream(conn); - - // Prepare the output stream for the file output - out = new FileOutputStream(filename); - - // Download the file - - final byte[] buf = new byte[4096]; - - int totalRead = 0; - int bytesRead; - - // Start thread for reading bytes into the buffer - - while (totalRead < size) { - // Start reading bytes into the buffer - final ReadInputStreamToBufferThread readThread = new ReadInputStreamToBufferThread(in, buf); - - readThread.start(); - - // Wait for the reading to finish - synchronized (readThread.monitor) { - while (!readThread.isFinished) { - try { - readThread.monitor.wait(sessionTimeout); - readThread.interrupt(); - } catch (InterruptedException e) { - notifyFinish(); - return; - } - } - } - - bytesRead = readThread.bytesRead; - if (bytesRead == -1) { - // Read completed has completed - notifyFinish(); - break; - } - - // Write the byte buffer to the output - out.write(buf, 0, bytesRead); - - totalRead += bytesRead; - } - - // If we reached this point, the download was successful - status = DownloadStatus.OK; - - notifyFinish(); - - } catch (final IOException e) { - status = DownloadStatus.COULD_NOT_CONNECT; - } finally { - // Make sure the input stream is closed - if (in != null) { - try { - in.close(); - } catch (final IOException e) { - e.printStackTrace(); - } - } - // Make sure the output stream is closed - if (out != null) { - try { - out.close(); - } catch (final IOException e) { - e.printStackTrace(); - } - } - } - } - } - - - /** - * Worker thread used for getting the response code of an already open HTTP connection. - */ - final static class GetResponseCodeThread extends WorkerThread { - - // The response code to read out - int responseCode; - - final HttpURLConnection conn; - - GetResponseCodeThread(HttpURLConnection conn) { - super("FileTransfer: Get response code"); - this.conn = conn; - } - - @Override - public void run() { - try { - // Get the response code - responseCode = conn.getResponseCode(); - } catch (final Exception e) { - responseCode = -1; - } - // Notify that this thread is finish - notifyFinish(); - } - } - - - /** - * Worker thread used for getting the content length of an already open HTTP connection. - */ - final static class GetContentLengthThread extends WorkerThread { - - // The content length to read out - int contentLength; - - final HttpURLConnection conn; - - GetContentLengthThread(HttpURLConnection conn) { - super("FileTransfer: Get content length"); - this.conn = conn; - } - - @Override - public void run() { - try { - // Get the content length - contentLength = conn.getContentLength(); - } catch (final Exception e) { - contentLength = -1; - } - // Notify that this thread is finish - notifyFinish(); - } - } - - - /** - * Worker thread used for reading bytes from an already open input stream into a byte buffer. - */ - final static class ReadInputStreamToBufferThread extends WorkerThread { - - int bytesRead; - - final InputStream in; - - final byte[] buf; - - ReadInputStreamToBufferThread(InputStream in, byte[] buf) { - super("FileTransfer: Read input stream to buffer"); - this.in = in; - this.buf = buf; - } - - @Override - public void run() { - try { - // Read bytes into the buffer - bytesRead = in.read(buf); - } catch (final Exception e) { - bytesRead = -1; - } - // Notify that this thread is finish - notifyFinish(); - } - } - - /** - * Copies a file into another file. - * - * @param srcFile is the filename of the source file to copy. - * @param destFile is the filename of the destination file to copy the file into. - * @return true if the file was copied; false otherwise - */ - public static boolean copy(String srcFile, String destFile) { - FileInputStream in = null; - FileOutputStream out = null; - - try { - if (srcFile.equals(destFile)) { - throw new IOException("You cannot copy a file onto itself"); - } - final byte[] buf = new byte[4096]; - - in = new FileInputStream(srcFile); - out = new FileOutputStream(destFile); - - while (in.available() > 0) { - out.write(buf, 0, in.read(buf, 0, buf.length)); - } - } catch (final IOException e) { - return false; - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - if (out != null) { - try { - out.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - return true; - } - - /** - * Opens and connects to a {@link java.net.HttpURLConnection} for input only, and where the connection timeout and - * read timeout are controlled by properties. - * - * @param url is the URL to open a connection to. - * @return a HttpURLConnection intended for reading input only. - * @throws IOException if an I/O exception occurs. - */ - public static HttpURLConnection connectToHttpInputConnection(URL url) throws IOException { - return connectToHttpInputConnection(url, null); - } - - /** - * Opens and connects to a {@link java.net.HttpURLConnection} for input only, and where the connection timeout and - * read timeout are controlled by properties. - * - * @param url is the URL to open a connection to. - * @param sessionId is a optional session id. - * @return a HttpURLConnection intended for reading input only. - * @throws IOException if an I/O exception occurs. - */ - public static HttpURLConnection connectToHttpInputConnection(URL url, String sessionId) throws IOException { - HttpURLConnection conn = (HttpURLConnection) openURLConnection(url, false); // not for output - - conn.setRequestMethod("GET"); - if (sessionId != null) { - conn.setRequestProperty("Cookie", sessionId); - } - conn.connect(); - return conn; - } - - /** - * Opens a {link {@link java.net.URLConnection} for output (and input) where the connection timeout and read timeout - * are controlled by properties. - * - * @param url is the URL to open. - * @return a URLConnection for output. - * @throws IOException if an I/O exception occurs. - */ - public static URLConnection openOutputURLConnection(URL url) throws IOException { - return openURLConnection(url, true); // for output - } - - /** - * Convenient method used for getting an input stream from an URLConnection. - * This method checks if a GZIPInputStream or InflaterInputStream should be used to wrap the input stream from the - * URLConnection depending on the content encoding. - * - * @param conn is the URLConnection - * @return an input stream from the URLConnection, which can be a GZIPInputStream or InflaterInputStream. - * @throws IOException if an I/O exception occurs. - */ - public static InputStream getInputStream(URLConnection conn) throws IOException { - // Get input stream - InputStream in = conn.getInputStream(); - - // Get the encoding returned by the server - String encoding = conn.getContentEncoding(); - - // Check if we need to use a gzip or inflater input stream depending on the content encoding - if ("gzip".equalsIgnoreCase(encoding)) { - in = new GZIPInputStream(in); - } else if ("deflate".equalsIgnoreCase(encoding)) { - in = new InflaterInputStream(in); - } - return in; - } - - /** - * Convenient method used for getting an output stream from an URLConnection. - * This method checks if a GZIPOutputStream or DeflaterOutputStream should be used to wrap the output stream from - * the URLConnection depending on the content encoding. - * - * @param conn is the URLConnection - * @return an output stream from the URLConnection, which can be a GZIPOutputStream or DeflaterOutputStream. - * @throws IOException if an I/O exception occurs. - */ - public static OutputStream getOutputStream(URLConnection conn) throws IOException { - // Get output stream - OutputStream out = conn.getOutputStream(); - - // // Get the encoding returned by the server - // String encoding = conn.getContentEncoding(); - // - // // Check if we need to use a gzip or inflater input stream depending on the content encoding - // if ("gzip".equalsIgnoreCase(encoding)) { - // out = new GZIPOutputStream(out); - // } else if ("deflate".equalsIgnoreCase(encoding)) { - // out = new DeflaterOutputStream(out); - // } - return out; - } - - /** - * Opens a {link {@link java.net.URLConnection} for input and optional output where the connection timeout and read - * timeout are controlled by properties. - * - * @param url is the URL to open. - * @param isOutput is a flag specifying if the opened connection is for output. - * @return a URLConnection. - * @throws IOException if an I/O exception occurs. - */ - public static URLConnection openURLConnection(URL url, boolean isOutput) throws IOException { - URLConnection conn = url.openConnection(); - - conn.setDoInput(true); - conn.setDoOutput(isOutput); - - conn.setConnectTimeout(connectionTimeout); - conn.setReadTimeout(readTimeout); - - if (!isOutput) { - // Allow both GZip and Deflate (ZLib) encodings - conn.setRequestProperty("Accept-Encoding", "gzip, deflate"); - conn.setRequestProperty("User-Agent", "RoboRumble@Home - gzip, deflate"); - } - return conn; - } - - /** - * Reads the roborumble.properties file and stores property values into global variables. - */ - private static void readProperties() { - Properties props = getProperties("./roborumble/roborumble.properties"); - - // Get connection timeout - String value = props.getProperty("connection.open.timeout"); - - if (value != null) { - try { - connectionTimeout = Integer.parseInt(value); - } catch (NumberFormatException ignore) {} - } - - // Get connection read timeout - value = props.getProperty("connection.read.timeout"); - if (value != null) { - try { - readTimeout = Integer.parseInt(value); - } catch (NumberFormatException ignore) {} - } - - // Get download session timeout - value = props.getProperty("download.session.timeout"); - if (value != null) { - try { - sessionTimeout = Integer.parseInt(value); - } catch (NumberFormatException ignore) {} - } - } -} diff --git a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/AwtAttack.java b/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/AwtAttack.java deleted file mode 100644 index 5722779..0000000 --- a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/AwtAttack.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package tested.robots; - - -import robocode.AdvancedRobot; -import robocode.ScannedRobotEvent; - -import javax.swing.*; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; - - -/** - * @author Pavel Savara (original) - */ -public class AwtAttack extends AdvancedRobot { - - @Override - public void run() { - // noinspection InfiniteLoopStatement - for (;;) { - turnLeft(100); - ahead(10); - turnLeft(100); - back(10); - } - } - - @Override - public void onScannedRobot(ScannedRobotEvent event) { - awtAttack(); - } - - private void awtAttack() { - try { - Runnable doHack = new Runnable() { - public void run() { - writeAttack(); - - JFrame frame; - - frame = new JFrame(); - frame.setName("Hack"); - frame.setVisible(true); - - } - }; - - javax.swing.SwingUtilities.invokeLater(doHack); - } catch (RuntimeException e) { - // swalow security exception - e.printStackTrace(out); - } - } - - private void writeAttack() { - FileOutputStream fs; - - try { - fs = new FileOutputStream("C:\\Robocode.attack"); - fs.write(0xBA); - fs.write(0xDF); - fs.write(0x00); - fs.write(0xD0); - fs.close(); - out.println("Hacked!!!"); - } catch (FileNotFoundException e) { - e.printStackTrace(out); - } catch (IOException e) { - e.printStackTrace(out); - } catch (RuntimeException e) { - // swalow security exception - e.printStackTrace(out); - } - } - -} diff --git a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorAwtAttack.java b/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorAwtAttack.java deleted file mode 100644 index 47ae244..0000000 --- a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorAwtAttack.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package tested.robots; - - -import javax.swing.*; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; - - -/** - * @author Flemming N. Larsen (original) - */ -public class ConstructorAwtAttack extends robocode.AdvancedRobot { - - public ConstructorAwtAttack() { - awtAttack(); - } - - private void awtAttack() { - try { - Runnable doHack = new Runnable() { - public void run() { - writeAttack(); - - JFrame frame; - - frame = new JFrame(); - frame.setName("Hack"); - frame.setVisible(true); - - } - }; - - javax.swing.SwingUtilities.invokeLater(doHack); - } catch (RuntimeException e) { - // swallow security exception - e.printStackTrace(out); - } - } - - private void writeAttack() { - FileOutputStream fs; - - try { - fs = new FileOutputStream("C:\\Robocode.attack"); - fs.write(0xBA); - fs.write(0xDF); - fs.write(0x00); - fs.write(0xD0); - fs.close(); - out.println("Hacked!!!"); - } catch (FileNotFoundException e) { - e.printStackTrace(out); - } catch (IOException e) { - e.printStackTrace(out); - } catch (RuntimeException e) { - // swallow security exception - e.printStackTrace(out); - } - } -} diff --git a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorThreadAttack.java b/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorThreadAttack.java deleted file mode 100644 index 0c5a0f8..0000000 --- a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorThreadAttack.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package tested.robots; - - -/** - * @author Flemming N. Larsen (original) - */ -public class ConstructorThreadAttack extends robocode.AdvancedRobot { - - public ConstructorThreadAttack() { - runAttack(); - runAttack2(); - } - - private void runAttack() { - try { - Attacker a = new Attacker(); - Thread t = new Thread(a); - - t.start(); - } catch (RuntimeException e) { - // swallow security exception - e.printStackTrace(out); - } - } - - private void runAttack2() { - try { - Attacker a = new Attacker(); - ThreadGroup tg = new ThreadGroup("MyAttack"); - - tg.setMaxPriority(10); - Thread t = new Thread(tg, a); - - t.start(); - } catch (RuntimeException e) { - // swallow security exception - e.printStackTrace(out); - } - } - - private class Attacker implements Runnable { - - public synchronized void run() { - if (Thread.currentThread().getPriority() > 4) { - out.println("Priority attack"); - } - runAttack2(); - - try { - this.wait(); - } catch (InterruptedException e) {} - } - } -} diff --git a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileAttack.java b/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileAttack.java deleted file mode 100644 index 9f76ccf..0000000 --- a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileAttack.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package tested.robots; - - -import robocode.AdvancedRobot; -import robocode.ScannedRobotEvent; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; - - -/** - * @author Pavel Savara (original) - */ -public class FileAttack extends AdvancedRobot { - - @Override - public void run() { - // noinspection InfiniteLoopStatement - for (;;) { - turnLeft(100); - ahead(10); - turnLeft(100); - back(10); - } - } - - @Override - public void onScannedRobot(ScannedRobotEvent event) { - readAttack(); - writeAttack(); - } - - private void readAttack() { - try { - FileInputStream fs = new FileInputStream("C:\\MSDOS.SYS"); - - System.out.print(fs.read()); - System.out.print(fs.read()); - System.out.print(fs.read()); - System.out.print(fs.read()); - fs.close(); - } catch (FileNotFoundException e) { - e.printStackTrace(out); - } catch (IOException e) { - e.printStackTrace(out); - } catch (RuntimeException e) { - // swalow security exception - e.printStackTrace(out); - } - } - - private void writeAttack() { - FileOutputStream fs; - - try { - fs = new FileOutputStream("C:\\Robocode.attack"); - fs.write(0xBA); - fs.write(0xDF); - fs.write(0x00); - fs.write(0xD0); - fs.close(); - } catch (FileNotFoundException e) { - e.printStackTrace(out); - } catch (IOException e) { - e.printStackTrace(out); - } catch (RuntimeException e) { - // swalow security exception - e.printStackTrace(out); - } - } - -} diff --git a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/IncludeNamespaceAttack.java b/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/IncludeNamespaceAttack.java deleted file mode 100644 index c5ecdb9..0000000 --- a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/IncludeNamespaceAttack.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package tested.robots; - - -import net.sf.robocode.security.HiddenAccess; -import robocode.AdvancedRobot; -import robocode.ScannedRobotEvent; - - -/** - * @author Pavel Savara (original) - */ -public class IncludeNamespaceAttack extends AdvancedRobot { - - @Override - public void run() { - // noinspection InfiniteLoopStatement - for (;;) { - turnLeft(100); - ahead(10); - turnLeft(100); - back(10); - } - } - - @Override - public void onScannedRobot(ScannedRobotEvent event) { - namespaceAttack(); - } - - private void namespaceAttack() { - try { - HiddenAccess.createRules(10, 10, 10, 10, 1, false, 100); - } catch (RuntimeException e) { - // Swallow security exception - e.printStackTrace(out); - } - } -} diff --git a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadAttack.java b/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadAttack.java deleted file mode 100644 index bb21f8c..0000000 --- a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadAttack.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package tested.robots; - - -import robocode.AdvancedRobot; -import robocode.ScannedRobotEvent; - -import java.util.concurrent.atomic.AtomicInteger; - - -/** - * @author Pavel Savara (original) - */ -public class ThreadAttack extends AdvancedRobot { - - @Override - public void run() { - // noinspection InfiniteLoopStatement - for (;;) { - turnLeft(100); - ahead(10); - turnLeft(100); - back(10); - } - } - - @Override - public void onScannedRobot(ScannedRobotEvent event) { - runAttack(); - runAttack2(); - } - - private void runAttack() { - try { - Attacker a = new Attacker(); - Thread t = new Thread(a); - - t.start(); - } catch (RuntimeException e) { - // swallow security exception - e.printStackTrace(out); - } - } - - private void runAttack2() { - try { - Attacker a = new Attacker(); - ThreadGroup tg = new ThreadGroup("MyAttack"); - - tg.setMaxPriority(10); - Thread t = new Thread(tg, a); - - t.start(); - } catch (RuntimeException e) { - // swallow security exception - e.printStackTrace(out); - } - } - - private AtomicInteger counter = new AtomicInteger(); - - private class Attacker implements Runnable { - - public synchronized void run() { - final int id = counter.incrementAndGet(); - - out.println("Running id:" + id); - - if (Thread.currentThread().getPriority() > 4) { - out.println("Priority attack"); - } - runAttack2(); - - try { - this.wait(); - } catch (InterruptedException e) { - out.println("Interrupted id:" + id); - } - } - } -} diff --git a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadGroupAttack.java b/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadGroupAttack.java deleted file mode 100644 index 963b549..0000000 --- a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadGroupAttack.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package tested.robots; - - -import robocode.*; - - -/** - * This nasty robot tries to interrupt the thread of each opponent robot that it scans. - * It enumerates the threads recursively of thread group that is a parent of its own - * thread group to find out, which threads that are active. These threads are all robot - * threads. - * - * This robot is inspired by the hacker.Destroyer 1.3, which proved a security breach in - * Robocode 1.7.2.1 Beta. The security breach was reported with: - * Bug [3021140] Possible for robot to kill other robot threads. - * - * The security manager of Robocode must make sure that unsafe (robot) threads cannot - * access thread groups other than its own thread group within checkAccess(Thread). - * - * @author Flemming N. Larsen (original) - */ -public class ThreadGroupAttack extends Robot { - private Thread[] threads = new Thread[100]; - - public void run() { - runAttack(); - - while (true) { - turnGunLeft(30); - } - } - - private void runAttack() { - try { - new Thread(new Runnable() { - public void run() { - ThreadGroup parentGroup = Thread.currentThread().getThreadGroup().getParent(); - - while (true) { - parentGroup.enumerate(threads, true); - try { - Thread.sleep(0); - } catch (InterruptedException ignore) {} - } - } - }).start(); - } catch (RuntimeException t) { - t.printStackTrace(out); - } - } - - public void onScannedRobot(ScannedRobotEvent e) { - attackRobotThread(e.getName()); - } - - private void attackRobotThread(String robotName) { - for (Thread t : threads) { - if (t != null && robotName.equals(t.getName())) { - t.interrupt(); - out.println("Interrupted: " + robotName); - } - } - } -} diff --git a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/UndeadThread.java b/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/UndeadThread.java deleted file mode 100644 index 75fcbfa..0000000 --- a/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/UndeadThread.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package tested.robots; - - -import robocode.AdvancedRobot; - - -/** - * @author Pavel Savara (original) - */ -public class UndeadThread extends AdvancedRobot { - - @Override - public void run() { - out.println("I will live forever!"); - // noinspection InfiniteLoopStatement - while (true) { - try { - body(); - } catch (RuntimeException t) { - // spamming the console - out.println("Swalowed it, HA HA HA HA HAAAAA !!!!!"); - out.println(t); - } - } - } - - private void body() { - // noinspection InfiniteLoopStatement - for (;;) { - turnLeft(100); - ahead(10); - turnLeft(100); - back(10); - } - } - -} diff --git a/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/Assert.java b/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/Assert.java deleted file mode 100644 index 27c29dd..0000000 --- a/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/Assert.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.test.helpers; - - -import robocode.util.Utils; - - -/** - * @author Pavel Savara (original) - */ -public class Assert extends org.junit.Assert { - public static void assertNear(double v1, double v2) { - org.junit.Assert.assertEquals(v1, v2, Utils.NEAR_DELTA); - } - - public static void allAssertNear(double v1, double v2) { - try { - assertNear(v1, v2); - } catch (RuntimeException ex) { - ex.printStackTrace(System.err); - } - } - - public static void allAssertThat(T t, org.hamcrest.Matcher tMatcher) { - try { - org.junit.Assert.assertThat(t, tMatcher); - } catch (RuntimeException ex) { - ex.printStackTrace(System.err); - } - } - -} diff --git a/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditWindow.java b/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditWindow.java deleted file mode 100644 index a0f8e9b..0000000 --- a/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditWindow.java +++ /dev/null @@ -1,485 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.ui.editor; - - -import net.sf.robocode.io.FileUtil; -import net.sf.robocode.io.Logger; -import net.sf.robocode.repository.IRepositoryManager; -import net.sf.robocode.ui.editor.theme.EditorThemeProperties; -import net.sf.robocode.ui.editor.theme.EditorThemePropertiesManager; -import net.sf.robocode.ui.editor.theme.EditorThemePropertyChangeAdapter; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import javax.swing.event.InternalFrameAdapter; -import javax.swing.event.InternalFrameEvent; -import javax.swing.filechooser.FileFilter; - -import java.awt.Font; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.util.StringTokenizer; - - -/** - * @author Mathew A. Nelson (original) - * @author Flemming N. Larsen (contributor) - * @author Matthew Reeder (contributor) - */ -@SuppressWarnings("serial") -public class EditWindow extends JInternalFrame { - - private String fileName; - private String robotName; - public boolean modified; - private final RobocodeEditor editor; - private final IRepositoryManager repositoryManager; - private final File robotsDirectory; - private EditorPanel editorPanel; - private EditorPane editorPane; - - public EditWindow(IRepositoryManager repositoryManager, RobocodeEditor editor, File robotsDirectory) { - super("Edit Window", true, true, true, true); - this.editor = editor; - this.robotsDirectory = robotsDirectory; - this.repositoryManager = repositoryManager; - initialize(); - } - - public EditorPane getEditorPane() { - if (editorPane == null) { - editorPane = editorPanel.getEditorPane(); - InputMap im = editorPane.getInputMap(); - - // FIXME: Replace hack with better solution than using 'ctrl H' - im.put(KeyStroke.getKeyStroke("ctrl H"), editor.getReplaceAction()); - } - return editorPane; - } - - public String getFileName() { - return fileName; - } - - public String getRobotName() { - return robotName; - } - - private void initialize() { - try { - addInternalFrameListener(new InternalFrameAdapter() { - @Override - public void internalFrameClosing(InternalFrameEvent e) { - if (!modified || fileSave(true)) { - editor.setLineStatus(-1); - dispose(); - } - editor.removeFromWindowMenu(EditWindow.this); - } - - @Override - public void internalFrameDeactivated(InternalFrameEvent e) { - editor.setLineStatus(-1); - } - - @Override - public void internalFrameIconified(InternalFrameEvent e) { - editor.setLineStatus(-1); - } - }); - setFrameIcon(new ImageIcon(EditWindow.class.getResource("/net/sf/robocode/ui/icons/robocode-icon.png"))); - setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - - setSize(750, 500); - - editor.addToWindowMenu(this); - - editorPanel = new EditorPanel(); - setContentPane(editorPanel); - - EditorThemeProperties currentThemeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); - Font font = currentThemeProps.getFont(); - editorPanel.setFont(font); - - // Make sure the source editor window gets focus with a blinking cursor - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - editorPanel.getEditorPane().requestFocus(); - } - }); - - EditorThemePropertiesManager.addListener(new EditorThemePropertyChangeAdapter() { - @Override - public void onFontChanged(Font newFont) { - editorPanel.setFont(newFont); - } - }); - - final JavaDocument document = (JavaDocument) editorPanel.getEditorPane().getDocument(); - - document.addDocumentListener(new DocumentListener() { - public void removeUpdate(DocumentEvent e) { - updateModificationState(); - } - - public void insertUpdate(DocumentEvent e) { - updateModificationState(); - } - - public void changedUpdate(DocumentEvent e) { - updateModificationState(); - } - - // Bug-361 Problem in the text editor related with the .java file modification - private void updateModificationState() { - setModified(editorPanel.getEditorPane().isModified()); - } - }); - } catch (RuntimeException e) { - Logger.logError(e); - } - } - - public void setFileName(String newFileName) { - fileName = newFileName; - updateTitle(); - } - - public void setRobotName(String newRobotName) { - robotName = newRobotName; - updateTitle(); - } - - private void updateTitle() { - StringBuffer titleBuf = new StringBuffer("Editing"); - if (fileName != null) { - titleBuf.append(" - ").append(fileName); - } else if (robotName != null) { - titleBuf.append(" - ").append(robotName); - } - if (modified) { - titleBuf.append(" *"); - } - setTitle(titleBuf.toString()); - } - - private void setModified(boolean modified) { - boolean updated = (modified != this.modified); - if (updated) { - this.modified = modified; - updateTitle(); - editor.setSaveFileMenuItemsEnabled(modified); - } - } - - public void compile() { - if (!fileSave(true, true)) { - error("You must save before compiling."); - return; - } - if (editor.getCompiler() != null) { - // The compiler + refresh of the repository is done in a thread in order to avoid the compiler - // window hanging while compiling. The SwingUtilities.invokeLater() does not do a good job here - // (window is still hanging). Hence, a real thread running beside the EDT is used, which does a - // great job, where each each new print from the compiler is written out as soon as it is ready - // in the output stream. - new Thread(new Runnable() { - public void run() { - if (fileName == null) { - error("You must save before compiling."); - return; - } - editor.getCompiler().compile(getRobotDir(), fileName); - repositoryManager.refresh(fileName); - } - }).start(); - } else { - JOptionPane.showMessageDialog(editor, "No compiler installed.", "Error", JOptionPane.ERROR_MESSAGE); - } - } - - private void error(String msg) { - Object[] options = { - "OK" - }; - - JOptionPane.showOptionDialog(this, msg, "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, - options, options[0]); - } - - public boolean fileSave(boolean confirm) { - return fileSave(confirm, false); - } - - private boolean fileSave(boolean confirm, boolean mustSave) { - if (confirm) { - if (!modified) { - return true; - } - String s = fileName; - - if (s == null) { - s = robotName; - } - if (s == null) { - s = "This file"; - } - int ok = JOptionPane.showConfirmDialog(this, s + " has been modified. Do you wish to save it?", - "Modified file", JOptionPane.YES_NO_CANCEL_OPTION); - - if (ok == JOptionPane.NO_OPTION) { - return !mustSave; - } - if (ok == JOptionPane.CANCEL_OPTION) { - return false; - } - } - String fileName = getFileName(); - - if (fileName == null) { - return fileSaveAs(); - } - - String reasonableFilename = getReasonableFilename(); - - if (reasonableFilename != null) { - try { - String a = new File(reasonableFilename).getCanonicalPath(); - String b = new File(fileName).getCanonicalPath(); - - if (!a.equals(b)) { - int ok = JOptionPane.showConfirmDialog(this, - fileName + " should be saved in: \n" + reasonableFilename - + "\n Would you like to save it there instead?", - "Name has changed", - JOptionPane.YES_NO_CANCEL_OPTION); - - if (ok == JOptionPane.CANCEL_OPTION) { - return false; - } - if (ok == JOptionPane.YES_OPTION) { - return fileSaveAs(); - } - } - } catch (IOException e) { - Logger.logError("Unable to check reasonable filename: ", e); - } - } - - BufferedWriter bufferedWriter = null; - OutputStreamWriter outputStreamWriter = null; - FileOutputStream fileOutputStream = null; - - try { - fileOutputStream = new FileOutputStream(fileName); - outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF8"); - bufferedWriter = new BufferedWriter(outputStreamWriter); - - getEditorPane().write(bufferedWriter); - setModified(false); - } catch (IOException e) { - error("Cannot write file: " + e); - return false; - } finally { - FileUtil.cleanupStream(bufferedWriter); - } - return true; - } - - private String getRobotDir() { - String saveDir = robotsDirectory.getPath() + File.separatorChar; - - String text = getEditorPane().getText(); - int pIndex = text.indexOf("package "); - - if (pIndex >= 0) { - int pEIndex = text.indexOf(";", pIndex); - - if (pEIndex > 0) { - String packageTree = text.substring(pIndex + 8, pEIndex) + File.separatorChar; - - packageTree = packageTree.replace('.', File.separatorChar); - - saveDir += packageTree; - } - } - return saveDir; - } - - public boolean fileSaveAs() { - String javaFileName = null; - String saveDir = getRobotDir(); - - String text = getEditorPane().getText(); - - int pIndex = text.indexOf("public class "); - - if (pIndex >= 0) { - int pEIndex = text.indexOf(" ", pIndex + 13); - - if (pEIndex > 0) { - int pEIndex2 = text.indexOf("\n", pIndex + 13); - - if (pEIndex2 > 0 && pEIndex2 < pEIndex) { - pEIndex = pEIndex2; - } - javaFileName = text.substring(pIndex + 13, pEIndex).trim() + ".java"; - } else { - pEIndex = text.indexOf("\n", pIndex + 13); - if (pEIndex > 0) { - javaFileName = text.substring(pIndex + 13, pEIndex).trim() + ".java"; - } - } - } - - File f = new File(saveDir); - - if (!f.exists()) { - int ok = JOptionPane.showConfirmDialog(this, - "Your robot should be saved in the directory: " + saveDir - + "\nThis directory does not exist, would you like to create it?", - "Create Directory", - JOptionPane.YES_NO_CANCEL_OPTION); - - if (ok == JOptionPane.YES_OPTION) { - if (!f.exists() && !f.mkdirs()) { - Logger.logError("Cannot create: " + f); - } - f = new File(saveDir); - } - if (ok == JOptionPane.CANCEL_OPTION) { - return false; - } - } - - JFileChooser chooser; - - chooser = new JFileChooser(f); - chooser.setCurrentDirectory(f); - - FileFilter filter = new FileFilter() { - @Override - public boolean accept(File pathname) { - if (pathname.isDirectory()) { - return true; - } - String fn = pathname.getName(); - int idx = fn.lastIndexOf('.'); - String extension = ""; - - if (idx >= 0) { - extension = fn.substring(idx); - } - return extension.equalsIgnoreCase(".java"); - } - - @Override - public String getDescription() { - return "Robots"; - } - }; - - chooser.setFileFilter(filter); - - boolean done = false; - - while (!done) { - done = true; - if (javaFileName != null) { - chooser.setSelectedFile(new File(f, javaFileName)); - } - int rv = chooser.showSaveDialog(this); - String robotFileName; - - if (rv == JFileChooser.APPROVE_OPTION) { - robotFileName = chooser.getSelectedFile().getPath(); - File outFile = new File(robotFileName); - - if (outFile.exists()) { - int ok = JOptionPane.showConfirmDialog(this, - robotFileName + " already exists. Are you sure you want to replace it?", "Warning", - JOptionPane.YES_NO_CANCEL_OPTION); - - if (ok == JOptionPane.NO_OPTION) { - done = false; - continue; - } - if (ok == JOptionPane.CANCEL_OPTION) { - return false; - } - } - setFileName(robotFileName); - fileSave(false); - } else { - return false; - } - } - - return true; - } - - public String getPackage() { - String text = getEditorPane().getText(); - int pIndex = text.indexOf("package "); - - if (pIndex >= 0) { - int pEIndex = text.indexOf(";", pIndex); - - if (pEIndex > 0) { - return text.substring(pIndex + 8, pEIndex); - } - } - return ""; - } - - private String getReasonableFilename() { - StringBuffer fileName = new StringBuffer(robotsDirectory.getPath()).append(File.separatorChar); - String javaFileName; - String packageTree = null; - - String text = getEditorPane().getText(); - StringTokenizer tokenizer = new StringTokenizer(text, " \t\r\n;"); - String token; - boolean inComment = false; - - while (tokenizer.hasMoreTokens()) { - token = tokenizer.nextToken(); - if (!inComment && (token.equals("/*") || token.equals("/**"))) { - inComment = true; - } - if (inComment && (token.equals("*/") || token.equals("**/"))) { - inComment = false; - } - if (inComment) { - continue; - } - - if (packageTree == null && token.equals("package")) { - packageTree = tokenizer.nextToken(); - if (packageTree == null || packageTree.length() == 0) { - return null; - } - packageTree = packageTree.replace('.', File.separatorChar); - packageTree += File.separator; - fileName.append(packageTree); - } - if (token.equals("class")) { - javaFileName = tokenizer.nextToken() + ".java"; - fileName.append(javaFileName); - return fileName.toString(); - } - } - return null; - } -} diff --git a/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/WindowMenuItem.java b/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/WindowMenuItem.java deleted file mode 100644 index bda1627..0000000 --- a/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/WindowMenuItem.java +++ /dev/null @@ -1,291 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.ui.editor; - - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.io.File; - - -/** - * Customized JMenuItem where each item is bound to a specific JInternalFrame, - * so we can have a dynamic menu of open windows. - * - * @author Matthew Reeder (original) - */ -@SuppressWarnings("serial") -public class WindowMenuItem extends JCheckBoxMenuItem implements ActionListener { - - // Maximum number of windows that will be shown on the menu (to get the rest, you'll - // have to open the dialog). The number 9 is also the number of most recently used - // files that normally show up in other applications. The reason is so that you can - // give them dynamic hotkeys from 1 to 9. Otherwise, there's no reason (besides - // avoiding taking up way too much space) to limit the size of the menu. - public static final int WINDOW_MENU_MAX_SIZE = 9; - // Number of static menu items before the dynamic menu (including seperators) - public static final int PRECEDING_WINDOW_MENU_ITEMS = 3; - // Number of static menu items after the dynamic menu (including seperators - // and the More Windows... menu item) - public static final int SUBSEQUENT_WINDOW_MENU_ITEMS = 1; - // Normal max length of a window name - public static final int MAX_WINDOW_NAME_LENGTH = 30; - // I make one "special" menu item that isn't tied to a window. Since it has - // similar needs for enabling/visibility and labeling, I made it the same class. - public static final int REGULAR_WINDOW = 0, SPECIAL_MORE = 2; - private EditWindow window; - private JMenu parentMenu; - private final int type; - - public WindowMenuItem(EditWindow window, JMenu parentMenu) { - super(); - this.window = window; - this.parentMenu = parentMenu; - type = REGULAR_WINDOW; - parentMenu.add(this, parentMenu.getMenuComponentCount() - SUBSEQUENT_WINDOW_MENU_ITEMS); - addActionListener(this); - } - - /** - * WindowMenuItem Constructor for "More Windows..." menu. - */ - public WindowMenuItem() { - type = SPECIAL_MORE; - } - - /** - * Event handler for the menu item - *

- * Brings the window to the front. This should be called for the "More - * Windows..." Item, because it doesn't make itself its own ActionListener. - *

- * Note that e can be null, and this menu item might not be showing (if this - * is called from the "More Windows" dialog). - */ - public void actionPerformed(ActionEvent e) { - if (window.isIcon()) { - try { - window.setIcon(false); - } catch (RuntimeException ignored) {} - } - if (window.getDesktopPane() != null) { - window.getDesktopPane().setSelectedFrame(window); - } - window.toFront(); - window.grabFocus(); - try { - window.setSelected(true); - } catch (RuntimeException ignored) {} - } - - /** - * Returns the label that should be used. If the menu item is supposed to be - * hidden, this may not be a real valid label. - */ - @Override - public String getText() { - if (type == SPECIAL_MORE) { - Container parent = getParent(); - - if (parent == null) { - return ""; - } - - int numWindows = parent.getComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; - - if (numWindows <= 0) { - return "No Windows Open"; - } - - return "More Windows..."; - } - if (window == null || parentMenu == null) { - return ""; - } - String text = (getIndex() + 1) + " " + getFileName(); - - if (window.modified) { - text += " *"; - } - return text; - } - - protected String getFileName() { - if (window.getFileName() == null) { - return "Untitled " + (getPrecedingNewFiles() + 1); - } - - String name = window.getFileName(); - - if (name.length() < MAX_WINDOW_NAME_LENGTH) { - return name; - } - if (name.indexOf(File.separatorChar) < 0) { - return name; - } // If there are no separators, I can't really intelligently truncate. - int startLength = name.indexOf(File.separatorChar, 1) + 1; - int endLength = name.length() - name.lastIndexOf(File.separatorChar); - - if (endLength + startLength + 3 > name.length()) { - return name; - } // return name anyways, since we're not getting it any shorter. - - boolean change; - - do { - change = false; - int newEndLength = name.length() - name.lastIndexOf(File.separatorChar, name.length() - endLength - 1); - - if (newEndLength + startLength + 3 <= MAX_WINDOW_NAME_LENGTH) { - endLength = newEndLength; - change = true; - } - int newStartLength = name.indexOf(File.separatorChar, startLength + 1) + 1; - - if (endLength + startLength + 3 <= MAX_WINDOW_NAME_LENGTH) { - startLength = newStartLength; - change = true; - } - } while (change); - - return name.substring(0, startLength) + "..." + name.substring(name.length() - endLength); - } - - /** - * @return how many nameless windows occur before this one in the parent. - */ - protected int getPrecedingNewFiles() { - int count = 0; - - for (int i = 0; i < WINDOW_MENU_MAX_SIZE - && i < parentMenu.getMenuComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS - && parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS) != this; i++) { - if (parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS) instanceof WindowMenuItem - && ((WindowMenuItem) parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS)).window.getFileName() - == null) { - count++; - } - } - return count; - } - - /** - * Figures out what index (from 0 to WINDOW_MENU_MAX_SIZE-1) this item is in - * the window menu. - *

- * @return -1 if this item isn't showing. - */ - protected int getIndex() { - for (int i = 0; i < WINDOW_MENU_MAX_SIZE - && i < parentMenu.getMenuComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; i++) { - if (this == parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS)) { - return i; - } - } - return -1; - } - - /** - * Returns the index of the character in the label that should be underlined - */ - @Override - public int getDisplayedMnemonicIndex() { - return (type == SPECIAL_MORE) ? 11 : 0; - } - - /** - * Returns the keyboard mnemonic for this item, which is the virtual key - * code for its 1-based index. - */ - @Override - public int getMnemonic() { - return (type == SPECIAL_MORE) ? KeyEvent.VK_S : KeyEvent.VK_1 + getIndex(); - } - - /** - * Returns true if this item should be showing. - *

- * Returns false if there are more than WINDOW_MENU_MAX_SIZE items before it - * in the menu. - */ - @Override - public boolean isVisible() { - if (type == SPECIAL_MORE) { - Container parent = getParent(); - - if (parent == null) { - return true; - } - int numWindows = parent.getComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; - - updateSelection(); - return (numWindows <= 0) || (numWindows > WINDOW_MENU_MAX_SIZE); - } - updateSelection(); - return getIndex() >= 0; - } - - /** - * Returns true if this item should be enabled (selectable). - *

- * Returns false if it is a More Windows... item and there are no windows. - */ - @Override - public boolean isEnabled() { - if (type == SPECIAL_MORE) { - Container parent = getParent(); - - if (parent == null) { - return true; - } - int numWindows = parent.getComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; - - return (numWindows > 0); - } - return true; - } - - /** - * Determines if this menu item should currently show as "selected". - *

- * The item should be seleced if the window it's tied to has focus. - */ - @Override - public boolean isSelected() { - return (type != SPECIAL_MORE) && (window != null && window.getDesktopPane() != null) - && window.getDesktopPane().getSelectedFrame() == window; - } - - /** - * Makes sure the underlying menu item knows if we're selected. - */ - public void updateSelection() { - setSelected(isSelected()); // Sort of a silly thing to do... - setEnabled(isEnabled()); - } - - /** - * @return the EditWindow that this menu item is tied to. - */ - public EditWindow getEditWindow() { - return window; - } - - /** - * Creates a string representation of this object. - *

- * Handy for repurposing the menu items as list items :-) - */ - @Override - public String toString() { - return (type == SPECIAL_MORE) ? "" : getFileName(); - } -} diff --git a/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/WindowManager.java b/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/WindowManager.java deleted file mode 100644 index bbdae95..0000000 --- a/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/WindowManager.java +++ /dev/null @@ -1,632 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.ui; - - -import net.sf.robocode.battle.BattleProperties; -import net.sf.robocode.battle.BattleResultsTableModel; -import net.sf.robocode.battle.IBattleManager; -import net.sf.robocode.core.Container; -import net.sf.robocode.host.ICpuManager; -import net.sf.robocode.io.FileUtil; -import net.sf.robocode.repository.IRepositoryManager; -import net.sf.robocode.settings.ISettingsManager; -import net.sf.robocode.ui.battle.AwtBattleAdaptor; -import net.sf.robocode.ui.dialog.*; -import net.sf.robocode.ui.packager.RobotPackager; -import net.sf.robocode.ui.editor.IRobocodeEditor; -import net.sf.robocode.version.IVersionManager; -import robocode.control.events.BattleCompletedEvent; -import robocode.control.events.IBattleListener; -import robocode.control.snapshot.ITurnSnapshot; - -import javax.swing.*; -import javax.swing.filechooser.FileFilter; -import java.awt.*; -import java.io.File; -import java.io.IOException; -import java.util.Locale; - - -/** - * @author Mathew A. Nelson (original) - * @author Flemming N. Larsen (contributor) - * @author Luis Crespo (contributor) - */ -public class WindowManager implements IWindowManagerExt { - - private final static int TIMER_TICKS_PER_SECOND = 50; - private final AwtBattleAdaptor awtAdaptor; - private RobotPackager robotPackager; - private RobotExtractor robotExtractor; - private final ISettingsManager settingsManager; - private final IBattleManager battleManager; - private final ICpuManager cpuManager; - private final IRepositoryManager repositoryManager; - private final IVersionManager versionManager; - private final IImageManager imageManager; - private IRobotDialogManager robotDialogManager; - private RobocodeFrame robocodeFrame; - - private boolean isGUIEnabled = true; - private boolean isSlave; - private boolean centerRankings = true; - private boolean oldRankingHideState = true; - private boolean showResults = true; - - public WindowManager(ISettingsManager settingsManager, IBattleManager battleManager, ICpuManager cpuManager, IRepositoryManager repositoryManager, IImageManager imageManager, IVersionManager versionManager) { - this.settingsManager = settingsManager; - this.battleManager = battleManager; - this.repositoryManager = repositoryManager; - this.cpuManager = cpuManager; - this.versionManager = versionManager; - this.imageManager = imageManager; - awtAdaptor = new AwtBattleAdaptor(battleManager, TIMER_TICKS_PER_SECOND, true); - - // we will set UI better priority than robots and battle have - EventQueue.invokeLater(new Runnable() { - public void run() { - try { - Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 2); - } catch (SecurityException ex) {// that's a pity - } - } - }); - } - - public void setBusyPointer(boolean enabled) { - robocodeFrame.setBusyPointer(enabled); - } - - public synchronized void addBattleListener(IBattleListener listener) { - awtAdaptor.addListener(listener); - } - - public synchronized void removeBattleListener(IBattleListener listener) { - awtAdaptor.removeListener(listener); - } - - public boolean isGUIEnabled() { - return isGUIEnabled; - } - - public void setEnableGUI(boolean enable) { - isGUIEnabled = enable; - - // Set the system property so the AWT headless mode. - // Read more about headless mode here: - // http://java.sun.com/developer/technicalArticles/J2SE/Desktop/headless/ - System.setProperty("java.awt.headless", "" + !enable); - } - - public void setSlave(boolean value) { - isSlave = value; - } - - public boolean isSlave() { - return isSlave; - } - - public boolean isIconified() { - return robocodeFrame.isIconified(); - } - - public boolean isShowResultsEnabled() { - return settingsManager.getOptionsCommonShowResults() && showResults; - } - - public void setEnableShowResults(boolean enable) { - showResults = enable; - } - - public ITurnSnapshot getLastSnapshot() { - return awtAdaptor.getLastSnapshot(); - } - - public int getFPS() { - return isIconified() ? 0 : awtAdaptor.getFPS(); - } - - public RobocodeFrame getRobocodeFrame() { - if (robocodeFrame == null) { - this.robocodeFrame = Container.getComponent(RobocodeFrame.class); - } - return robocodeFrame; - } - - public void showRobocodeFrame(boolean visible, boolean iconified) { - RobocodeFrame frame = getRobocodeFrame(); - - if (iconified) { - frame.setState(Frame.ICONIFIED); - } - - if (visible) { - // Pack frame to size all components - WindowUtil.packCenterShow(frame); - - WindowUtil.setStatusLabel(frame.getStatusLabel()); - - frame.checkUpdateOnStart(); - - } else { - frame.setVisible(false); - } - } - - public void showAboutBox() { - packCenterShow(Container.getComponent(AboutBox.class), true); - } - - public String showBattleOpenDialog(final String defExt, final String name) { - JFileChooser chooser = new JFileChooser(battleManager.getBattlePath()); - - chooser.setFileFilter( - new FileFilter() { - @Override - public boolean accept(File pathname) { - return pathname.isDirectory() - || pathname.getName().toLowerCase().lastIndexOf(defExt.toLowerCase()) - == pathname.getName().length() - defExt.length(); - } - - @Override - public String getDescription() { - return name; - } - }); - - if (chooser.showOpenDialog(getRobocodeFrame()) == JFileChooser.APPROVE_OPTION) { - return chooser.getSelectedFile().getPath(); - } - return null; - } - - public String saveBattleDialog(String path, final String defExt, final String name) { - File f = new File(path); - - JFileChooser chooser; - - chooser = new JFileChooser(f); - - javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() { - @Override - public boolean accept(File pathname) { - return pathname.isDirectory() - || pathname.getName().toLowerCase().lastIndexOf(defExt.toLowerCase()) - == pathname.getName().length() - defExt.length(); - } - - @Override - public String getDescription() { - return name; - } - }; - - chooser.setFileFilter(filter); - int rv = chooser.showSaveDialog(getRobocodeFrame()); - String result = null; - - if (rv == JFileChooser.APPROVE_OPTION) { - result = chooser.getSelectedFile().getPath(); - int idx = result.lastIndexOf('.'); - String extension = ""; - - if (idx > 0) { - extension = result.substring(idx); - } - if (!(extension.equalsIgnoreCase(defExt))) { - result += defExt; - } - } - return result; - } - - public void showVersionsTxt() { - showInBrowser("file://" + new File(FileUtil.getCwd(), "").getAbsoluteFile() + File.separator + "versions.md"); - } - - public void showHelpApi() { - showInBrowser( - "file://" + new File(FileUtil.getCwd(), "").getAbsoluteFile() + File.separator + "javadoc" + File.separator - + "index.html"); - } - - public void showReadMe() { - showInBrowser("file://" + new File(FileUtil.getCwd(), "ReadMe.html").getAbsoluteFile()); - } - - public void showFaq() { - showInBrowser("http://robowiki.net/w/index.php?title=Robocode/FAQ"); - } - - public void showOnlineHelp() { - showInBrowser("http://robowiki.net/w/index.php?title=Robocode/Getting_Started"); - } - - public void showJavaDocumentation() { - showInBrowser("http://docs.oracle.com/javase/6/docs/api/"); - } - - public void showRobocodeHome() { - showInBrowser("http://robocode.sourceforge.net"); - } - - public void showRoboWiki() { - showInBrowser("http://robowiki.net"); - } - - public void showGoogleGroupRobocode() { - showInBrowser("https://groups.google.com/forum/?fromgroups#!forum/robocode"); - } - - public void showRobocodeRepository() { - showInBrowser("http://robocoderepository.com"); - } - - public void showOptionsPreferences() { - try { - battleManager.pauseBattle(); - - WindowUtil.packCenterShow(getRobocodeFrame(), Container.getComponent(PreferencesDialog.class)); - } finally { - battleManager.resumeIfPausedBattle(); // THIS is just dirty hack-fix of more complex problem with desiredTPS and pausing. resumeBattle() belongs here. - } - } - - public void showResultsDialog(BattleCompletedEvent event) { - final ResultsDialog dialog = Container.getComponent(ResultsDialog.class); - - dialog.setup(event.getSortedResults(), event.getBattleRules().getNumRounds()); - packCenterShow(dialog, true); - } - - public void showRankingDialog(boolean visible) { - boolean currentRankingHideState = settingsManager.getOptionsCommonDontHideRankings(); - - // Check if the Ranking hide states has changed - if (currentRankingHideState != oldRankingHideState) { - // Remove current visible RankingDialog, if it is there - Container.getComponent(RankingDialog.class).dispose(); - - // Replace old RankingDialog, as the owner window must be replaced from the constructor - Container.cache.removeComponent(RankingDialog.class); - Container.cache.addComponent(RankingDialog.class); - - // Reset flag for centering the dialog the first time it is shown - centerRankings = true; - } - - RankingDialog rankingDialog = Container.getComponent(RankingDialog.class); - - if (visible) { - packCenterShow(rankingDialog, centerRankings); - centerRankings = false; // only center the first time Rankings are shown - } else { - rankingDialog.dispose(); - } - - // Save current Ranking hide state - oldRankingHideState = currentRankingHideState; - } - - public void showRobocodeEditor() { - JFrame editor = (JFrame) net.sf.robocode.core.Container.getComponent(IRobocodeEditor.class); - - if (!editor.isVisible()) { - WindowUtil.packCenterShow(editor); - } else { - editor.setVisible(true); - } - } - - public void showRobotPackager() { - if (robotPackager != null) { - robotPackager.dispose(); - robotPackager = null; - } - - robotPackager = net.sf.robocode.core.Container.factory.getComponent(RobotPackager.class); - WindowUtil.packCenterShow(robotPackager); - } - - public void showRobotExtractor(JFrame owner) { - if (robotExtractor != null) { - robotExtractor.dispose(); - robotExtractor = null; - } - - robotExtractor = new net.sf.robocode.ui.dialog.RobotExtractor(owner, this, repositoryManager); - WindowUtil.packCenterShow(robotExtractor); - } - - public void showSplashScreen() { - RcSplashScreen splashScreen = Container.getComponent(RcSplashScreen.class); - - packCenterShow(splashScreen, true); - - WindowUtil.setStatusLabel(splashScreen.getSplashLabel()); - - repositoryManager.reload(versionManager.isLastRunVersionChanged()); - - WindowUtil.setStatusLabel(splashScreen.getSplashLabel()); - cpuManager.getCpuConstant(); - - WindowUtil.setStatus(""); - WindowUtil.setStatusLabel(null); - - splashScreen.dispose(); - } - - public void showNewBattleDialog(BattleProperties battleProperties) { - try { - battleManager.pauseBattle(); - final NewBattleDialog battleDialog = Container.createComponent(NewBattleDialog.class); - - battleDialog.setup(settingsManager, battleProperties); - WindowUtil.packCenterShow(getRobocodeFrame(), battleDialog); - } finally { - battleManager.resumeBattle(); - } - } - - public boolean closeRobocodeEditor() { - IRobocodeEditor editor = net.sf.robocode.core.Container.getComponent(IRobocodeEditor.class); - - return editor == null || !((JFrame) editor).isVisible() || editor.close(); - } - - public void showCreateTeamDialog() { - TeamCreator teamCreator = Container.getComponent(TeamCreator.class); - - WindowUtil.packCenterShow(teamCreator); - } - - public void showImportRobotDialog() { - JFileChooser chooser = new JFileChooser(); - - chooser.setFileFilter(new FileFilter() { - @Override - public boolean accept(File pathname) { - if (pathname.isHidden()) { - return false; - } - if (pathname.isDirectory()) { - return true; - } - String filename = pathname.getName(); - - if (filename.equals("robocode.jar")) { - return false; - } - int idx = filename.lastIndexOf('.'); - - String extension = ""; - - if (idx >= 0) { - extension = filename.substring(idx); - } - return extension.equalsIgnoreCase(".jar") || extension.equalsIgnoreCase(".zip"); - } - - @Override - public String getDescription() { - return "Jar Files"; - } - }); - - chooser.setDialogTitle("Select the robot .jar file to copy to " + repositoryManager.getRobotsDirectory()); - - if (chooser.showDialog(getRobocodeFrame(), "Import") == JFileChooser.APPROVE_OPTION) { - File inputFile = chooser.getSelectedFile(); - String fileName = inputFile.getName(); - String extension = ""; - - int idx = fileName.lastIndexOf('.'); - - if (idx >= 0) { - extension = fileName.substring(idx); - } - if (!extension.equalsIgnoreCase(".jar")) { - fileName += ".jar"; - } - File outputFile = new File(repositoryManager.getRobotsDirectory(), fileName); - - if (inputFile.equals(outputFile)) { - JOptionPane.showMessageDialog(getRobocodeFrame(), - outputFile.getName() + " is already in the robots directory!"); - return; - } - if (outputFile.exists()) { - if (JOptionPane.showConfirmDialog(getRobocodeFrame(), outputFile + " already exists. Overwrite?", - "Warning", JOptionPane.YES_NO_OPTION) - == JOptionPane.NO_OPTION) { - return; - } - } - if (JOptionPane.showConfirmDialog(getRobocodeFrame(), - "Robocode will now copy " + inputFile.getName() + " to " + outputFile.getParent(), "Import robot", - JOptionPane.OK_CANCEL_OPTION) - == JOptionPane.OK_OPTION) { - try { - FileUtil.copy(inputFile, outputFile); - repositoryManager.refresh(); - JOptionPane.showMessageDialog(getRobocodeFrame(), "Robot imported successfully."); - } catch (IOException e) { - JOptionPane.showMessageDialog(getRobocodeFrame(), "Import failed: " + e); - } - } - } - } - - /** - * Shows a web page using the browser manager. - * - * @param url The URL of the web page - */ - private void showInBrowser(String url) { - try { - BrowserManager.openURL(url); - } catch (IOException e) { - JOptionPane.showMessageDialog(getRobocodeFrame(), e.getMessage(), "Unable to open browser!", - JOptionPane.ERROR_MESSAGE); - } - } - - public void showSaveResultsDialog(BattleResultsTableModel tableModel) { - JFileChooser chooser = new JFileChooser(); - - chooser.setFileFilter(new FileFilter() { - - @Override - public boolean accept(File pathname) { - if (pathname.isHidden()) { - return false; - } - if (pathname.isDirectory()) { - return true; - } - String filename = pathname.getName(); - int idx = filename.lastIndexOf('.'); - - String extension = ""; - - if (idx >= 0) { - extension = filename.substring(idx); - } - return extension.equalsIgnoreCase(".csv"); - } - - @Override - public String getDescription() { - return "Comma Separated Value (CSV) File Format"; - } - }); - - chooser.setDialogTitle("Save battle results"); - - if (chooser.showSaveDialog(getRobocodeFrame()) == JFileChooser.APPROVE_OPTION) { - - String filename = chooser.getSelectedFile().getPath(); - - if (!filename.endsWith(".csv")) { - filename += ".csv"; - } - - boolean append = settingsManager.getOptionsCommonAppendWhenSavingResults(); - - tableModel.saveToFile(filename, append); - } - } - - /** - * Packs, centers, and shows the specified window on the screen. - * @param window the window to pack, center, and show - * @param center {@code true} if the window must be centered; {@code false} otherwise - */ - private void packCenterShow(Window window, boolean center) { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - - window.pack(); - if (center) { - window.setLocation((screenSize.width - window.getWidth()) / 2, (screenSize.height - window.getHeight()) / 2); - } - window.setVisible(true); - } - - public void cleanup() { - if (isGUIEnabled()) { - getRobocodeFrame().dispose(); - } - } - - public void setStatus(String s) { - WindowUtil.setStatus(s); - } - - public void messageWarning(String s) { - WindowUtil.messageWarning(s); - } - - public IRobotDialogManager getRobotDialogManager() { - if (robotDialogManager == null) { - robotDialogManager = new RobotDialogManager(); - } - return robotDialogManager; - } - - public void init() { - setLookAndFeel(); - imageManager.initialize(); // Make sure this one is initialized so all images are available - awtAdaptor.subscribe(isGUIEnabled); - } - - /** - * Sets the Look and Feel (LAF). This method first try to set the LAF to the - * system's LAF. If this fails, it try to use the cross platform LAF. - * If this also fails, the LAF will not be changed. - */ - private void setLookAndFeel() { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (RuntimeException t) { - // Work-around for problems with setting Look and Feel described here: - // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6468089 - Locale.setDefault(Locale.US); - - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (RuntimeException t2) { - // For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF - System.err.println("Could not set the Look and Feel (LAF). The default LAF is used instead"); - } - } - // Java 1.6 provide system specific anti-aliasing. Enable it, if it has not been set - if (new Double(System.getProperty("java.specification.version")) >= 1.6) { - String aaFontSettings = System.getProperty("awt.useSystemAAFontSettings"); - - if (aaFontSettings == null) { - System.setProperty("awt.useSystemAAFontSettings", "on"); - } - } - } - - public void runIntroBattle() { - final File intro = new File(FileUtil.getCwd(), "battles/intro.battle"); - if (intro.exists()) { - battleManager.setBattleFilename(intro.getPath()); - battleManager.loadBattleProperties(); - - final boolean origShowResults = showResults; // save flag for showing the results - - showResults = false; - try { - battleManager.startNewBattle(battleManager.loadBattleProperties(), true, false); - battleManager.setDefaultBattleProperties(); - robocodeFrame.afterIntroBattle(); - } finally { - showResults = origShowResults; // always restore the original flag for showing the results - } - } - } - - public void setVisibleForRobotEngine(boolean visible) { - if (visible && !isGUIEnabled()) { - // The GUI must be enabled in order to show the window - setEnableGUI(true); - - // Set the Look and Feel (LAF) - init(); - } - - if (isGUIEnabled()) { - showRobocodeFrame(visible, false); - showResults = visible; - } - } -} diff --git a/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battle/AwtBattleAdaptor.java b/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battle/AwtBattleAdaptor.java deleted file mode 100644 index 11436ae..0000000 --- a/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battle/AwtBattleAdaptor.java +++ /dev/null @@ -1,335 +0,0 @@ -/** - * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://robocode.sourceforge.net/license/epl-v10.html - */ -package net.sf.robocode.ui.battle; - - -import net.sf.robocode.battle.IBattleManager; -import net.sf.robocode.battle.events.BattleEventDispatcher; -import net.sf.robocode.battle.snapshot.RobotSnapshot; -import net.sf.robocode.io.Logger; -import robocode.control.events.*; -import robocode.control.snapshot.IRobotSnapshot; -import robocode.control.snapshot.ITurnSnapshot; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.AtomicInteger; - - -/** - * @author Pavel Savara (original) - */ -public final class AwtBattleAdaptor { - private boolean isEnabled; - private final IBattleManager battleManager; - private final BattleEventDispatcher battleEventDispatcher = new BattleEventDispatcher(); - private final BattleObserver observer; - private final Timer timerTask; - - private final AtomicReference snapshot; - private final AtomicBoolean isRunning; - private final AtomicBoolean isPaused; - private final AtomicInteger majorEvent; - private final AtomicInteger lastMajorEvent; - private ITurnSnapshot lastSnapshot; - private StringBuilder[] outCache; - - public AwtBattleAdaptor(IBattleManager battleManager, int maxFps, boolean skipSameFrames) { - this.battleManager = battleManager; - snapshot = new AtomicReference(null); - - this.skipSameFrames = skipSameFrames; - timerTask = new Timer(1000 / maxFps, new TimerTask()); - isRunning = new AtomicBoolean(false); - isPaused = new AtomicBoolean(false); - majorEvent = new AtomicInteger(0); - lastMajorEvent = new AtomicInteger(0); - - observer = new BattleObserver(); - } - - protected void finalize() throws Throwable { - try { - timerTask.stop(); - battleManager.removeListener(observer); - } finally { - super.finalize(); - } - } - - public void subscribe(boolean isEnabled) { - if (this.isEnabled && !isEnabled) { - battleManager.removeListener(observer); - timerTask.stop(); - isEnabled = false; - } else if (!this.isEnabled && isEnabled) { - battleManager.addListener(observer); - isEnabled = true; - } - } - - public synchronized void addListener(IBattleListener listener) { - battleEventDispatcher.addListener(listener); - } - - public synchronized void removeListener(IBattleListener listener) { - battleEventDispatcher.removeListener(listener); - } - - public ITurnSnapshot getLastSnapshot() { - return lastSnapshot; - } - - // this is always dispatched on AWT thread - private void awtOnTurnEnded(boolean forceRepaint, boolean readoutText) { - try { - ITurnSnapshot current = snapshot.get(); - - if (current == null) { // !isRunning.get() || - // paint logo - lastSnapshot = null; - battleEventDispatcher.onTurnEnded(new TurnEndedEvent(null)); - } else { - if (lastSnapshot != current || !skipSameFrames || forceRepaint) { - lastSnapshot = current; - - IRobotSnapshot[] robots = null; - - if (readoutText) { - synchronized (snapshot) { - robots = lastSnapshot.getRobots(); - - for (int i = 0; i < robots.length; i++) { - RobotSnapshot robot = (RobotSnapshot) robots[i]; - - final StringBuilder cache = outCache[i]; - - if (cache.length() > 0) { - robot.setOutputStreamSnapshot(cache.toString()); - outCache[i].setLength(0); - } - } - } - } - - battleEventDispatcher.onTurnEnded(new TurnEndedEvent(lastSnapshot)); - - if (readoutText) { - for (IRobotSnapshot robot : robots) { - ((RobotSnapshot) robot).setOutputStreamSnapshot(null); - } - } - - calculateFPS(); - } - } - } catch (RuntimeException t) { - Logger.logError(t); - } - } - - public int getFPS() { - return fps; - } - - // FPS (frames per second) calculation - private int fps; - private long measuredFrameCounter; - private long measuredFrameStartTime; - private final boolean skipSameFrames; - - private void calculateFPS() { - // Calculate the current frames per second (FPS) - - if (measuredFrameCounter++ == 0) { - measuredFrameStartTime = System.nanoTime(); - } - - long deltaTime = System.nanoTime() - measuredFrameStartTime; - - if (deltaTime / 1000000000 >= 1) { - fps = (int) (measuredFrameCounter * 1000000000L / deltaTime); - measuredFrameCounter = 0; - } - } - - private class TimerTask implements ActionListener { - public void actionPerformed(ActionEvent e) { - awtOnTurnEnded(false, true); - } - } - - - // BattleObserver methods are always called by battle thread - // but everything inside invokeLater {} block in on AWT thread - private class BattleObserver extends BattleAdaptor { - - @Override - public void onTurnEnded(final TurnEndedEvent event) { - if (lastMajorEvent.get() == majorEvent.get()) { - // snapshot is updated out of order, but always within the same major event - snapshot.set(event.getTurnSnapshot()); - } - - final IRobotSnapshot[] robots = event.getTurnSnapshot().getRobots(); - - for (int i = 0; i < robots.length; i++) { - RobotSnapshot robot = (RobotSnapshot) robots[i]; - final int r = i; - final String text = robot.getOutputStreamSnapshot(); - - if (text != null && text.length() != 0) { - robot.setOutputStreamSnapshot(null); - EventQueue.invokeLater(new Runnable() { - public void run() { - synchronized (snapshot) { - outCache[r].append(text); - } - } - }); - } - } - if (isPaused.get()) { - EventQueue.invokeLater(new Runnable() { - public void run() { - awtOnTurnEnded(false, true); - } - }); - } - } - - @Override - public void onRoundStarted(final RoundStartedEvent event) { - if (lastMajorEvent.get() == majorEvent.get()) { - snapshot.set(event.getStartSnapshot()); - } - majorEvent.incrementAndGet(); - EventQueue.invokeLater(new Runnable() { - public void run() { - awtOnTurnEnded(true, false); - battleEventDispatcher.onRoundStarted(event); - lastMajorEvent.incrementAndGet(); - } - }); - } - - @Override - public void onBattleStarted(final BattleStartedEvent event) { - majorEvent.incrementAndGet(); - EventQueue.invokeLater(new Runnable() { - public void run() { - isRunning.set(true); - isPaused.set(false); - synchronized (snapshot) { - outCache = new StringBuilder[event.getRobotsCount()]; - for (int i = 0; i < event.getRobotsCount(); i++) { - outCache[i] = new StringBuilder(1024); - } - } - snapshot.set(null); - battleEventDispatcher.onBattleStarted(event); - lastMajorEvent.incrementAndGet(); - awtOnTurnEnded(true, false); - timerTask.start(); - } - }); - } - - @Override - public void onBattleFinished(final BattleFinishedEvent event) { - majorEvent.incrementAndGet(); - EventQueue.invokeLater(new Runnable() { - public void run() { - isRunning.set(false); - isPaused.set(false); - timerTask.stop(); - // flush text cache - awtOnTurnEnded(true, true); - - battleEventDispatcher.onBattleFinished(event); - lastMajorEvent.incrementAndGet(); - snapshot.set(null); - - // paint logo - awtOnTurnEnded(true, true); - } - }); - } - - @Override - public void onBattleCompleted(final BattleCompletedEvent event) { - majorEvent.incrementAndGet(); - EventQueue.invokeLater(new Runnable() { - public void run() { - battleEventDispatcher.onBattleCompleted(event); - lastMajorEvent.incrementAndGet(); - awtOnTurnEnded(true, true); - } - }); - } - - @Override - public void onRoundEnded(final RoundEndedEvent event) { - majorEvent.incrementAndGet(); - EventQueue.invokeLater(new Runnable() { - public void run() { - battleEventDispatcher.onRoundEnded(event); - lastMajorEvent.incrementAndGet(); - awtOnTurnEnded(true, true); - } - }); - } - - @Override - public void onBattlePaused(final BattlePausedEvent event) { - EventQueue.invokeLater(new Runnable() { - public void run() { - timerTask.stop(); - battleEventDispatcher.onBattlePaused(event); - awtOnTurnEnded(true, true); - isPaused.set(true); - } - }); - } - - @Override - public void onBattleResumed(final BattleResumedEvent event) { - EventQueue.invokeLater(new Runnable() { - public void run() { - battleEventDispatcher.onBattleResumed(event); - if (isRunning.get()) { - timerTask.start(); - isPaused.set(false); - } - } - }); - } - - @Override - public void onBattleMessage(final BattleMessageEvent event) { - EventQueue.invokeLater(new Runnable() { - public void run() { - battleEventDispatcher.onBattleMessage(event); - } - }); - } - - @Override - public void onBattleError(final BattleErrorEvent event) { - EventQueue.invokeLater(new Runnable() { - public void run() { - battleEventDispatcher.onBattleError(event); - } - }); - } - } -} diff --git a/代码/robocode/robocode.api/target/classes/gl4java/GLFont.class b/代码/robocode/robocode.api/target/classes/gl4java/GLFont.class deleted file mode 100644 index 292705151399aa3ec0012ddd9685b5c266e07e4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 259 zcmY*U%?`m}5S*=6Y5g?bzzqjY#ErN}xHKGy``7xy*HoKSc`ql4g9q?XV!v{6nc11m zW@caS#}mK^o(+T0Iwa#*T!p_37Fk-@FbQ61BqBZd>oAs4L8wkus)`w*((CUC<~-X= z2Nl#Cuuvtm1C`3v~tic_%8yf~3M!g0+xQvZ*wwRl&_*q5+?GKZOG7ta& diff --git a/代码/robocode/robocode.api/target/classes/gl4java/GLFunc.class b/代码/robocode/robocode.api/target/classes/gl4java/GLFunc.class deleted file mode 100644 index e59a50857aea98d053d9e38c32eed708e1992391..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 259 zcmY*U%?`m}5S*=6sh>99zzqjY#ErN}xHKGy``7xyC)Fm^dM_u5g9q?XV!v{6nc11m zW@caS#}mK^o(+T0KE&gbxC(z6EQ%zuVG_L3h(&Vn*WpP~tic_%8yf~3M!g0+G#H!ZY%#Z3@w1Eu+z){!G4B8X diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/api/Module.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/api/Module.class deleted file mode 100644 index 6b01fb7b7f85914f7c1e01322927ab08e0f1b7b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1817 zcmah~%XS+@5WQ_XmS2#L6TcEWvE!F4KgQ1_VB>&onS@A5kc_=x)si}LC&P@+JPc;R zjvYI8?AWp6umKL|Bp<*>ai|&%qp`GLp}Fe5-M6Z4jY@z2^Vd57n>fv&OW?Mn1IvG9 zd2Yq6x;1U7hOvrnEwpt8Jp%Hzx=@y_oVxX*@>*Ae40;77+iz7}Pg_r$_XK+PjAMd* zf$r?msX)&m2@jwfgG0!mPvCmNIQn_`RYiLzs$y$_;euOL_Nnp=uj9?0;N18Wtk52< zmE*3!pn4T(ui&bht_j@C7NU&9z}Qy7_`xn`&|fxnM+Korp|;vj>~-j;tJ&Qrg$zan zZY3U-$gH3okf1++F-&AIE|6=_($`dtZN623aUH8vDaUK=4dFKK2=sZnP8n)XU?ff| zGWyU~zQ23GVW$K}lduOW2y9)_erN}N2KUIw78lyKrsm8Dj3=8VH*{)whm6TzXouKY zfr*4|%BAUffvFZ9DLyg5LG&e7SQHrRJQ9;j^ggwbMdSNP_+{!(!XIfBoW~be1#Tq7 znQ`K6i;PLODU&m0+cC9qwNC0sT5l^|XZek3G<5AG^#0S`N#|LvD#y{a68AI~f0(|` z4qRUG;DdBih)!Rn7qaF5Gky8e(>rNh71% zZI!=Bzj@JtvvaNORt$jwYJPLT&`gl+zjAW!>Ifn0;xV$`cJ_aN?-Z--hF(=48=g&r z&8TZUS1<#bYV^5AGqj74<{3TvX=M=#!fUxdFz{PM57DzX+8n`q^nIv#0Po{Et*8pz zAd%td>`fLC4O(~6`rYs?+50C(hbLtp!(G|WFfAW4+?Ue~b8?1ZLEdM`%2|e-oMTv# z^9*Zpfni-PGHl8$!?s*vcp!5OkK{7LhjN8sPp&fT%Qc3NrNwX{*BOrF2E(!3WOyRC z7(SER3}>#N+@*F^Cb2p$#PY##1=!`Uy-soWXfy#sgy=z~vW;(`NYq diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/core/ContainerBase.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/core/ContainerBase.class deleted file mode 100644 index 47d94b0bf58541608171e0398cbc8857e6a2577e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 707 zcmah{O;6iE6r4>=9E|x2G^HPaK&?b_z@o<{%At`s1$s!trKgQqf+6fi_6CVx#I@xB z5{F(Z^+#15+q5<1z+rdi%|5@G_trmu-G2x00h=yL0^3^IAUO$QGc=(&RzYZD6?BcZ zGSVvkBopPr5m-8tmogYjJqkV#&s1mys*z5t)S(i1*L%K9OQ6z@bYwdM<(}izH(n#6VU)Nkrj8>YK-tYAO z`RtBmlC&BHCU;IFv;AnKrJcr<*lQ0yKF#Sosni|}TAfydyMRyWzp}Fsc;RCP6_4np zk3}r8SDWbzEEkIBmIUgL+q#c-?uV6Kai7$8F+m&jYG8`Wm9_eUc2cC zoGp4O^P$;nYK^E&%rR#S5bzXaXPS5Lz7dq*bFXCN0_KVRJOK;o=Z=&1MP@n6t+DJ1 z<5D38zA#RU)^4!+1FpD+N7TGU{VQ3gps-p{s9_DSc>kI!*G!o=jNWqbH}&@2%>6pU H5;lGVG<%yZ diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/core/IModule.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/core/IModule.class deleted file mode 100644 index 79a981b0c23f2fb27cf2992df6f6b74a2ca19d50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234 zcmaKn!3u&v7=-7y($o$?*B+oQE!5HI7z9QKq5G=8qKFIY+QW6|0eYxtlTIDF&A{-@ z%=2}B0N5h*;1HHA8_^X)t5jtwXOSt*;&fJd->`=E%d`Qtsqr|CfxC(@Y z=TK;`%a(KN&QTKfMrp%@bah)7gz3e0uHsy`v77&!H@$R3APnLyfa1^)qn?n(Ofdcd DVrnnz diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/io/FileUtil.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/io/FileUtil.class deleted file mode 100644 index be119ff9d92f3d31d5eecf39fd1080756a00a508..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6012 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 gaVg^!pYkj^_CuYf!aTOF^ewryj7I?RxnSuIW5 zG-;F6HtAOy8*OX9($XevKJXkM;hglG=7*fqKdGmur_a4Ju*il^#HuK5)Kjy+G&Lplc1GtYFL;RU#yb>C^%Wf3wZmf?>N43e4VwlSL_O|7 zTE~~x`9Cs8KW0p9Lz2Q?DXa%WFtHg)DZj(SPPHR^U+&y%LPt`^eHylxL8v_5Kr7lz zv}22gWS{avDt4MM(4e6)Z@c1&(#(YLN397*Xh`S1g5``^zAeAiqJcWJ(d%&94m7mp zH)MmcZVg08YF0tg(4G0hfM&;}Yh5N%sMlZ++#wMJR*_ycXYPWxH#=rf{D6sl$T9vJ z5*H=d8huXRt)0R{5%uvIK?*%GM!zHsBK@$5Bls#MiXuGgd$Yn1=QJFtamd}Kvv)5U z=*1&C`qq=J(!|6uJj!+Pe93Zx(?!?w#efxT6!b*{$1$LzUqgE}5v9;}auNII`D)?> zPHHeiuipynLf#5(R}oT9m4Ru?AK}TuEr{Nleh=cbj#C=8)hHtqUqd%bX;xO2;~E%5 z-o%hx+pN~)%CL#EGW#}9Ii+CQz&VWS7}2n&+WSBhO1>S=N>3v=-(~+z;YC`GKaO@tXlIBG1=#jIw(PD-YGQyZ(r3-8a<&)WH}MKyrDs%?Kk~%p*ZgQ)*Q$AY$+b#25!qT8^j-E8vl`3gg89T z`ARuO-3$1Wi9chWS*yBI8Tc|RRrdoqTL$r06Yr|lRdBq3W8pSz=I4avu>jg5Qm9wc zK_Z@*rP%hkH;#JeczFqf0nZIQIcJR#ujCiR0;K<}{=75YDo#eKTx1UXDk#nDK zEpp29X~@aQ=e=@x^Vz^}6I&?1m0yn{!Czp<0vhk2X#v~spk)QE<4f3e2OS@AD}np@ zyH%OLk0y6fy%S$nJD?d}6JldIK1l^OcP(LeSv9E^Ta}6#31AQQQm`HmAj1{u$wPcb z%6E`0D;vte-3)BcIs;Kq^_=6~v4KOBlm?Pro0hS^+Cqk~WGgHraS&foF7PH0S20ol*dlYTILXc>pohZb@4CSL1W#$#t%Z(_>=nz|P8_&mbs?F=7_cw!!t3+Nah z`sXs9yd?qcpwxv6e5Rk4FZ1Z5_CeZS!L#ElxI~OC?k-}2f?^TVOK?7hn*bN<77@;) zVbw_YXY)vQfA)`$7~?U#i5v9t2HsZBI>pa9G;yt){Om_F4v_8~+8E;=Mw#KII7fhc zaF`dAhiTymr~FamdBHf3K0Jd*@FG`VWjb8PWB3_mZc;*Wyj|gcD@Kdh;2W4DUf<+i z6H*y7@gKD7Xg#Q((DA~*DP50muW>R!JS8X1GTiicmhjy;)LIk`(%`8IikjCbdI>K_ z6k&`8WyZEigJk4;G?{*l@aFJoK$d3?rU zKBdzs+P_}I+Au5YY=xgGWkY5&TWf6NWhSh&(W6qSGyP^|D&4PAX#p)!8f{Z4@zyx2 z=9eGi?F6Lz5vy%H3K$`)qh$3wSsi2TJ%!zz_J{Cvg%dq7SdtfJac82D_0Fjg`|}D7 z%GBQ5^*NI1Uw^oQ+f2XTE5m}B=Xv7Zu4S(mkJ6YH7)AfW(7AAsDh(1_@=rA`F%xpaph-%WV@Ia>` N!c-ig2I(GA`X3QtPig=F diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/io/RobocodeProperties.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/io/RobocodeProperties.class deleted file mode 100644 index bf77d9ee6f427b538ac095eaac6c9f0d2cd8a49f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1456 zcma)5ZBr6q6g>}b3+wt4iWX^RX@aJdX2X8bArg1+>n zno*}_`T_l@ru!`0f}%6Q%)Z>`o_o(d=kD)6KYjt2!?pw$!$g&vv3e`C3^#|ru}K+VeB zv?-l1EJac+K3UVys^xfRB-$DBW02UGMuS@3L|DSDi!H5E3T|VV!N)%|h#W(xy<2no zc=Rv;hC2$p@cD6<1}XA}CKXH|APBzGsPAOzzx;_abZhl2FEk9zJjs+wmg;1O(iW{!Qr1)p?|0Oi-MB}q zZwSt1QqMwBl~#ZNa-EwwUN`BSI7JSl`+huOkaEdvZacjtVS!=jvJdMGty1KMjCo9o z%aVd;cus1nwHmJ$8HTA)hcPxPE)dHKRzR!cH}$5q3F_i>)2OHap68)Wed=cUJPK|ii#6j1-oF3 z?u_EzsWUui!F*P5(1Iw<1Vj*}!~mu+O%cIn+&Td~-!SsUDlS?!u_I2q03JGsMH`_I z;u9qIXLvjU>9)u=krNJbhEBY2$!m<-&R$hy?7AW|R~LynMcTNJUFN>vfCG4BdDGP1 zZLtpp=YC@T;0#a0r&v5i{2VXdw4`e)zCwDhT4kE@g|KehnQ$mLVw_{+x;c^#l?!6f dq7fItYR2A(?%-T&1uhS?<5XeTB9IHO{sKmY4UYf- diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/manager/IVersionManagerBase.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/manager/IVersionManagerBase.class deleted file mode 100644 index 2b3eeb5ae91939f29e240f6d29a6d61cc522e400..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 281 zcmZus%W48a5Ue)p#zztlf%plEkO8lrj1X8b3K4SfHm>cuVrF1w^y57E0e+O&>cU>U zba&C!Rn@2S;Rv9Q*9av-&u~zFrJP;Z#4cI=Yok+kD*j{VGi!eC_)B|^P$slCdau=1 zn^a8~8%_eDo^r_9g!fK&Tu^4gWhNaE8U<%Ucq`D*$3`@sI^CG?k@>Oq;df_pz0q2X zczN5;#c5`DF5&NN%Y^oWh@V&MDnSn9NuVr=E2zpqi1Pl7+6~vy5C)+swS<=o7bZwy diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/peer/IRobotStatics.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/peer/IRobotStatics.class deleted file mode 100644 index 5fbbc3de004a312e0e2a80b7a5fbfea8e655ac19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234 zcmY*TF%H5o5OYeQ&{hKR1SVLB#1B}II)Nw?TbdpyRY_43`Zxw2z@rc;%EEF!TX(kK zpXUp}25E$VVWG)#bKz}MG_om)--%kD9UZl~6;??TA!L|Uq7%Fp`pWl3Mba|NmC3ZF zR!FNl`h74Ama8*Es?0$sZM`^EW?ObbODesRD03ol^DNGrM=NQkYI3%J;p;wk#NeD= YYan!8h8VepA@Vr(IO)+{#%=~kz6+T-!TrI1a^btH9G{GjTTEc&+uO zqWlFU{syn*rBp~Dp7}$(AjFy7wLOuH5VAabXXe~{&pmf${`mWs-vE4srh$Y&xg!I! zcWCp6kvzcQ!oG7R;O+5?jK7#5Xfvg z9VfUekX%@NCXiB|IV3TbM;aM{i*=_X8>c7x(r;P&t`sQLJ==1hS-zv@@nR}Ca(V)0 z{eO|F2u!qP@X+zeg}nQ;1!foOAy>yUw;fkj7NcoMz19h2Tl$qO##vI=_iWkg4PxXV z@J=2RxGZpv!G|%|;+SEOX5c%WcICgbP?-bA7r1a1N*x&dvE?gz{Tx|L6Bsl4+Ucr2 z0pmDAW$~WCxJ`k3Y|V;tQbrClxNhJYwH~&o>RP>C9yc&c|3lAjSSO4$H=+Vvnb50Z zU``;f%coL&n8yMZ1;$8wM+QgUfxx{H@xIZNj^gPVe0k`yS7sEUlEV_p29^b;hTP9$ z@>qe%bLMnjdM{YRx}GySg%v$#yrd_Mm(;Ob&GY=<63D8~Dvj9e1sxkv&SJvACscdL zDn2y^J{7p8ExWF4Tkd^Z9ipvoZP^VRuVY|CU}=czmsDdBwxtj)%O?fRVN+mc=+N+* zr}j~#k_O^E({hJg8(y&OopufeDE2PWs^6u8){*$wQh@$Bq5#@{|8B6)wvwmys!Pqs zHAEy38*&mKf@y8DUuWE2z6VYqPt=_smKJwIKrr$RZKF0)O5X9Z2I^<{S0#zRuHi=t zNsOL&w2lN#o_(sQMf_Y%XcEY&)UTM? zOBOz8zQO!Ps+ba7NbV(AQo5eJ(((hQ?`4LkM!LbmI`Ebl|Tz*Zh zfY0y%x5MuvtcTwQD&e<u^%4oiY6S8$%hedbSKYhZmbu$~O8=R`!f3^`WukUNv)u!U_h zoJSF#lS7(23G#T%-CAg=Si7NBr}Z?nc4#%oLA5=Kw#$_-xiXFPpLk&4_LhNl{ww_7 Q`3nhyRR}yGB7v{|0R(>cqW}N^ diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/repository/IRepositoryManagerBase.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/repository/IRepositoryManagerBase.class deleted file mode 100644 index 09ec41a124c34c16c14dc69c401392dc664ab51f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 337 zcma)&u}T9$5QhIrG^bHPZGC}D%rF+%I=8~^ z_SKqTV{him6}wERlso10Oc>UaN5WapxmmOGop&~SiHT6xlc(7(%1O*B!7NJlZ|Rh9 z9>lf{hvLocR#EP6>e)|llhwz5`ftZ^BQNUs&Icx3{0(=xu^$l%M0pZ0EUfz&VZ&VE QVA~HdE*rv8sRJB;1L*r>bN~PV diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/HiddenAccess$1.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/HiddenAccess$1.class deleted file mode 100644 index 2cde5ef5ff83f10cd124fa2368b535d85cf39c05..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 964 zcma)4O-~d-5PiKf%dE=)vI2_hHz2zROw=RBM2SX|1rBR4(NphC3ys4JneN5-LyW=S zz{LwD9{d6RCS!avyTl<}ICNK6SJkVkSM~ev&tCu@A@EQUSWJ`+%!eRLduf_wT;0j#clZP^hWwH}&_4ZU~J&Xv<6u&wRUg}sSa$iwel?jYI z(TTQC1)NrUTfki>ejN@*eR!w|OmuXjHv9WMmA#R@SP3*bX(;1undw{~e!6y78-aG` zf~Br8vt-!^R$#8xDOa~P(25SaHq*(@TKiocS1|2i>P&wFtB)C66&ST?C;ghAq%$m0`DIT`R+n8}eYtT)mt2voN0r11HM^Wu`;P3A{+cI5p&9L)qOl@~|YZ za3P+3EMtYJVWy;2>#;PZlgcQc`}^~)KJV+8wle>vkn;EGSW0b{J;~PVB;hFXgv#I! zNElC*J6+-7Vo|%q*JDaSSzY>p`uD=@^R5?eU*OU>M%^DcVH^|GxC5Bvodfjg=~6bA zPte$0Xl+BtjFDPaG!bwi)c~0XyXA^iwuK)`1}Vmm*=Md diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/HiddenAccess.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/HiddenAccess.class deleted file mode 100644 index 18fb3a552d080f60c21e4382940bc2bd7b0370be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11107 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 BC7J*L diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenBulletHelper.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenBulletHelper.class deleted file mode 100644 index 241ce7e201a843eb20bd4cf1fedf32ef96603729..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 205 zcmX^0Z`VEs1_mPrPId++Mh2a{)Dr#TH2tFdr2ORklvMrV)a25l%#uodPmj!$l+-+@ z(wv;s5|7lJg47~*1{OvJfvm)`ME#t^ymWp4q^#8B5=I8L(t?!4l2k?pO${HoK@g4B zE-pR@4Z$TvnR)5fQJP_l3|ztarA5i9ZkahijS^UF(*x;aV`N}tU&L5{sl9r)m$PQ>GR;hi`D)-q8?TgW0%}}Fv`NB|l=$7e}nAk&+gC^>Y z7|Otd2O7%UI2R>F8cOeUdu6C5$`r!N1%obGZQJvGT9sMSGaXsP zoO!obOA+Ma1U9E<}?s$kbH{qw=%Z z#Tjc)=xfKy^M@pi#!|}F<|rrI-{?|#Z@$2S&^y@DX3B!NStX8xMghurgpi0|9 LyKV@p4A6N4GHN#K diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenSpecificationHelper.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenSpecificationHelper.class deleted file mode 100644 index c8ee127e9d66889315ed467cfb90f6f07b8df23a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 648 zcmc(dPfG(q48>n+?P}{k(7V^}#Q{BO?^2;CxZ-^}n=VtfGi5dv{AwP&>xUAjwdl4W z6fa&TLr8w)z2yDl)@ zTuwP8XcCUb`bn!&yF%R!$83afYyxZHl@7vNcd%aCt7S3?))oJpNeAEhjdv1!sqUj8 zvLdBNI4M}JZMiP-vb#}#T9f_dSwwa!mIv08TRmaI)n=p`Xz5@27*TP$AJiX)TCxc3 x%+G@1xm3dG@0V~k-)xIO*orp=G~;1xqZL1d1Urkki}oURuoo)``|)ky;1l&8(;xr< diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenStatusHelper.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/security/IHiddenStatusHelper.class deleted file mode 100644 index 4299256ee0fe40c8872a6f9e12f1a216c4b44e18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 211 zcmZvWK?;IE7=_<&r4=n&c7z0Jpl#a-jUdPqjN@M@;>0)xU9Ck2=upv!5G{I($6I{x zz1REk1hB>=fJcaGwxT%;qcg2^&Z1$}n!?^i5*K;Sb!w$;o0zLBn*c+?yp%U7Dp_B| zF)LYF!b};KmV1;CF1J5PT=wDND>ylm?a>Wkn(Edl-W3%S7Jr$KYRe`OMmAP@!!1wfjwegPr4c*vLguCiyW=X!`-Py!kB12oT31h(lQy$n zWwdP4zDcbxB@FN14DXZmE*3Z;T>SdN&dR?Zp(@`5!`UZX{a^kjTYZA;C-s4jbU8vF Txl@5-$p@15K;RWUq#9sFgWebfFawZ2VFQQc_?6op%SP_ z9?vF28J~#ZSdx37LoptRSlNCFX3d347}~-AveU!$b7|~6KXW$PoxhS6!LaTjhrCNw ziJ{y#BD^{h(`5p;uV-;64^^7++fVJ-$+1Z~hrXG?wKh~`sHP!lFH*Eh?R^liiVAf_RIx^g75B)@uG&5P7nGmCP8X;>z^DF}aEG)Yoej_=&lYJn SQctU^rwmplvj&wJG~WR&cyWWwTPX8g^@uZE3qt5KPNFSUEe<`D>b=^YSwD^_?n9Qk_cE(y&_+#>l{(l8R(aDCO2@VtR&= zfh#z_v?w{%Ei(t`7YQr@ss{=IHbw?U24-NyFfcF!!Cg1)fx2=^&er#k< zYG~h3*8;8+yBa%Mo7>iOwRb2;fK%r=jQ^M>HJ)$w*2f11!m+*~d$6!>I2tvR_EY;| zL6;dGXf=n1!u_UtBzt+73LDIx;r`PS@j)|@+?kpzTszF6;b_ugDwBOsRR?sM>`aD} z!|CUFKw<5eHK2ogT{xMHnr>E**qZI27zYLp<4A9sbAYMXV$c}tGy591o3W&`s*I`B zVze%jw7z6cn8Q@$OvoIX%QVFrYK;sHWpkbfjW?L#&xMcE0~NVbkr4JXGU?7n3ipBIdU9oPKBXxPt>$l)!=OOM#DoxU2#!3 z+^|K(rr~5HTHP8R#Q3<*NPi5+FM-h$GDlZiqzYv9!ew=^w#N0WZfDZ0sRa+ccWXE? zWFpQ@vxZ}lc(whky51U-X=Y5qCuEs3=Cnp@ip=gak2<@-nu6H@372QLcQiD1cpiD_ zrCXUM^bRKyINux1#1O(XlYez@G!ly>YneRd6&snn^+2Q3R;DHITeIVc>0E<0&_K zKJA1)w!{-{;Q_E)RPHiDXEG6q_19F4snHtQ_CkX;)0qK$yU3sq(TAapgxMb%!ePPL zaPw1!uBj9KOl*n7%(mfy9y8G;K82Ip67LO1H-?e^K&yuV@=#2tOPNC1N<<1lZb(!& z+a_qW=sE<20DY7`uG7bu=4P+zjVH`%B*tVIyC-C_L6_4fa31ZU{$6Cqfy&R zaAn?_@pK7YVbG`OO2`8SHk36(&B6nI&@Ae?%Aj7#6I*=7plj%}@TZu$!}dj{dF5lP zH|4Ox=5q#}MIRhT*U=3+T@Tqtn>5}BYc(bk@x+>5sU8fvk-h*A>1aHyy`zh1ehxck zuc-;p&Gbc`Zef}|dI#&c*{}?{mA-^D8;`Yyqi~=Bv#&WeI1JI(+Um=2xKTSDi`>`I zR}8vMq|hNn%bNN|!FRhsUz4qi0X$zuDvxt_tS$qJ>cdj+od?}p%EOp9f|ND zQ+0;xU{a@f-mn?#HQmQ3y;$jcpF#WS8?Y4SA#5<6>QbOlxMiW_gV&miz5_T zbqqEbrf(Yb5It;po*mbY?0Ko+C!Y6+L1)uB0s0nwN2hNe!7uDZ;unwo?@o|{AR9j+ z1_w`Xa%%+9t@0?@%3U=he&_Wl%fnxCDiC=pRdhr3mA2}UW!i_6aAyQT6r(kD)>`-Z zmpB$^Jipf*l+!k((=#at!Q$q2XGB8dj|_T_ehe%_kqgZBEy(@lxi~h9^FD9TPsK;` zuscGDJo=eIFVfGMeBneQjDYPeuh?7{pkLCjbb1M?UO9ReWP^T9FJsA$1PT*;mTyMn z6)e9o=t=r5f~w2QTn?2B7uM~j-y8G?iFM-=<^TdHf{ma4#5BvP4MYuPTf&j3*|(~! zC)`&i!UpJRdR3CuYgySKm0h64ykt0m01B;GTF#OLHuOrtf{Aha(o;Cv92kw7vHm1- zZa#|p-fhT~c5VsgRCZ2p5JBHI=p8Y@gjA4dh$PfiYm(zAU2*I1Go5_wS{!r3e;ag& z-h+*zk%0)*FgY_MDffjE#`l>H0H%txr>eMXJE|QH+>Q#PGaIZiu26w3k!Uo9y(%}0 zoH)gIcC*jmJjPwgyCoVyv@3FFFN-Sz&TbxOa6nuo4_1W>`>{JMXoyGvMuIKtK{zgp zClI8{B12`dc(QD0cyKVDKmqON2~4$iDlLm|DeDU-!=q*`D(f~=Ys%uW=+3gCWFj8x zFB=Fad$)?b1qM&zLfFuyvo$dsos`-nIk~((huZu+8K%hP-4JXjKAh-|RaQt+mb&`>R-rrUAe6iESSt1&Ln?Cu@@~G&;0FFE zGEgdFX9WTj+Wc{YFK66`^ZHcx<5+@*>wbcJ5?AQ_DO`usK|@_g{rqWEWpyYC<%(im z)A$O$8g(ImCLIyoq0JR{y0#|bJLHZh=7$A7Yw)#FUHAv%LlG%D<>BY$;d?scZd~DH z2H6eGBh@HUyW(afm*iB@4pU1lf;$D{sD#p|>1YdUbiO&G8=taCfy+)(UV!x&r%zSz zyZKAvP6(176tAcNT+2~7ndosGi31`dM>3s5MUW${X%cPiHuz4y3o3*Y+c5{8jL71~ zFQz>br+VRZufg~6{fGkKBnu!(c?F_sp-U1gULJ{6gRmMgcrWj>N`_R31v3OvH?z8U z9L-C_{{AXAb zCk9=PXc#XQTFvCvIB=X|`?Na}Zgz!2#UxessYwZQOB6MJwZ#EW_8R|1=hp!`9fLFH z82kqR72z0x(MpjKRm^zHQ8&o)Hx2$f{{u-N65Af%hPZg58^vkM1!MoS!TeiDY}(Y%O?(YVz}%`&|^5$Rf9su!lPx5Yb$d$(FvaPo_;`H@!A zqNfbe49%kZh}6}kIv=hD0j9F_f@ZuN?GHySJ2|sd4<;N{&Hz7hiEsG_Y&T##l>OEu zm#aAMO2)>ITEEK0{iyIUf39nOZuFQmC9~NtFQcrt0Fzy-l`QgJDC_Q%>29N{7$(#M z9&M_jm1w0_hO-srbSsp=ma5=w+H|B~Z3feEIb183Bk|kXEJK?uMc}v|xU71`jytb5 zM>=abIi8^es&h}G2Pv<>C6V%P1XNdcYD&ZhQtg<@&^5`uHGP91D-o?oy)LoOP{|X{K^EyBV@Z+KcYKXFv;Si%_L$xXF9bZ;%F} zwnW5yO4p7@4`S46R~tkYpI~UqrE@tx85il*1_5oUwo+PxFAKL-5PV$dnv^&>?he2r5rvkZK`K8WSVE=bqdZVL zD2@D}$7RuhEPA|)HZVWmMNa@d(M1=4o|HuwQjxRYWQ-TPXxV>?ix&P@!HLCTy!1i zdKcXQy3s{9fnMvP*MV+!(d$8<>Y`gfx4P&y(CsezG|;EJ=nl}GF1icW#T#PyWOFLA@Ikuve){|f-PCP; z{qhKXwY$K-kM3xZ2Zi_Sqx(Xh5!%~rEjqA=4r1V-TJ)$a!dEPMygLna5se3=GXP;T z&eoYU8yX5iM<+l(HPl1vp@%L&JsX-hm->|eQ!KdjUHTr@*3e@5KK%f~u!KO2{SZ&R zpq^IR`v<;@PR|O?s2ZVXmwO8gAYSDw^%eGv&`-KceE{}p>szr`K0~Fx5qe>Seo^dI zGlQi*S^A1R{@wMIe}JCeRQSie^yh=lOcBVVG{2M#d_NZk96)f1BOnao(4L2bm!PG1 z?{^|?hZFCBBc2cExd0+xsD!GuK-xk9F1=2Ffe`ZT4cJgz;4Jzp{SEv0;bw1Qz85>R zDdBzecZ}oJ;Cs}`I^LIvF8(n}7h-C0jHcl9O6a1tz?gZ?K6-1Fx72GZ!|N!+J5zKK zEcMFNS4yFoOxa7l_kxop^l{jl@IwO~q7>j2dOf-bWV zID$4Q@kG!jC7uQ@CoAzh;I&+d=S_=OZ;SUX{d1IfkJ{qZr%W9xFp9nBjL^TjLzaA@ zlz1V_)WMLlY$#i}P_}GWLFu2t`TQ)-{I!tnbCB(Nc-{?&a5uuBH@Rf1cVw%#J(D1P z%82!j5o>HCis_Km4$&I%VI+8_Qy@tW-G;sbPPX+A(-?dzVZ(eY%Qaba2Uon^BFytxEm`tAcXd(O_N-V`0sD_hx zM3-DRN|(o}8iHt72ueC>Mz-qYY3)pLlT5|Qb5W_d$}JQWWgp;aQ230!JPXdmvx|7% z2rrOv5F=bJ>I-7o#8p1azcTddOY3zxsuH4u!1XAi;kO|9V+hz!Ah&;)7C{@!aF$O( zWb316@hhX}5J-MZ7t!-dk5<^&<>+yj?QuT3P-#yCCsS$913oRb$8EEbSvvLmfbvN`(Z>2ISlkQ7^D3Vp1BejBZl{tUPRy#dP}K;Zq(VHtoIDEYpRw>& zB=6T?kk=7&-+*iX6^H#zg*0ffb&$?;kj~>euE(}TG?5#SiaZJ*vTFWh1+CGBwgYpd zke%*^RuHOuSV6)OY;r-G2Hz%n3!Aw+1I&OZ!g z>N?>Z@7B2$?=IzEns8Vqr5{Tn^CY+ZSCTCg$+*3HOv!j0eqJ4bWaA;30mBYV!>q8YI z+}(YtkBfc9d82K{IPqKz$)-TEsgSG$lA-p;=L(*243cejBsvcryvqc+a zG!)K|%*>Vy50qqEY{>?}Nltq~XvX!V<3M>mS7*k@0A>&e5j8>znRTQKoP$!}9Fzj? z=dGA6$D@R_W*m#d_-Y>oT)-vwsof*??#mkbivK1pi-)t(#r4l{#CO+FSdOPOPF-yh;_I_(>4+#e9jq`5|zWB-9|qPik{~ zzqGAth7{GPk`5w~er$w4xk?hoD&GOV0wvLvrM|s<)xi*^UNhsI5&j&?gnPkrDzg4U zz77KI0@onY8X>CtxE**;1Ktjrgitw^KS1+&6IJjTv>Xn&20=tB1*>FiaO7xkrYtpX9@M*ad6E%M^59m1A}kx#u=%#vJ#gu~Yzq6s?R z1Wnw+U$ix`3kDL4m$)@CHm9~OP+Z={ey^yL8TWp~MoZTrLaXCVXBSncL zMG=2lNl}15;VFgftSTaHm#^?`HkvyzCfB%%Of-QumA5BUNtMd}c9q#?+wU@fHw$u3BXGN-Y|-*B+Roz!L-V<3I}F|19QFuvlK8-1(YI$*{=e+RhGf~MX~SE zIHYXkPv+bCYexp2mjV2a)5ivWA%I^5;2**cy8!%R0KWvlF9z_--WTxRBLX)S@Voiz zM+WZ80DjMgv4LL>;GYEWD**gT0KW>ruLkg|0Q{Qw1-$c!z&9x15AcHyaO=jOHW{0^We_`41u zyh*d=+H+49n>{Wzx#apDe?JGCAKabAX8)1d;C1uUHk%G8UeFYUoL9T+pXFn@qK#=OO>f{o1NC{nC;u#{C*Je(h*)9zmEF!Dqu~U&!04 z`bcR0hS2-1RJ~tZW6_pMyRrr1c>s8UO893qlV5a!nC*a=ZQDEmm~x4RiRI_f_{{9* z-UI-WikF2@b-jSyu92?Q2)|f66V;L3WBIk}b;;mNRe#8o8xB8{zPnm!`eg|G3If`1 zXb%65D*5*)Ags28Rj(~`&@Hq3Q_`@IZnK7F#ys4aq(3E*27ft>A9t4F?W6p?6$sV( z2XnMfco8NE{4Wnl52F?3=Hc6^!2a~B&-;`$YN%F|ilBy?a21fxHVxNT+J*0{XaX?2ihI#( zh~IyKdf%YA{5Qn!H*qieJJs-8bTYq9P5cfTZSPVW|C8GJUuYyBQiihXt}bo7W`G-{ zu)U>#LR!8y0kYynl=2%78n<4)QJaWoYt^>`d}~+VCgDwgAy!K>0zAO22%n<50`k?= z>6&k?uIc!HoEJKLSDTELnTFpANyYQ#9w6SdS1WE21&wG^_G{BLdW7F@g+pjF@uV#6 zd{!xbnEVJAC7R}Pyt&$398&zbG)>dy;Y9*|R)Bi+4Q)R59j7fo0q$|_udJyZr9j;t%m4DG+#mY t&_dF+leAhuT}(R64&y6>qK|tRTYFJZdvq;?>RS3ZNDkU5;HYV9{vQm|^CSQO diff --git a/代码/robocode/robocode.api/target/classes/net/sf/robocode/util/StringUtil.class b/代码/robocode/robocode.api/target/classes/net/sf/robocode/util/StringUtil.class deleted file mode 100644 index f1e55eb17b0ee30bc185c971b95b240cec147bf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1788 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 Omgp%;i>d_6@cjY!nd&|O diff --git a/代码/robocode/robocode.api/target/classes/robocode/BattleEndedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/BattleEndedEvent.class deleted file mode 100644 index 6ac49c5f89b73090b4f3188fd74f44f55f48e00f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2413 zcma)7*>V$C5It9tkt`2bRe^>5fVr_^>V#Z zugcuK>3KD|WLIT%>4~(xC?W#q+SmF_AmK{KGHWI2xK`cXDJ%+z2Lfjo>bC2dwpTK1 zN3xFu>QB&qacOyOr?~yY#%5uCv#`BO`$Cv^Re`8kt~;LOO6+mxNcX7bxdQJN+pNu? zHk&tjfits~ZFzSEE~WS0WR)oiL>8D*9AOL_7{Z7^IGri=gT4)%#W}UQXkZWtfx)6> z%eAA&W$A32<(d>o7V8zJXfjdm{lkcNXfd|YAZw>!46omE=UO?Dky*tLr00iE%5)|O z@1&Nb<)Yj-S%VG7symkVOov?%7~oasELOGLhUrxf1Olbfaj7O0b z7;B@|;tf;=CU8Swm=SA!-8Mzb^`tEwflPM=db`mGHy=e#;Mxh4P21@>rf@5YX||hA zqGs9$x%KixS@8_a;I=@F@hsF#mkPea5IR=+FdxS!_$-P~*$sg!19w1S6BO2Utpi(i z#IjR=EO0)3%uQx*0F(IKz+K$qOw{eJnG(3%C05sk&Vhv%=+gyZ)~6GdBg2tX+EJU+ zD6GohOG|}%>P?ecTdeCR#oEs8%j!RycC**i993r)ojw{9DGqMJ-N!7vvM#1LD>He1NkmT{KIW<&(Z*c?{(T6kKMY#(h#(f+E?Y)7ddNp~MRBtA~ z>TZZTjuUsg#3(<5*_Sw<9es`q*@@>!{m!EhM)^NU3Xm?s-<^KkqN^EP;>ndJ4DaDG zcXXg>gkCA45DDI=Rg)&iue$5Y{(%d>a?y0I;s$25L!)WnI~4c;AM!-S*bPqo7632x z04MMf#(eM%eicbLQ4R90c0t2F?+~t@2D;M&n!q(&_gQ~tg6gLO&~R{VPy_>uKB`H)vN<4n_QyXskd zfjOOD7V}sjD><=A3}q>_C7JLG6N&`u@~A7hP@C!jzVwspl=Mmv z>UKd}C5@qoRUewsT?6$0g|%Jr5*tA|pK1q8BN4+Ewtd)DKUUQ~$2uU>1=&HV2jp1C ZrCSgd>}wV$gl{+r;N%ECCjxtj{|}XE8F&By diff --git a/代码/robocode/robocode.api/target/classes/robocode/BattleResults$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/BattleResults$SerializableHelper.class deleted file mode 100644 index 3c98b06448e813d71456a4c28d87b99562ff4f2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2462 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 B9OnQ4 diff --git a/代码/robocode/robocode.api/target/classes/robocode/Bullet$HiddenBulletHelper.class b/代码/robocode/robocode.api/target/classes/robocode/Bullet$HiddenBulletHelper.class deleted file mode 100644 index dafe0255811b08e637986bb7ba94a66418778756..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2776 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 diff --git a/代码/robocode/robocode.api/target/classes/robocode/BulletHitBulletEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/BulletHitBulletEvent$SerializableHelper.class deleted file mode 100644 index 8a28f9c34303c21b985ad1cedc89fc6ac87935b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2027 zcmbu9T~pIQ6o%hzV+$cb4Wd>>Q9%>h8bR@c;s?bKsudhjX7tLmY%xqtoFsJyFTC*g zc%e7I$c)3aKg#iJnwHXL7}Ru{>~3<-dCqxv&#&J$=q+j3leJLOq)RI#% zYbz#!(L7v~{CAeeFjZ>BK4dz1Lh!6le5uMXrr7++h9fz8TLcU%|DcF%IYwc_=Y@K;8ZFa`(BP7S%k3IW z%FvNXVuJQuhky#Q$T9S-@$hUESA+dp6bcv$E`kJ1YmKBk!WVUlmd2F$>Ka2P`l~20 z=rknCK@JSVk-iCOmA6&v)&EyZ?^aI6ZRC@fVHgTj-JhU>Sy7t=)uw3sqK0?H$-T#r z(;m>(=5N_|Eqkr~+=MG{!XnKnC}5sppe?I8dxJrbu399liiZN=5yN=bk;->&zP#u; zRAtfm7>;(mrrr3i*$^3~yBzM{yb;}!0>~hp=wK~7b+^JFS)zxfqq@@-QC&0ShOAJuLtO2 zES}xOtu5SH%+TQeF7z2`2kPrwTH3;cZ>_2fP*#9TJRU`@xAAB#9<9Zrg*-zT#$zmy t?Fjl%q>+>YiTNbt8Kqb}@ZCYxSv92wVx`!dhy`|nfJF*=n z_PD=i51TZE*rYw~VSm#!@mL8dE^8pVwF%PQ1+!~8FpKGzU4ZP^`?M$C~#)Ob^O3^g0^Az z{h;(jV476r~NRFnGDC{ZJZ(H)OXd1UnLV8^pu z&kCN0@#+GFL(A_Pfq5*@8OmId6s1Hg9oNLKQWEX_c??A2vwK z@&oBePoO%Sd%Bqr;n&Bpgd2G*v%Dwx?E^~CaFb2rI*GOwxH`mA;xfcCOM$U48i8wX zYLgz{Zpf%Wo}I0TBQftnFYER+;+6EIl1&vmX6pJ$aYQ_E%2+}3`!9`d)RgDR{a!ea z)=!Mkb@rck*}!b}b%BcMNh6Tk*5RRa23o2ztE^12OZrnCS<&=?x*C9OX?LYp&*PrJ z&A32m?9PqCifG`znn4D%dO~qh;9LJVFJ&fTLPkEj)DDYgwcziBV#y5v|Q|iUx zs-B-R&hk6O(*f_5oypouoU1LqK&7_y0vCUyC__^UmgBd^?;@c~G_j2LDY?>z;R9Ua zi3UP9BHSrQ89Mk7mm@bCS9Ld5`yG{Ex#=5MaRaNN!BSr#GAQUE4SX>PZlr+An8j6^ zQwc6}RZgpHW(X_!rZ8(hb}} zJ&NZ|DznK{zDY@?fV=oSf>y(7vG{+YaUfpeizJQTh6Wf>xquBcBiKCGLD@!_pB;j1 crb0$4ePsY)?pw?)g9q5=TBMf-|8*2!0|k587ytkO diff --git a/代码/robocode/robocode.api/target/classes/robocode/BulletHitEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/BulletHitEvent$SerializableHelper.class deleted file mode 100644 index 9ce95f32d69983a310e50cc1d6a25a15d45f4e86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2215 zcmbtVZF3V<6n<{9NlI8tN#rFJ6`??qCM;BZp}}g~fL)EPQivAc*rc~{nXqw^4Kwf$ z)WHvq;EX!{0zc@Nl#v;S&-^II=k9Kkke9+}W^(u5yZ4;uInO!w?Bjp_`WwI;zKkIx zkZm?9jcQ|48cXeZUAil_d-0ZZ+?jRRw5_^*$EwujimZPvn=xntQ#Y(zmQlBynz2^7 zA**f-QGv6LbdA=Q(RJ3^v3Bi-W0=Fv1fmyg$95M4!s$#|KwBn>IKtSgBZdiqeI?tG ztL>W=*}S4i2qa34s#PyrB*t~HskvX-ErDFAi~ZC<3IuQ2cjVfZz+$?zJNL_#9rChS zC=Etm$e1xC1rCitk0XHtIu7EHz=Tz;%2sRUj6gm;j&32-hq3N9ZKqa9`=_p1>!pyl1(Mvv-?%zHN4ELgbeAybn>l0YHWZ4d%D;H<^Q0+V>gVY z+pb({Z*7fEN?GZCQpYKzd%B-xpu6clkV49yMJ|R}mg2xG9eJD<*jtmXUu@>4SH`Bw z)EOPeL9A4u`~X`sLvks+s!p9_Mn|9O6E-LUWtPC}I^MvWy_n_%j_eXsQ9;csD5h-; zp`yBd(Tb-f>%~VNAkA1eWnb2={{O7?*SX(GDEK0lV^|VMdUf?A2^~cxdX%D@j;oS$ zNp*^M)om*BH!Ruk&b2^&Q^$LFUtoV;3^uVjoxh+F(CNWn80Ejn8E65fZBtv-t;j zzJtTprzWod&TZdS!aMREaqrT>_cXrixy|~ffm=Gki+IU{O5$ZQ4$)!~ui%)+{5WO; z&~Is{;z;KSI3 zmd-~WBC(Ou4oC9a`0$SbnSLg*UoeedDZpX_r{OODrD{OY;0Wu280FT3Wm-#;BRsq&)sa6Gzri#Gs%5>&hv7fb8r6s_xC>m%;AeL0s@z<+IFo{ z+mYHrqgs{Dis39BO4A7=BrxP3x_bg~TUv%*ElbNbYUXAkFCZQZTv)7`wxgR)S+6!^ zAKj~upnZO6d4984`f6>x@NB(M+M<0S$g??tkf|R?fkg3Z{ZQAcy1A!qIF@1Vy5SL>Z#v1~`bf!E2 zfh#dwz>u1~8N)@y)$FYpE+HXsv1pibwQ;a5t&+Z7brY{uNQF*9xb`+f&c0y_q&fq) zXl2F&d(vs9FEE_WbXs~AOCABtjTD55DH^+s8qLePB`dlkcNk{9VLHZvEE~4L9Og~4 z=I9PP!xWNjbev%5UHMvdsUKnV9^}VpuufHY5&dNol;CMz?&^)Ivt}7J%W&8xW?2x3 z>=<@kcPje=+v$_KRMQ;8bfmSbSEQ{K7IfRFxDj$iQ#zWxtND$sOKE8Z_i#hiQn7Q* z9QAJ@*RogHbmtW-DdvKyVsXg)oj7p>4TSC?-^R_oHrh4EA%>o?_9UdOuuQ55k^y#Z?i z+Nllc0d#v5(JNH5Jw7WieJVKD^MbSwg*> zt_|N!jzhE=#t45$xjLXX_5U!MeSu_l@))UX`WRQUsn9X5{p!Nr=5Nw9nnDQE7{Cmj zXml})>paVHmkw|PV;t2?1s3j1g$}qg6+Fb>3^Md0RcU0aQty|!$KX-r^dV(hi4kArkAj7W;l;wD?yC*%}O=8N=<)n~QXCbAY z;OYOH%a=Xf%`lhKOFJXG-5&1ZBzM*;ZJMJXN5S~qPaN7iWVS(rUWek;=bQ(9PHUyC zVv@fe99^zv+nIz`1 zK<`SHi^$VYgo0bbGCe)wZUo{VjE4EQ0IZ~( z5-+gY+2kKx2h1oQ!6#VvU^h7m!j!_g7D2{&30()B4* R3E(qqaf}jNR0`d|<3|ZSMTNSIy)qLGBxcf|Z z9A16A$4z%?gWI}h==)mP;7_^np4$>44E?*>o~9a_xvj33cX`E?5M`J*xvM%gHNbP4 z)~;@uYM~R1A-b%ax_h4?oJ^G%BCF(wj4*l?Na$whE9xd+tG_FA`-O0VVX$abG^3=E zW3=`+BkqpwFsQ|V`z*2Kh~Lro`Ff3EC0RV({paPT|J=?M+Xcv_3Jh{HU~V&H{sxa6 zu{z;fJpnR9=^s2bbxX~EaCyF7tDWqANx~Sz_@DKYF^UTc61d3FtyL=Aai-=- z^5iL+=ThxIb227yS;8cxwv9`{68QEbt&rv}6DiD!tMa>9^kkD;YOsDgT{yd^oC|DT*xX938V!-9l)h9R#wevd}M z4Ix~Vge#b?5csC(o?Fz~$w&0G;BC0JZf>`hufOw(6cHJ|BP{PS#5>ZO^Cc5k1j9hP zD5S(fhfRx8CtM|jD1!u~#@Vpyc7;FDMT3uYwC=13nn5X;Cbw4&jqWFE_Q7U99$!wF zB)l-aU39;7Atde)TJ_LMrJ0G{^daQW^bvwWW7ON+#5wv_8V3+VAFb$?!vKxK_#w?< znnT?m#n@u`(zBdw{Piuxi9rl`Xd%QgOlt}Y=Y2GjP74R)+3y%#ip*rjB403mfJ+CM zI`%B)VZJ60-w@VYk7u!A7x2Ubo;XrS6Az(!jA62iVFnpQh&78@pL>UPBXlZpgo&*f zJ&c7j2T%{OxORlmt?VIge+puhJw%Q8D;|HkVH@x#0{(>0KSX*hA%}23Nc?4=b(&`3 dn-Krrafq$ri{ByK_r?b#I3Q|+QAw^q{sqxUrj`Hz diff --git a/代码/robocode/robocode.api/target/classes/robocode/BulletMissedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/BulletMissedEvent.class deleted file mode 100644 index 98af0cb9a417a9be26209e54ef1309588becea9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1858 zcma)6U2hvj6g^`*UB__~*NqJ+g;JWdwnMumw0zis(!@!-$SswVTIv&8uP4pIvTN_!6Trw^G>f@~Ha%Xmyp;B2iv9n6R_Bii!F9(nPD&<#R2eyTZH0{MX(4ei)D7U)kD zqiT*_KbGN_%b%5BQw=yC}n6`+IbM$vFk*w&NucG+qA!r%{!qz zJf>-@-KzJN@E+C;ToPDM(dy4jjw)gUmjx=SKy|+EbH|Nh>B~@{K3VMiG#U}LmQX{( zKwV(tHRp~2MQq}IPFUbij-J4U35g~>8pZkq7Bmlm%P-n6pIKLHDPV9km1LCU{|L*D zJx&y*Fmq*Qh?i<~<#jv~g?LTaJLlVb_AnW~RjPiVFO>TO83z90(;)|yqrAgGc0y^# z@~%4=NdF{C_2eddGCd#TYnfy*t&?yy=y#Xe6OkT7bsdj2X)u8`Eaqp<=HCm z0bd36Kg{8Gz<2kNm zpz6wMB4t(t>`cSN;20pnJP?N*OgbP_!jfzsm_PE!Av)qD-ZDx zDh6K(;3IsT@Oe?nrRh@c&nYF3Pw;61t!wFl#Xrz|B%Wb=TE?zUz|NKOxP>ng*ap{^ YDu3|=!a{D7XoeE(axDpF diff --git a/代码/robocode/robocode.api/target/classes/robocode/Condition.class b/代码/robocode/robocode.api/target/classes/robocode/Condition.class deleted file mode 100644 index 317805f566903b67af7b3168d7bfc812c5e8fd31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1728 zcmZ`)U31%15Ixs+EZ0$7*ZC-rKvf{%4;qI;N>eu}ZD=6HP67^@DKk9CvPe~A$;dL9 z&cL7GnMY>&!UHhWoq-u1dEn>p18C2^QtdcyXFOVI@9x<>yGQcB|Nr?nfXmp^kPs*Y ze#^J~wq4!wy|xoNzNaB2kiTz!XI5R)JF4!r?%P%H^30A+fchx1 z83vAbR1-*FcRVND6i60JhYa0ffh>}k(QyXZGY~kdV+v{7y5rfq{Z7jc4$PLT0Da4J z56!@l&#^NV-g9~abM?t~S#G{K*+l73mRZoDAw&C|h#eX7G8Q$wGRC+0pcmR59ZPtX z1pGd!&qw%H#EF1Fso)Z4yWTy%n4|mvKPAC!dn98PtW#N-*MY^kU>%4!bIh-{lKuEtlt#2n*-~@;@&z7YWN-=A_s1ENu`&d?F9DSp>RFQh2lgB5V zq1~fAsPZqFX}PxP^}7Purr!@Nd)twE&JACz71>YfB4wH68BE)lR=9!9XEIJ5CRWkj6IUC^>zMPvS;K ySc_vijIh2Z)(Bp};HZnZA(>BVs?EAjUtKSk4VafA=Z=PdY^a diff --git a/代码/robocode/robocode.api/target/classes/robocode/CustomEvent.class b/代码/robocode/robocode.api/target/classes/robocode/CustomEvent.class deleted file mode 100644 index ef30b3755d00edf81074f6cfbcce56f1a2a44db8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2246 zcma)7$#NT26g^La?oGmu;U+CKvl5IPz9`5@KJ>GUN^1w0Kp4)zjudo?zw%h{`~9bUjfYEaRL#6LEGB2 z8dg&;Ep{B&+Fjn$O*es0m#@rplA(asM zuEMOZujXovC-=0r?>};CnM9O?#$+uQ1$x^7*EE?2dJ!j=4Xj)Ea>VCs1}k;PU_J6F;PFzd-^+r*@4l ztw5r}fABb>s>2VPv%TBaY`ty?oDUVL)F|gUU{O@lsDR5OuFHMHUC{;b+|&oK$f-0q zS?WrLjd5GBku|l5j4xTTW!9gzIf9)0g#_vhQ=ec$+}FJL=B(FmBN)Zl=I|K8EdX>nA@sF$(q%%8~TbN7eFS|z-dVU zmpHU?*O4>g=;0~BQv|&{Cy@%yX?!bJ6>V~F^&`Xo=XkQ{8{u=faDahA@h1!w|3Iox z+{cA|yz(P0QDV@}>_8qd6qupNTvHgrG$xfzWx#8=%#-w$NCL0(y&vKQ9U}>d1Xl|e zHm|Pu;9nD3k{=Ji3ll_@42p$)T-`^m%V3Pvfm0E~O)|JegxeUv9oD&^SY*9a0gG{; z1=Evvicpdd>wdwIsK-YrLIu|2sZrun-o*>gG4umpBC2>PD^OQ3Y0trj$xwy~-bg90 z@hSbHnbq%)g+302MuX66)XxijMj)y0@xmMhH|%)?a6Pz(`;5=v0cQO?Q+!GSk?8RpU#T3Pt`R@SIr*#U zM|PWXfD_7o6AF$81U|x=A3Q57B5d*()E*A3AK>HPB#BU4pM^3c{R{$+l-H+!1KTd) AJpcdz diff --git a/代码/robocode/robocode.api/target/classes/robocode/DeathEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/DeathEvent$SerializableHelper.class deleted file mode 100644 index 35d52298e42daa34412437fca7b27e1d014644d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1204 zcmbu8ZBNrs6vzLkD{JYd!y!JR4h6EIvC+3PMnQ>78c9HBNJvaO?%&%_IT zMWTrxzz=0Sx9!TZ5#qy(-gD2rJ-_=u=broX*S8-4o?^*>Mp%wQFYJZ8!hR*(WdHS{ z2$IDu5lPpV$FAp#H^TocA_F>M=D<#Zg^b!MQ!jnKGcHFlMP&|xIWEj|; zNf@F0Oa?M}PAD~7U4p*G0xXnJsltFss5vqaZwH?|5xr9)2z4jyxqjDWVeIFNda^HL zLenYEzA%Y49~{eLvC${IY&sX~-t>mTMbvi2GjF##1Z$Y7hzO7VhQ~s}w1O(J2{vK6 zAQQU(pfr%7y?T_0)j_|1zI?8F*-Li`bD4y(AVOtVjOcj(|2kTexf-}bm_6tIEX<=q zc=*Sc+v-|i&3r9e;UMaXb*cKMcGeM(RiO#hP7sJ_&3EHiaP!oM*L>FOXfUY6-xNQT zDQK!E*_&q1W=m>y>NBGOGbX@5lXjdlj&{;uj^SyH2RcuRo74BQR z44VTdWQx_7wlCamZVAsY=eZ}X6?K{`+QK)yZKLM7B7|$0`f}ChzO=kt@h#uy2LIq2 z&s<*FrK7PzF1wzsBnkxP0#Sv&i{Y%xd-o4Pk{VLkvn$j zphA5~4Lr|~wp^MXu_U*)gnewKsxv{=Io&DMISN<|^VnSV^^z!8gqw@v5lLAq(uvlY zv&L~u;)xoYDTbkj1!@4IE@X(WI(x1q7Nwf6))ObAN?nGeX;Xvc%iQw>m8t!#Ydio6 zK+_(=RW#ue?V@@YqkSBS+CE9=q%>OS*-91@J z3EP4Zj1rSUTrsfU=!(+#rf^@2u0*V95IL>EQiDv?7hlP)kR!Azt-`6yY3OntG#rE) s!#E}aXja!7xcnWH8|)B|zYtHo{v}PI>KH;!Kd14O);JMN(tif=f2D$YC;$Ke diff --git a/代码/robocode/robocode.api/target/classes/robocode/Droid.class b/代码/robocode/robocode.api/target/classes/robocode/Droid.class deleted file mode 100644 index 94ab802e129cff22a92f1606039bb63dc8af995f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100 zcmX^0Z`VEs1_mPrc6J6PMh3p3{G|Nk{FGFEm!ka46m|v{Mh1bb#Ii*FoW#6zegCAa s)Z`LI2Cm@z(xT*4x6GVWAP1~e52T8Xk%5tc8E75|Ffy1@8x%#YSg^3bLd6d(qO^dNG-`x!!HwB&2Ut?J&F&V0zsVbK zka*z_@Yk4VqKQU5Gh5r*7Ujl^?#@hSp7Wk}&e;z?-n|Eqz-kCShNxZ46^&w^Yb%G` za${>|KF=*VUgL!lw?hapbnokjx>nGwUF}(JpBrunZ49c#UCr6istAW0W!rR*wM-L+ zp>4smOm~sNA0OXh2&5@!1b%cV2%(*!D{ET(Y55?>?M*#b;0(RlqM;YIblVj3%3{FX zGaZJJY&Gf`!jlXkhr65R0ipWi4f~Vp<69B*VIYKlhR#1>3I@@`(5@Q>cbwQPLy!x1 z$cRP^1+n;%7lf^oW(v8?cl2_>eQujY;RZurQ*RaOO~e>F zh+IPk;u+y$b6&J8PTf)v$7n5w1OZ5B4Zt#Fx#^@yp-C=F6I&|X7Px5zDl~a_+XT&< zPDyu-JqEiewVFf1RM)gzZtv)1q?SqPj%mCQtI2F*?UXpTwT%38!_`TXlg!Gh(~n&3 ziLICRXeqIr^wPVnUBrhz*Fj{BRS?wZ>r6OU7Y!u73!BO8%L$RKH)dQF3R-+tDK3s%JitKw!bTfw{}|HP$))yb)$zzGr!`k0@- z!2yYz^EOs-zjLL-xP!YDC+^|C%r=a9JRmrudRu6r`C)@*7W$j!ZcxcQu3&_*GIc7M arJCOQk`aIVkdn_dmgy~unA!p>i2MT2RCg%= diff --git a/代码/robocode/robocode.api/target/classes/robocode/Event.class b/代码/robocode/robocode.api/target/classes/robocode/Event.class deleted file mode 100644 index 7b5251bccbfbcc8feb2cd1e4fb8c32a2ee544d38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3512 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 diff --git a/代码/robocode/robocode.api/target/classes/robocode/HitByBulletEvent.class b/代码/robocode/robocode.api/target/classes/robocode/HitByBulletEvent.class deleted file mode 100644 index 331690644a3a9dd8776d0f0df81bf6f6b1ae2531..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2836 zcma)8-*XdH6#j0LHfg%hw4{ZCB2|7gff9-!N)Vw9&|oMvEm0JO&E~dU3A>ryEet*} zzWVB;j}DGA&WJPo7<9%*AN-ee9KXA}*~D!GGLziB=brEU_|7?Z^XEUm{tn*`yR#xN<6n90|NA+SrsHf&c>m*89nO>CCx7IT#;7AIG8GDQx4KvsmcnEdN za@~=V9x`RwcBG+uvdJ>nHZ9M*BkQJXGR5h`lWtXFSc}Rz1YQ+GNkOt ze@utLt7uMW>>xT$F~}wT4mr#*iLRX$PZgFn3V2t;NxUPFrs}eNPdZ9i((sKy{UM}V9BPioy3Ks3;9C(S}0HEOtmNS(EooMc7f-4R@Ip_O8# zqpt3TMcHagry*|FcD1|zn848&z)SsZ zk`8w6W&OZgIJ07JI)=Pxs(W!Fp4d?};R0I4VmmLibk|ik&G^=IF$Yr5YcPr37{m~F zDeeZ4=01awXs=;h-OoH5SGP0QEYHTc6WGDsby`Vs9W6XVu5joHb{1xzVCol&2C#>} zcOWY=d;8oNSFE)`BhmS;~Iq1$>k~L;^xdAbKP9{Lg*jP+j0E8 z9(*?(z9k}jz(ttOsW=@E`r`RQiSR-2A^vpS|2KW{eDUr^&<5u^@0dIhFhaBU8!3b5sVP+CI_K_TO`! z9(-nuhor6DhuTfKNDg zL0fiHDa2EG)F+iRKE-DtG*1`mGyEHFTo=#qMZAoUeFKarn}&`?2s^-4k*B6;%OJej h12NEyAf0CIGkDV-2y>UTJAgH;b5;LuZt%N-%)c~NL(~8O diff --git a/代码/robocode/robocode.api/target/classes/robocode/HitRobotEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/HitRobotEvent$SerializableHelper.class deleted file mode 100644 index 264ef7d7d22ed0bf17b3c47b125aa2f9615c013e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2148 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 L84y?29jHG6f;VSY diff --git a/代码/robocode/robocode.api/target/classes/robocode/HitWallEvent.class b/代码/robocode/robocode.api/target/classes/robocode/HitWallEvent.class deleted file mode 100644 index 9270b4c49c9932c10aff39c465ab0d0b0debde58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2038 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 Orjgzp^uJyxRQwm)cHlk$ diff --git a/代码/robocode/robocode.api/target/classes/robocode/JuniorRobot.class b/代码/robocode/robocode.api/target/classes/robocode/JuniorRobot.class deleted file mode 100644 index 009b0b54fe1671e26186de0c7c663e0265428bd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5817 zcmb7Id3YRU8UKB=*=&wUnzTu;OY9{;QAT<3HkK{k`AJPNr$v)IT!s`+oDi z_cfbW{=4^C04L$y6byxyk~iSxyu6(~uk1QrsgIa#08odz2 zcU<2tZLxCpaJDBVLm@d(v~pJ~s2+ueHJ&@{Tdv=470Y&l27nhv1|6To{{8zE5+yrN zRL-ltlI0fU#UnzE+Qp(bBG-hcP_k{80=AQ=8VH4vzj~-#8Y+@$JGP7Nk~hL@cdVVo zYlV_E$`{-DqHc?07xNc6d4Eu$UK8tVr!eS?T7S?k4HL0lyHpq@q8+@rf^1eu4cb=T zaSIewD7)+8M3-%q^qU&K>Ejy;P?spo7|vO)Yv;Qi2|&(PFvF8hw@@V67?P2I3P-

Q&fzwTV z2&dLEsb`pIM~z@-n#cs$*(N#ytjoml0oH9|S%95mVtIhAGqEDT&NGn>uwD}<1lR@> zCkEIBCL2KO=rgerHOx}4_GPBpqS;c-PRp{`r${%!CA+x7+nC>Ml zDG>VA-jnGUA1*O*DK6u|kS&qQPB2bx9=VY1VV5~MouLazud2rt_*e>8DlCsed?bt} zEDTWVR&N_!scP@e^w-gvya^kp(th?j)8JS|=Q=yT_S&31jk=Q_qR1*rU!*#eJh3n%3s_Z+(?1g*` zo48Tr&2qicR;$=&7cJk}X6srOk)JR*9vGLDUoN?nDG3Xjur}{)VE?m$<=!nOJ|%HV z+1J{+vd<7Eg@e{9hZb&eN-SE1+fCex0l_|F;!b>)Wkg#K?2V50%tX!)-yLn4U42dbtuHw!`&GKW|)p1Uy^ zq2bF!NitVEZ2N1xqNgWzdruD=E`_gED$E-3v-)iv9>yawTrQTxK5F8d_?C>|pi1=> z)=PU}W5l&8(=XQ_H}P$`UeD_+7kyjKziZ-qa^Apm7Oqta<uZZ>5v!HhSe! z&OXPH)zK7-(+VkmdZd@(nxZv4Y;%k>AG8~>n6@SOmn1e1Dbx_J<#&>SI@0wq+9cf& zqZ>)jh|x`?n`87$(z9Z83+dJvJ)88L7(JKtycj*7R60ht(Xs`kv;y5jbD_=t{d=0toHRQ6_kgHxpE_w~Q<~8J!*N`h-LoRp?x!yJ8 zawjw-<%D86KQs9JFsWTUSA<<1dvIEZu^X%8v05Hybu{hVjZQ(=$YZTM&Xq@xJkFQL zdU)6QW>1gEhL{#AgX74Rh?=kl8V;&VPR1G*<%|W|bg5_!%PEx0G$#mij z)r(H@Y$B%_ScD7FPfE$A4XrJ(It-r8>v#&AUqZ8h^p0^{p1`B19z#xyNI;C3%_4%j z3@LRvW~wXDs;H^qI+if^Bc(tjx_N&lR{oEd@co7Ex0c`H@kh9-48W~nK=-3wFQhh}v@<`XVaJF!$f$a31HO*tx15_zA&r?vNuXu%F*hR(5xWb!|#SM~o! zO3b`9ipR<1mv~fn%y=5NO-}V=)c<(QEu_?IaecTUgv zw<#GPoSyN6DH*>yEu&FCCF3qU6h`)O&Xp<#r!%OE(**3p!<*B4@bz(g!$9SrO&>fq zaj-xie8)JbBNuW%!kEJfo{PE0JYRJzeV?C|gpe+cdPEBM%O*r^L`9J2L$mN%3D0h@P zWkM_tLaKM!b9g?zqfN&DI9^B|lxw}rj4f1Hz#c(WXt0=JQ;M`sEhv|gddG40kjUZoMQVTtiNmKtxM-FQ<+ zGH^K)8Id_~>n{}}-iVAiFp|HR9LaYX$@gMnr-~$ha!en|UmoJq#rQj&_y;5TJ|p>0 zM)F@VZHJHKZz8?ZM3SFV1^xYWC?gWpNF`EOlBmJbL@nAA!3>{1l7{@7BXoWf(tOl!&j diff --git a/代码/robocode/robocode.api/target/classes/robocode/KeyEvent.class b/代码/robocode/robocode.api/target/classes/robocode/KeyEvent.class deleted file mode 100644 index bb417c4d51c9f77bdda897808f453fd657713d1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 546 zcmZ`$O;5r=6r5KING)IW6G0Pi6cd|x)p$Wk)W(b2`+^&-!8U0N#($-W#>9g^z#nCN zyA*Ehp>OBy?7W%o@89$~iUV2yZ^?WL$tPGP-TeNkL&`4zxig6&5 zG>oIWi!%aU5~}?;N;45Sr0bDI(&j`5;v024x{{u8EZ503j diff --git a/代码/robocode/robocode.api/target/classes/robocode/KeyPressedEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/KeyPressedEvent$SerializableHelper.class deleted file mode 100644 index 4099bdd9ccb9a65fb11c13b64a5f514e2e0df9db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2321 zcmbtVTUS#@6#gc+gW;%%20^4^QB1f+dyz^Ik%%=hiUq;qwI|604uo@DCqaw9sSoW- zaMiWC`qYR1jQ)_Weltl>+e7Q1mF`m1_A=(o||_IZc!%h z%e_aQtW;!i@r`tnX?`FaCav!y~hfK zKyS`1SmiZ~!1&)-3{^Mnioj&f_x<;gr0Bh3zmrQPf!p!iUxQ!HH_=Nkl{*-IDv=S0 zHp7*kz{J0?M{N5fw;Fd)$1DSJ`$W6;ET z3<;drkku7;*DFX(5rM&Yq7K@6TTMzu8$~0%nTp~9E*cmXIIH72tYYG0j4*k$%2Vl0 zi^(Gw(otN-6$7IJWBL&a9f&)fSW|e$OpIfq<&uokE;GvIlroX*Xd+WL zan0o2p$U}>qE?Jl6j#EcV`P=UxsI2DHy~K?3iQ&kfCAk`*+#$B|4+XL zTiUt@X_CQx16hI7nkIiPoQa&Gh)R;;hf;oMVoBvRqO$B%)zVicmYccExz0uuk3m|m z3XC2mP+`}zt9!{6t0dFz&TH2pYfU`C*Gwi&s&!3Ze^a2Zo#y_!X82Rptey!BHF&33 z-qOfqGnup|PCs5K&6fh_+cXbc8C6+hyLlBvy78x3D%fVaxz{9|K)^0?X{SXi_RzPQ zNrKtD8t+*9BU*b(k(<_dHR>1quB{sG88W>6QJ7LC5->B4BfWIl;%mXy+uQ7qt)~LR zv=-zS=35g+Ky`Hf9phh;vrwyJ`-uKPApnzOL@zGmIAyc0fD<^$KfXCQ#Zeu;%{j<9 z*faPYr}m?(`si?dyK$6?=*4MmE{HRT@dV3>vkh~Pw&c(sf_DQNztvK%*M)Q`&z8_+jw6BceEPwEyl z>bW`!A9dD8oy9zZ4k(Noe~_AYuz)m?AID9~i_EXUU3}Sy={Ke?O8xnX8t%<;cyK+W z$FLqFdNepbn(q35{`C*Iu>Kw^u}EK6%!q}CV&Q$P@8kLRetxIWO}Rur8?qb`+SGFzqK$ zq!gi-5lBh~=OLolKvxg=x7mpIGG~<^#V5O!{&qg8?EnF*aT{gMitK#!2sZi$j!rKP diff --git a/代码/robocode/robocode.api/target/classes/robocode/KeyPressedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/KeyPressedEvent.class deleted file mode 100644 index b8c294e2130acc461729d5d016c66ebbbc7f409c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1770 zcma)6O>+}R5PdDlmXU=Kj&Lw0Byl7n`D?*}5D+LB%Z3d~a2ew&a!HL=V?2r2Rqc+Q za()HZ{09zj3FV|Jl~WG+QB-t*_L6X0{@ZQAka62ldFLrY2oW_(b1E}>N!Br+Mb^0f?igeN1% zy(1#!ZJOO$)0f(bcAP$|u9TtU+QWxhXyrw<0hzm@=KnCr7JKmJ2`IBFcTDCcnzpA%-dBZ+f6tEP&y^kqnJ zD%E3JF&r1wav)Umn8Q3_f{`EEnZ$~lVX(KUV;qZcvRER_zgHa=GRotUQBgkd2dXEG z*ai?T9z#7bMM9PZZ-zxEz0XKlD^KEC63z@tN(`7?I{hXt9>e2k3;7DNcD$dy72R0< zMbk)oS=BGhGw`<#x~y}S?H$6D7fPY!J=JbY|BaU!-Bs@Pu(WztK1OleH}2-9-IJZJ z3~O0@ogBfSt+wH%qY*jOv0`pBbGekbH}8(LFG8-TkacD5esL&h$*6_L>-sFl)sEmt zjb}7@lmsrb?#x@1!a0m!l&!3_#@Nnbyl?0ElpBl*{+?owI!B~<9i5whg~Cf4Gs)ka z-CbnwC49j4RL=`VoMDUodFMmMDBvunW2{A9iOg!mqe6{}*NtQ6k*POlSVa#B^rvH&hO>kb+^Ew%}7X=oU_J9Yx$` zCMzhRVUu0y0rnY}xkt;EKp9`)imj*2#J*&#BG+*ZUm=6*7Mn`E+(0d6Hz;gjxUl>G wQ`i`8;#M45wNn93{DJyodWG9B7&+OQ2NuALAca-?ZD5U8^N`f}e;v7h0i4CUi2wiq diff --git a/代码/robocode/robocode.api/target/classes/robocode/KeyReleasedEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/KeyReleasedEvent$SerializableHelper.class deleted file mode 100644 index 9ddeee994880264acddda79554ef577884f5d8bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2327 zcmbtVZC4XV6n-Xei(ys72BApBqL?7Er7uzmA`-DCMrlE?_}Wb}frYT^*#s^ArhaI@ z#GZOiPe1iTe@1^uPoJ42n+T-GwjXxp&di;ApL_2!cmMe7mtO&V3fDkLVAA&rUePN_ z>#p2ikrioIWohZ9bZZw@rSI4k=e1p^$UCy~Liz?G0)5-|OWUg0?xwX|*p|hbftbLw zD{EG@Yz5}3t=l!nbFJ)QV*;@`$8~D+0^ww8T_BPnj5xyRHDRDf;AGx$<^8?gg7hCK z5CZ*quV`1+Z35%Exf!W#IaPtFeBk>%LP^to)p;$K%K|r(`F}>gQfR@KemZ|J{&XrU z5O2jReJ1ta*dq{6=TU`s$hN?-z_P&le?aOwp0&7NlZ$)h^3m|u4GakkbxmI!gBUh( z79#>DHf3$q+w+T3lSE)RnQEZ6U)3zBh@+UK57Tj+!+8Uv0%vq!hgD2`j4@`9R(UJ4 zWixwZLne-kxMW~lVB-BtV`2bF29j(5IuLj!wXX0?n7E9|wo7tOyUZ$=Q_6(Z)kL;o zV%p^Mp$U}>qE?(#Bv;lyH}Qo!it;FXOYO{<__C#Z&nr1)NBY&J@72+)i8ST}3@Sg| zlCH*)Q#j@ojvHNZJG@kfvM>X99IsVR{VM-NAz|6X?^fMK^T9xd-{jDC^{$F5} z=ED4<{NqFsQf-~9V_aFBh1#8XgZNJrLNGbT^yUhVQ#Kn4IDwN~@yCNx9M$EUoWq>M zeZxO+>b$z9uZ}j3n^&obew^0k!uS9Q-e5s-rfKeXMCcgEUHJ`zvyq`l9Usm{FHa6d z>-eaS3k@k%$CZZkNg#a|NLK^tS{>Kh0gY?Gk7)lfkv*l)XE=}N>_OkLQ`oqH0?Av{ zsOK9f0@S$xbq)&*I;1da{9$U|!Xh$6ejL{+FEPIYxA9dorazg!IQ17M>$o$|;ojAV z9;14U>Cxc$^-RxO3~s!|xs9K(nurbbB#cC4BoTdsjW>AmW02n|^inR<&nBfU7Q0&R-b786Z?a4XgRFd9VydTXi>%STi-n1bRTWHThG|vO|z{{7`>@{r5l9vmDaanUpV3i?MRc}@UaQ& z)ons%jVb1k#<@HuFiAMuQoek+_kCN2TcX{SgsE2GF)P8`cpo2T^sb5sbFE|@Zc=hdJIu~D+h*uE_GAxh`p|U9I7Bx`hbwGR9(VYM@2oMyl(%V4>n&euC)#law0cs8j%$riw9v|n>PKYmg`&61M=MQk#yCE}#Vjrm=Kmig zj}P$?lUI>zhzL)seQC2;@?U3hiLfwWVScwOc4y&aiEqxgh zoJ#eCRt(2Q^&AM*JQlD>m}KN9b|$gp<{0d4@)$=AP8Q3A#Z%Q`A)`D#HZqzB{Dkfa zBenyC%O`M8jFFIK$(v~rN~f7Ai{*JdOv21jO^FG!OLx%4+6g?4_mJyh@p#{TC3>;` zr%fmAbyYty&%ob0=&{gQw|5D%UMPi@_f@AO{nuV*cGtPx!`kX!`WVG=U%Q*Tc3*aT zGOTBDo3J#PL87m=<)z~xIW(|pE;N(5nz%Wq2(_<5t}l`eW$ypXaMZF<3?c9OEXcL4 zh$6{jnmSGcS6O@JK}z9$j9`>^S-TtKeGcP;eV(n{V@&e*EPFIKBE{?I!r}`QezP%C z{LR_Z8hbC}9p2COy)ca#-myQQyvrB`yoX|pRpXV|mM*k^;UxtFWT*hwEl9p^jzJ1c zZH`Y2ji1=tytn10L!2l4j0=l@WBw2&!i`KZ^A9GAnT6j`ImA*5hGp7<&)T3{IKy>J z;|?=fMF~xt>{=giz_`pkTCoJm_ypH%J!K~LDPv7@9iQQIWblQ>rV=kVP>NA y?7@E&HinzH6^B;sRDd&oqVbGg;Lfj%ob1da3t&c&!kYayvCgY`Od9;Zf!r&l+q`N3 diff --git a/代码/robocode/robocode.api/target/classes/robocode/KeyTypedEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/KeyTypedEvent$SerializableHelper.class deleted file mode 100644 index 3f1b4cc44e0747e982420b0c440d85f6a5ebfc14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2309 zcmbtVTUS#@6#gc+gW;%%4MLHMMKJ;7)Lx_#L?mKOjM8$mchJDzK04;vGR%{Z>(&kBT-sWpK}h8W@qquYdmE`if|$CVFvcM7t)qCg1r z=Dng_S+fa@>*i*}-*jpM z;M9inm%ZI;QEGY!3?@?z$o6aBl8Q2lK>9Ep#|2z8Ff4FRM|D`m#D^GR>S&d>GMhG2 zM;>J2xQr_XMg_+Hd0kBOAt^ABYydhCbtbi@@Qj%l$3)vD*`{4)mCH$G!aCMOwqfF$ z$yY-YDi=hp*r@2Otbc0aGj$Z@QTC47nKJQtOZkCUa>|aZ))u~1N7E+Km=Q3j{Ag3U z8b?mym{mA#9g8EU9!jjBt0|B;GF%!Xrv&aG5N>NUC2 z(KkqvEbbe~37pj=`E%J!<52KUh!M^7AW7Vdf2n;n@r#Rl$ z$mX)yjHXRLo+-`e0_Qt44?GxES7W>N5JaZA(i|0RG2J|C(M=%al(@CiCKbEqYt19U zY)&SRsr(TwJ*|jMTYMIc$9>n)jh5_g{|Y8mc?8U?>&j}TV%KVt4Y#+|7u!Dw4AWMa zUzGosC_<`_b9I6%i?dL>WBZ8zKp_N^V@z)@;Us0Vp@363%@zMNIKxq0zRfwzIovb& z9jDH#tNQA2)< zbzEvlsXDGUq>lpWlR&y2NH^-Z*$!w_1Aa{VPl)UpeLlxUykP73h7H2TEfh%GqDDR2 zKoOwM1*mhFW6&XmQR5F&^A6^bA@Y;BNqK?!6}XEpnlb&x^u?(^H&MsESq=}bNAwug zV@!_*$1kV4-l2c}9WJcD#d0Fn*Of35k)cF%AM5*g`hAe!Npw>#)6WK_O%}spG+P+L zHb$_6D{wId4>vf^aIH%CR7XD-L^KyfG}nwM%Fg$Kx!`YJ=cB-g&X65N<|Rt|DU>M1 x=w$?wlEHb1C^pd51Fklk@m}Vv@}v0VwA0_oCv_YmU^Q-|!dX$BjgesEe*iY1Dj@&> diff --git a/代码/robocode/robocode.api/target/classes/robocode/KeyTypedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/KeyTypedEvent.class deleted file mode 100644 index afcf10577cd89869940ae99992c7daee70280223..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1758 zcma)6-&0dZ6#h;U2!@D}A{DW=#l$8cxt02(HJXY9^lGdQA~W`-v$w`zX33ZTWKT+<6+PUyr3za zyK-w~t1X+0o6^^5qzK3Rb@rN&i)5%oYgLAk3j9ZIjX-w@M;8J=(!$rPqO~ChIDq*h zwy!NN%|EKI{PAGfy}#_PJZ5`0$+`w%@S5_Kt`bfc>wk((;fQD2ktVz$V*^%7tAx}7 z^UENK<5?WV2;o>=`SQ1ozZx=J5sj84jMf8>SqbLGa(tQ6>nb9gtoP^9%dx@?qF^KR z*ni?c0*w7c>Y7{=8!i1HR6(fp79m+IxrCvnirPYZ>x4$J7skZX%GWYn6P}D5_oj%H zw`^`Jbzf>HT64Ob+ERv&Yn2bR(8`M{Juotri6tXyn9|)6Nkv_fcR9!_{`Z6Rq#nK_A z*y|TnG9Z+)n8plYgpnWGp2YJu$zTV~#xQ2#q){f!d{G`2GRopdGeeoc-XAj}Azks}cJUQOed!ijr{+KDF zT~zg)c?Q0jdfWG#yz*Wsg_gHfvnl-@E7Q13To#DgsJ7Vo{q`ADF>m&mnUwo>=5v1bCCGGUV@cVa-{n#^Q$onPJ`dqSOGJ_6?u_my zfD1ft<^@XN6b3NJQrb#GEN3v>m9wnn(qe?a$JnCE9tl1Nr)ORv_n-9{Yno30G4SsdpHeNKL;)aU16oFf5Z6eB3%+#}UqB3^$m`Jo2d7 zU>7@pUB(5j(VQhvz)!en^C>W~%ZxR~d0fHINZ}WYO?f`9q7t*~C05>>*xgSgHiT=q q9=n!oSAZk`qxzU$;l{s=++Ugd7QnP1fd%`mVUbVsfK>T^37L;2{k5L} diff --git a/代码/robocode/robocode.api/target/classes/robocode/MessageEvent.class b/代码/robocode/robocode.api/target/classes/robocode/MessageEvent.class deleted file mode 100644 index 055e5f1d0a6d18ac3126938adbd4163d7f9508ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1810 zcma)6+fo}x5IrLa1d=d95n$Q5$g<<;0^S&tIJSrrgTPS`F@ z+HOZ!Tf+BwSF9fiN5v6ixDZ|$9Yfj|p5(o@@O2pwwREkfNiKipdp$uW<15mU>K;R-csjz_PNgjG7Ad1-(W-!MPEtcAoV7QpV z6fWq~r4*)-W|(eBM|?Lp+!J0)C)HS8o9gGp0?C0grVgafFy9F28fB7@PIiTA2GwSZ zrPF8`5@Zs15t9FGP8XdayPDYNgPz*xmrcc$wEgN3E&oYb4?NyKAk|W>T52azL^+NU zL*f5}q)@>ELsI%J!4FM%gZgnCHyEyl>Gk0R*3dkOMSPmVO)N2Fi35FMhO!}jB^*6R zMPlvzNXEghCb5jq+Pm1Na2sDR%(za_pdDcgc_cbCC?ha{- z^nzxdc1TlBxZb5P)bVc65!&K2+e9Y4ke~B#gmn5eu2a-{`^PQb59V9*9qyi@#cw_7 z(=O27tj4iUYw~7)*FDemCh&lvbiyO=?&pPmSMrK{^Ny?X{-ED?JtaB`)KJ&ENH59k z8LOKi&a%?071cO`~P7{fS8agrjKAUT0#D5sFoOHOwgz2fxM zwlgF#yhqY5`RF*)L$Fef8Z~`B%(8r^7I~#sb_j0aHVRARxmP6iA~njymVwc3wHd zIgP8h7C0}`S0{<4H=n(gw>IJ$4f3Y(F|G%$PYI=d+Y1ZF_=MpXT(10u#ba0ucVoHO zYb0~A@-c2jpy`Sly5@{WgQ(g<77vlbHdWFznU;sqLdpubgS!S?0adI}Hp+!BagSnU xiO#R^HPL?G#Aa9Mvx>C<+A^8wsuI7Wwwu{_g>U{OX_VB*BgG{`Qa6oN<6o=dp9lZ| diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseClickedEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/MouseClickedEvent$SerializableHelper.class deleted file mode 100644 index cb56ef26dae119199caa2e12bc45336adfcbcdc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2317 zcmbtWT~`xV6y2A641_@`HV7&LRcV6YR9Zg@mR2Il&;YGq5K3$FaRY;4hE66b{-!>( zFW{(>b^J0kP5PFo3(Q9nRCxQ=j?O#oaFbve)$!^1hx&d35@$*!7F+t zX)SoQs?1cJ;!|0geJ0)D^0M@ue8qX0FI425tn5nPKvbZ6JO3;-bBRxTf(e$GI@z`3{AFM&Rs zH*o<20;e`*uWKlSv;>B`}C#149D+8ryM3CO*I=0;T7f zS`c`yri7iq6?|x5L}2vY+hd{^DF#c`b9w{3ozAI*MonB*5xW>sb3WtM+(4a-o4BS< zqC9!56d#$m-c+n9#m6Q-QHmHX?0ZUc)5I;MQI%QnN>164es%VRI{MVaBuF)bN2^=1 z4s2cl`%EQD?!P6`dG$ub3%X?j$z#E=N+gcJg%g<1*paGV6gYoEj|4hPvV~=j{y)na zlxP_fWWpTg4e(t#qnYr})|mKG)iAEAs#-CJ1rv+S+GRa=Gl8%0(7@LMBS+~_tocr` zXD#Q;GUM&+dM;^bVi_we9$hNE=3{s$(A&z}P_GG_Qxj-aV6ed=McP9Pd*0?}U2~}q zYsz+A;9`sIk+-1H%{sS*8W%-1YBlWy#0!4+1lpVuTd{LUA@cCKW{sE^m`I(_=VPYz zl;S%5F z9elF53#A=BK;mZ#Z7{jUwQ?0*l+C&UPT@44_(OvCxT?!{xktE1x`%({)_QeaUmdC+ zH?GnUJvgJ?Mesh7yg^(z+i>>>q6`eIjQ@td$!LFcALk}xSI7Ee`?$D|%XKLoN@Jm9 zh0;VQ-3X=I`?zxmZ4?Q{_>PgDFvmQj7ch(>2TKVzAn`fMu(3%FZfOkD^_)TsD+;1TKlU_P$Z!`4=(`vaH)oVfW)%5a6dDw`smJnT#>>C|x>JE7K1b^=UOF|`j4 G5`P14bu7&Q diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseClickedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/MouseClickedEvent.class deleted file mode 100644 index 09a17465116943a0f46fe5a8734c85fd235cc336..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1790 zcma)6OLH4V5dK<{Ek{-q;W!58VZca1vg0g>gohOjv1BJpDd2JxSA`2TT8-l&Vpp{@ zG8KLWSN;PBxR5ebQJgsNqbPbt8(FrAV;y$X)7@Wx{hELN{ryh>HQdW0MYtSCohXR9 z(t8jMv~2WL@Kkm;_GM_Y$Pg|b)jI{DsAa4~Z%4*jMd2gANuVzX=NnO|jR?(-=ndoq zhp|6m`{u^x-AAqVH(T5OSKEI3G28oT)^!MzcT}j%8eyT*`c~`f2&DG> zb)i+TZEx$XP#RC~dLw3iDPzxf%7;c673lgQoqMt9@9|Zw$@Q4VHN2U{0%7shAbGrn zx0$@sz9k|8qxPkX;>drU#XE$h5exh02<78m(^y0~kL!4s>%|or)4P7Plr}PyF~O@; zPbtN5KV8p(P|afr%Y*_WKXhG5=I$DUy?jQdu>voPn}p>vW#T|}9`D&%Dn#M<1`sA( z5eU~$p+DA1LY7D0HjGd@OIvwfo+SMwTsll^tjTQB8x?Zp6dotb$jiv{6Fhw&`pFi| z+G4u3RX;G#C~QCL^R)Bmt`p{hSPCQWt8Q0@FRX0)Zga(tkJoVd6BN&XVQx3>zU=j7 zT+iY&!pf)#!c}`bC@2^2Idp26+Ve|>0;++K2oqimI|=yK=MO%0#amZ zSNO)#_>ryc(_6lAfUAU`u(13W77tJ&tY+pjf1@y;S^5o?1Kdc#vP?VhIp?&Fb7(N= z1~b`23BC(|p9Dy?Dbj#&a#%+AaShJkRNB9^SeB!XF#K$V?3A@9@yyJ;& x{ZC?3xPwm<*Q)CZaPAMRJ*MaQ{1-+ZuT0wk*cPNX3HxnwBDMj<%^^-G_aCPq!l(cM diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseDraggedEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/MouseDraggedEvent$SerializableHelper.class deleted file mode 100644 index fe60182865e24fe4543d23cba5ed3516c8238e50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2317 zcmbtW-&Ye?5dJRtu@Dxe*dV9~RHX@mTWS4Ku(T3TmIi1AgHT$#Np8Yo*rl6|ihold z+86NDb9(yRXa5;rdivc>vZR6>+vc3yJ3Dvo%zQK7PV(npzx@ti0^1te1jao#?-tym zG#1@jRnB@=xh#uwPo?8uUXh+{RqPj5z9Q#kWmkF{q5|F9)>F%lyN+QVbtVwMV>`A#Ef7hia{|!}^GG0qP8}NB1x{yeM=sTN^3q#X zNeJ|0-GWugSxk)24Q15dva13{HjMo~Sf&`iYQK=nC4sxC?8)gr$T#zs-cN1;LkjOM@sRDj_Xaux>9_q<1?j*(ZZZnnwvUqDUGVkqFb~}w)CoV&(+cAIwnD?X*^on zl67DU3fLDaQF8wsi7u!&BAyRgCXhT9468)q2wXUU`HUT@dIf>=C-g|5vnX3w_VE9+ ztU-yEF+nEGV?hJol`{bo{@EHGU#l9%RaI3h=CP<_sady#7t1`jlRD=>1D4uzU$ z`+LTURgxKZXV-N|LmewvW%1}z=>tB7hXTE=ybbjMVRLE%tqBY^SfogMXkjjx{A>hV z>chIS-4M9gVteE*XmqpAZK1|RA*7vvc+T&hK$~4;D|QYkL>@j1SR)n$CQ>K#`Iu=v zrMOOi3|4<%@7ZdG_8ysz*Hk+MbklL9m#J9Qs^mQFX^y8n4La9&pj<;2WxZ~IQ#j2h{*d4UuIln#?h)>h?%|)gwO-u_t`60Y z8&_$F9-Il>Mere#yg^(z+i>?9Q3eK9$NxazWVAoJk8_i;t7HAKeO%nf<+_v(rLj;l zLTMtDZiLe9ecU;OHi`se{J=<$nWM$%c?_e#!BWHxNPLMBOq9vNtpLMxJ*N=EYKUQ# zwqFqgGY-&1Xt~6q%n(Nx?jwU)R$E{W_ZkS_&`T%nO{RW-S}ixD!5RzJc(7{0+Rin5 ztK${=)?Z<8{Uw%@T5m_PJsC^JlhMe)0UjRU(JypXFZ)E$wAE()R>^pq^beDQcw;vglC5E%m%y|VSI;8Hm{Snzo!(X_uDMtCZnC@f0D

R;ij|APs&@)PQOj6~?zW7zio$1pgFs&p&aXwGHX=0JqT82a z9LD~L?HlVG_n$ReUv6&sPqzHlbGG->tZNg-@2OCk6~bJl`IXogp7_>y(h?X@av|&0 zZ9-;^dFGJD8+n{ZfpDRzLixD=Ogmtb}*Czlzsr!?Ve^Jp%kxz?G7 zj{0%H7*|fA!4Y<)X~-SX@0!h6MX@q33F%7JCrosd?g92&DG> zRiRa|WpC@vP#RC~ctd7ADPzxf%BMyc73lgQod>b#?eSHu!S$HLHN2h09AW|HM(s-%#gTuJ#e0N>Aq)HG2<78mlbA<2kL$R>_2P<*=v}{>N*fu>!RTZF|kW#T|}9=Gi*6{2u-0|;ZT z2!!jW&>!g}AF1hlN}^g~!P<@-p)L1YbWAy<`if zZ86>2s_&R*6t-UWc-nb%R|zvgEQOH|Ri`7v*H*TDce&!n$7`_s35w^xHn$u1Pt2W4U{W@eeFtVvxZSdIL&*CfkL6ld zXf3%@QzwbweV#!3Hl=VGV;E;C>!b;mbC?{;dDe27QQ+?dwpd}06rbY@i?2}p+4)TI zH|K6^Z2bW)vOF`e!Za?i#P)piCSw%w7G@KyB|eFD>05j{%jJx=dv8FkXkMJ=v_{3pTiH~K}6LyD*-9Db! y=D#F1fqVEgajm+p0Ox+g%5!>!&wpa%(aN+OfNepFld#_gCt@2w+#KSBa{mC3SHhzJ diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseEnteredEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/MouseEnteredEvent$SerializableHelper.class deleted file mode 100644 index 353a7c6e95f0bb1e5c38cc354ff374cd107d2ae0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2317 zcmbtW-&Y$|5dJRtu@IIPsiDx80=C73Lf4}GAyl-av@8bDLPJ5cZju{V8g_Aa)0X~C zKIjYd*mFES`|LmCi^uP7k|h?(shV?g@9f;UGxN=SJIU{V{qie-32bX<6Bzg0qFZvy z(pYe7zMORe>B;i!GwB4Em!)T0Rr{q?tjalA-Ibn(xIp)|^~^G=ma}Or6}M$6(2x|k z?#RIKD@NqcZ{7}U*D=ha&IFQoY{w3!1!9?OK_H%E9x24osY64%!0Ej0$i>=DQF<#X z34xxxTe7MJi;3~Mp^OJxwl84hquB3)Ws32A`=wl}2;9x&Pfq_~v6;X0rt)tVU@B`0 zq?&-GCouMJ{4o(XETqDB#J504wnIX?Y@hJJx_Z?9hpeK@b< z0tN(5ZOUNTt$8IG(nMe&ldY$1Jr4}2sM8>m5~ora#IS}Tf&LKNaYi~mz$F5u=b2g% zxK2n3GleVoP{WA8=)1Q^M=vrAmZ|6T26!`DPzjCdxT+#{F=DQ2m!9U_niHs#aUIvx zNt`E-mEt2E*PDtprTAFKCrXi^g?UeDZtA$DG^#QSZrQHb((`9usH0DHOoCL?c(l4D z>%is}u+LPYM~< zL5Y?zK_<*$UIX8iGa(cH*%}>Rsv0I$RaGnIu%KhHS-ZUJY^LxP9%}enVB{zrN;S_8 z_Kan#B6IG}uIrF{I+n4*;?bqjhjfh&1$tX~8|g#B7Sse<6&P%=NRjr?!kjnxSr56? zhc#upE^x8M_Q+e%=w_YULXC@3L^}cTg5N!XHoMGL>>N^vJbWIqM$8LLWKQVwG1GcV zah?7ctp2{VDudatzhw8_T zt29Ip&V=q_cpqurATFG3xcdWf1_oBfe?#A7yg$B=bCZdyWBrMJT-?Xyx|EHiu}Cr^ zX(EztMAGej+&P3ciWFmf$4F0@qs8b&45P%sQpOEPe2xlCY?6apA%^LCP7#Kc2*V0( zzaR!?9HNQQa*;)uA&xFQKo0j1_8Nn0udtNXdOOnX=|no2j>iTL@aO=Kf1i3goWK8$+Dzgk;U!k2KD7e8Ln_wWmBY+hn;C9ojPt~C)B#hPJn4DruM-` F>TkcMEnNTr diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseEnteredEvent.class b/代码/robocode/robocode.api/target/classes/robocode/MouseEnteredEvent.class deleted file mode 100644 index 73f706c2af4b2094c833ed2b14e8e3f10083829f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1790 zcma)6OLH4V5dK<{Ek{-q;W!58;ee5XWXD+|5*}7?5?gk%l#;j{#Z}=#jaK7$KaeiTK|Xd??5jCI&iPj`R)^=tn8>zCgE)bJpS6yahVwWA>F zNbgb9*K#v7GM1gq0~wkuGKBMEdaEE5wTzYM?#fuJD17EO2=p1@>_!x7BSNz)x_vpp zVeF6CzOlJ=|5>y3#rBT>WXEqkXL~=*x;A0*jtZ4oBP>*!Uy1|aiEoT2ZJdOX{adf@ z5;7aiGlw+Z$m1*ugmX<5%E$e$+cIv6c2^Q+no+>K1hZo~xy+b-r3sgtW4VmvT4x?Q z>c;_NTsnaUM|dGkL+*)w*KEfsij{duNLQ*pVXC8aPnckz(5@T>vr&z*!S+NTwdb!3 zt%4nUTW^NaczVwpGV4hhd%jaXHNvPs*N^Bth(&LouWAjh$26|sY8DHG#s3G%<88dd zlbH&HUYq0zYis!#Jw;T6Rc6&0e zXK|OXGHk+VVO`Nn$9-~G!+pEg%%(Q7J*V+?uS0GyDO<|E19QjRZrHgY zmfWeC<3wriXH#wOnQt_R^^7)88=`2=f)PhwrV*#3c!6fBUX0<1ca{6L+66q(v3 zzOgjEV{7~LmaiY;GU0nHEdP$hLzD=snfc5gD9mS;en#aG*Hf@8(++&jIj!RiHW+l1 znQWm1-vzrh030$dbB$__K$&y8A+)@C!bNm8WIc%VCbwP$@AjM}&IrbgJq*>x#zN~*#n$)PV2QtohFz3VVN}i0 z3T)*%KNIJv^Tc8_WTwW|=zpToKlp(CmUA}vZRJWG=;)$`J+!#DIb(C(V#N1yRsJ{F i#!jK>awVRX`|q${`Jh3`DKmhR%a}7lAwz6dvD$wSv~pnp diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseExitedEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/MouseExitedEvent$SerializableHelper.class deleted file mode 100644 index d4cd81bc2663c65c089c551e82619227fda8d7ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2311 zcmbtWT~`}b6y2A641}RYYA9GKU|UQmFc$5HP|=doGMIuE8VaIylH9=1FoQFb7W$if z&=+vowOl^??4R+)<-U_-hqJ9aQ55X)o>0`VNvNFjz!9U9sN&gX4MF4lI6(pynU z2=wILl2t8OOpMPBWjxrjeSwL56#EUJOf$T1zmiK8fqR+!KWG2A*i2t~)A{50r?aL& zs)<*6Eb71U$3)z)jtbrh-vS+xXMw_h$kef2V|G7~v$aa)^z;iF`UU#WEME$JxTND< z3<#Xtl)NRQ}!>9iOWbCRI^YC+6`;$6~W|dDq!Y;R`(0@TI`WNj8*fo*nEP z%T`6^+?`$5A@y`DV}-S&OQjFl8XXGsw$e7zhkPxl@v|y0*dUSO?2(1JVDhsbQmGGX z%647ga*OSWm!Q$iI<Z43(?sqO8{qa1Q7B#NQCS#Z_It$34b9);;_^x7Mrc;nkt~apNit z(Sr-2yBOX^nm5=?Tx_`e9dQN*R>prt-&DLmet>tT64%H269>3_fU9*W8%bl4WJJ0~+{8#u(1Lp=R~&gx~K4Ey$+0jmtL!yY+==3)T5xPtGH zg^zIrm_dyR229Ei;Z?$Nm=QcPf@e11B?#jyY_NHqy!|z$IKAIt2{#z+BL9s%qm*Q% zF?>r&W4sX-c7r6#l6plJx1$@>mm6ic#$A<7kxm|Urj>N+xQ(4q>n1w^rm2|P2OFus E01o;p{{R30 diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseExitedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/MouseExitedEvent.class deleted file mode 100644 index 280798ddc275a78131a5ca26c04c8c42b2912aad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1784 zcma)6-*Zz%6#h<2K0Zw80~HbGYeTj4ORX@C zDCmS9L(HGRf)hNFx+?cYr=@p76@*GZAtZ|>moU~;QCn#5fY2!RbD5-C`C5ki!jqBX zZiq;EyXLe~^QCs8eWypPEoJDq)_7kFt-Pqxr*kV5?E^k4SGgVIxQGwaSRgF^KS&lI z;bSJRBG(WRo>qs_X0hbIPvaB9QjdlC^B>B?QR7%dA&X1+l>5aU8L(UF)KsLUFGGS; zES=Db;kc-h0il$|5|#;*jC|it#exzpGT6H%GLBU^Xm3aeZhNCVU%@DG#&yw71 zi71jhrm5pJaD~-po}~od#|TDwm$thx-e)l0+h^IzJ;o$|&$7olM}nUV$GE^fDq8{tuIZ|+r+{ntg0ZH#j_ddmDSTzIDbLFqDlxl$Vdde% ycHUCh7;fO}IJ9J^0-Sk?^@sEV-~PeKgPo~c05gIF7h%3tF2oFgcsRrbWnKfs$iUqI diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseMovedEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/MouseMovedEvent$SerializableHelper.class deleted file mode 100644 index 0bb44367031a0dd4ff08e03f6f0c4d597c566b49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2305 zcmbtWTUQ%Z6#fpm41}S@wxOYw0=C73OVgsg2o)_UErS8H&`=PqxtzezFoT&1E&WYC z=nJ^)S}vb`_Rsj@@;fKV5V_P_*2+11_St9e{q6nDPJaF4r=J0gW6MCBz)00CxJ9=l z)AMf4lk@JbEY0jn$G^5Dt9HI(zs?sba#mJ$WYs`epnEI7n@?Br&PIB%uqBJWfvCVO zNBU{6oDRHs&D*~1I%(^;GlA%R+p+yAflxA)69{LRMGPTynlR8Va5if@a-p_ekkw_C zguuD1Tg+E-c_zl^hBEAL+Md8zHi-TANG2KGvtP@_vcQ96_U*|(DKxW})yeEp_>(D1 zAl8H{s{*6{#vc=Lbr}`9W4;AC0?z`u|B$I;yXomYUryJ`<&)FT8R!*AoL0RU61Z&Q zUGxc@*^vH{TdNkOriegaGF4AH|I$xOMVmT}^zmd2{TMVbAkeFkon&OQx%M=nyN<3V&23;vvOJ2*@)qDJTdTvz|e6r6l+!6 z-%Bs$%QE9`@3;<0XkrP=EFE1cy=G%@DA3c&+CZ=Anp3l9MWDaIAw}6k3v15eXH7FH zfmLO@CUB+2_Sien=w+SRLXC=IKso{Oir+nfHoL@DY#$PcEPSasBjyBdCQt412~&Df z@tocms{XD%veoRoaAYdpP^}O!Eyt17OeODml2i0tbJQJ9eGJfBh~Ef*HX>+K!=L7F>RhJ)d4{;B54}Qn3_3E0wI#54u zT%{q-;k6gRR8HhP&SoW?*1>>=z^^!oA^rT$+fCjP^$Mab+LZ>QX9@Mgu7w zNaKNYJCN?}suMxdQ^=jy~oon`P z#~UP8-=Kf>M=ZvTo{o5XJQ9z_!=b(dJUzg(@9C^w_Ho^}7YtZoh;8=BAv70#*uhnN zixfPJ!N(M8Oweaio`zS}<*)*HRshdxz>5&Zmsn@>I(hpmN@04x#}ckH+C}~kc}^+H zNTc|MlEHXGEbKZ-mLl~EEN(|Ps4q3jaGkp`W`^)Nva-q1Fv{0!&jeH31v3 FKLOveD2V_7 diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseMovedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/MouseMovedEvent.class deleted file mode 100644 index b7bdb5863cd41b488456e26e3d7d32b77b660807..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1778 zcma)6QFBv86#h<{~WhqASKC_|G)hH(D4)for{En_9xdotE43Lp730)0t1yAg%jh|uhbc2|z^ zCH6<`U)$We_o&`@y0hzlz3Vp~v%jBaTaz$;SB1)~5$4PFZ^WVS#P`ONmOzh?yRur@ zBV;z1We#b)mB(335zf_BD8K4{*OYNXG~1FeU5^6hC72!Wlf#TTP?~V5ems{!rd4L4 zqi!59!sSy)F#a=XYI0w6+h!+LQLM~!Lb_b>2@@@)JHiA9gl2hgmA%ub(8zdS1X6qc zy3i`vwWrm3D2=E0y*{swl(FYK<3l5i3UqZq=YA|Y2Yj?r<7!Oe3f|3Pp0MzGkUZYQ z`%GSG-x3jlQHRpq;>bVA;se5BpN0K%jPhvIBo`tw^(nf|dCV1t_ zDWw>V)72aZl{^-)M3`dahfbBG>#i`^|98kFmf>Y_ov`#qnK)3L#|_&_`6wK8KVi(3 zfN=E`@fw%eZ_BkCR2@LFDcUzTFm`WCCVv zDc#7bADCwpHlBC5*ST@m39~^gg^>?bt0lu%URJ!@T<_85>J5H^;`y)K?X*3R?T(DA zS$sY$!Jw?J;Kh>>IjrHHooMEAV`y?-AL(9&T(3vAl%4;Xk)Z3gUszs03#}z< zG<}i;KH|=^FH#DZFotp7W!-Lq_c=`V_j$H*ficD3bL_Fk5h-5B7nfe5@WRDR^Ec;C zSJ?X|&hvh@=Y<(u;2rz($=i%kz(vd@Sj)T;+tP*R&%C5yfh-kZ)q&)D<^-g`)GqUh zrST(s+XuIF?FjD>e!~3HpIA6Tk+7PX%lw6@xy<6PC?DZk3YKNsfzP_2b)3NlgKjdD zEfnFq%Wm}m`;1FmqZLP>#5vt^`IK-QA2Zer=kWq1?Y+-o9u6 diff --git a/代码/robocode/robocode.api/target/classes/robocode/MousePressedEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/MousePressedEvent$SerializableHelper.class deleted file mode 100644 index aa2d5047aa52d2fd6a8af622d6a8258312e861c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2317 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 BWtji~ diff --git a/代码/robocode/robocode.api/target/classes/robocode/MouseWheelMovedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/MouseWheelMovedEvent.class deleted file mode 100644 index a643d718c56f0872cae30e0e9c544d630fcffdb8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1885 zcma)6-&0dZ6#h;UxELY^L|SUmid1f(colzCiM53UZmgvpZd^0%JJ+bCJ-ov8SZBHob#P;&-u>&`|kDM02cAkL5eUHN3|%3 z>eAbYT8aFASIWjlv?uGUdot7xGK8}SU95qSPh_k_V_U|Fio(Z!nLrN-r%O?oXc6jd z(P+s5&Sd_G{mZLs%a1G7A2+xB@3#Ev6ZZGhY^xCl@2ODf`-BT_OHIaAQEN!TSS1RWmtc0h?;K|Iu1W|OD+lk= zcikdWNupL9FwFU5m~fJ(QkUh9Xf^a^tfE-yXN0s{@Cie8l{AG8b_q4Nm(L{DD%3LG z5rIrRe?=rJ*fOWZN+`9L?08*rO(|o~x5h_WXcZ*I9-RlVXzudSVwp=aj451naDg!W z{~$ShhD%IdCB7jd0&0@*_;NUW0uFJywI6%2SY8cb_Jclco<$7^N_StRADk{-3 zlrh0`3&)hAKQ1X|K`7)fhk3#XBR{fT=}2#i!Twt&4i;EQN7-$+EygfBTz7DdFn^-k z+Mp!IQ*(nb8ijqcLb!aiaC;f8dIxMp30ID(#XeaO93CapeZtI1G{WM0+7SogT(3s^ z6vHl!ZdVqL;c>VpJlrhC;O7m|>`c|T>5P2_)Njl)3aihWJUToFD};$4mO{&QRj3iw+p`TDMz$9k30WIUJV7GRo$uST%Wj*F9ml z?OL`izBOfDm&v0duNt)xa(>8SFEvDxNN(BKVLG_Zx;Bqq3ZGyAgS>O>Zix3;40rcA zwsO5O!rwFOai1enybjLIzeN6pjTz%_)}Ai1_YIuo{Y2Xf<2c7V_UDt27$c95G1v#;ZwqMT$+E2=~tK`EM+D$ z|6p`7GxrzVw_t~>DHx(@i$7uGR&WX>#$9DHYnX*^^WAJ?c1gRqiCdO~i`)3pUdhEB z+-0nBj#xqw8QinjG|S6ZT%R_<-ra8Z-)-}VyA9!MeA5Xn*v0^--eCC&y+r9xM&4hX Yss%7zNHKZyeSmdd&0Dq1|30$s0aLu>tpET3 diff --git a/代码/robocode/robocode.api/target/classes/robocode/MoveCompleteCondition.class b/代码/robocode/robocode.api/target/classes/robocode/MoveCompleteCondition.class deleted file mode 100644 index 8be7acb97d4055adb9aa9e29fa384cb2560ca543..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 826 zcmZ{i&u-H|5XQfW9lJHoA3_PxhBkp7+8|nlH~~UJ36(0P99k5q+&0dtY)S0M*+k+= zka&h(kSItTcmN&>F}tx`kkW&9cV=gPGv9cB|M~d~z*B7dC=fQ&WROJ3Q0^ZkbJ?d#!O#E~2xo0}H|@1=^Benr^Wxh`n8PjEY2 zK7fN8A$)`cXJ@y+3PL$V5gwt^Q?YzI8xLgqP7FqpJL)Bo81+S}jGZ}M{XtC$&8u2V zC2?boYx_A|RK6Xejyr^vNve`m=}!bYeSi(z_t7BKm+KF)i7mp~nbci1 z)n+iqax8cv@tH+*38fP)qK`*nk}2?`kreT4LI_ThSsKX$Wz?=O)v8X*s--!5L-d%~*aSTBG6f}(rjTrk_Q0z8fco?CWk&()0Gv@uj>XA9=a%;K3X0C;WsZw`Ug+~sE8 P{Dbl`6yX8q7Vz*doyVB< diff --git a/代码/robocode/robocode.api/target/classes/robocode/PaintEvent.class b/代码/robocode/robocode.api/target/classes/robocode/PaintEvent.class deleted file mode 100644 index fdc78c88894efdb6c848a6d2b7020643075cc84e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1417 zcma)6$!-%t5PfYsaj+c{vXOO$4nUM*iy?n~(Rh zyRWvkGcUF?yZhvy3DQ{;L-Vq9hlAc$)*wBjm5TUOfQdG&2xxVt=G z77QI(r$EU$Q6Ssj45>ruF?45ZTRXAkG zC+p!FN0AJ|E%Ji!tjsF+WMNzHrn9zCmRGcDxhg`qR>mCeD6V9|OJ`s6BX03`%6j7R z${}q{ucuSFC6u~-zM=gxj6sH>T7JDaN4D-CMI3ix7{V~A zLn_o|$x2TNTeu9VWa@&#>k(c$iczG(NHPpxlH9b47sD9F8N!ZjP#AiX{}6_u$yC8G zasiiyOCVHgHmx-&@jo|0S6%Y2LO06a?uT5;HC0A0;L)fFH9lQ>;mtE%@td)Wblx!| zBHt53$KE}zP~%dEuZFQeJ#BKAxm~h0T-R}1u*5KaE+Xy}IfFgcH)lUA`aCv>5ktakL^x(_hn z0|Z(=(MbS0TBipl8zKX>$X@jMksrug|5Oqar|4(+h=K7Rh@T?CuoUVG{Y11cGYOb`dnB!MYdrlJJyl2k$RX{G<<4AnPl qu-PDe<_Ppmm05DpfswD6-|tvFLHavcjm51s6c_PRGOQS{hkpP8UQn9= diff --git a/代码/robocode/robocode.api/target/classes/robocode/RadarTurnCompleteCondition.class b/代码/robocode/robocode.api/target/classes/robocode/RadarTurnCompleteCondition.class deleted file mode 100644 index 4cbb1106ab7f192ac76240ffa704e80f71057441..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 842 zcmZ{i-EPxB5QWd!j@=sPhd{$m14&wt+8|nlxB`TPQYuvnT%=W`_HJXZ%0gmC?xqq? zg4Ac|O(hBv7d!wDg&1!v7X-QRdUtl_n={A$`Rn@+08jD2gGE?RlTi{Tk=!1LNTdg| zH0~vn=~!ynOX5grmBbz#LcK^V;)GHb)P&pp;`ViPD&kN^gY4!7!F{P>rC$+NHx?yr z4hc?=HTbY`Er5rBU~g;=mqDlmD8VIE`zn_2W|NUj55#CJSy4X;#ds)Em7VjTqu;9& z!o#axi|1l>&4r@&=IvJkG;oWsG)+~KD*cH-dn{MW6P}wz9{E_sJr7Mnc;Q%zcs3>Y`^hW~<*v$RZWV-ozS7nQaVpSZ z%WVF>1S|86cMk78Eb+R`r(KR){Pw%w_<3}R@&%tPRC%qK$`)6&Ik$rv#~Sl&Tt}Tx zTxY0k0yA&q%tOw}dR7Z&w|R-1SKvA$fycaVF?gFBJu&e1ysUs%b2y_i*BQ&d7VhM2 zdS(=$*8PI=SKO_9K10blx6hevn*m(T1fCmqVD`0~-8MN?;a~^ZRp!Mr(*SV0^p_95 UnR$oBy!iv=<|x7%*IHQr4aJzBVE_OC diff --git a/代码/robocode/robocode.api/target/classes/robocode/RateControlRobot.class b/代码/robocode/robocode.api/target/classes/robocode/RateControlRobot.class deleted file mode 100644 index 8e26ecd2dfe92af5fdc0d693647323aa50f04be2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2212 zcmZvc&r=jf6vw~4zjqlRY!(7pHJBJ-S7i(slM09e8#NJ(g%p)sw3=nIOk8(T<1B@z z+~dWZ!olLo(XxaEt!SyadCH%XgI-g4ZvvZycS){P zsZ4g>Da-1zbZwpo#+bKe-xJ8sE6(sXCMnlF%UfFZ5E|stganZiI zD0C^P2z|^&o6RanpIh=mzZ> zJ8K}#)p8Wv;Xr3{Se(k5KP*VCCan#tT=%FW1kM}y3ON#;@-4`X=0PTY`V}3q3b}1S7mR$w|mxHZ^ zoURzS%1$3Po!Zu;_};)dZsYEo9#vkDzXtu9x#`s1vUSKOMGjuS+bHWovK zo0I-UxQG0aj@KVacp5(-Pr5DiHE3qiC}@lq_t5>sck88Z!Z%KkGsw+%Kp(O+BYfoO z%fZuBl8YvaBfIEtMQ5luaEm~0`xyrOc_PTb*%^@we}usxmq|VcAUo)POyLoMq#pl6V@WHPv@a90e5zQ+1C~^A2gCdLER3_I;iQxEV?dyWXv+6Sae;6!yx}?AaMmUszAcJ6vDc^BVFEWEV?e-Hq3HLvFN%K zI&~2d4X35cX@%3KOPEERL|lw$EV?dDmNSY)*QF5BMV!+>TDpuWkgzUhNEh)VQsO6# zMc0L|5$p1WV$pRm57Fgk4X35cxWZ}ErGw>n(&d51qU+LRnNTdcE@oJlO%0@_3q3lt z9lp>{=>6bJc%w+2-`~KOJoNmzh3;YwUpMg0HuAn{^HI}uVH>Gp4=r&>p@B<0nhnhH zINZQxdRV?=d87V)9_KpZDapHoKCz2I(ZC6@hf`u7W8xVm#9x>cFEA%w;+lAcAH-{o V`9{#=*C<~c(R`M1=V=nb!v82|W844$ diff --git a/代码/robocode/robocode.api/target/classes/robocode/Robocode.class b/代码/robocode/robocode.api/target/classes/robocode/Robocode.class deleted file mode 100644 index d7ab53d66c6213cab29aad81d12a4b045637e489..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 461 zcmZutO-lk%6g^i*C#NyL%8c5y2((2HYH0)!M2o2)!%eF<&zC*X8F(`W{j63+i+(^q zD!OBuL~YKwU*~>(e7?N{IK-BV9HD08FjnzEi<`OO!XZ>g@==PhjE3Sm9BGvjipM50 z=?Njjy0hk#7d6)(wfYl2c7i6B!ourXKv&eE%46>g4c_uR_Sw-?O$HJ80_HM%C9I*skxYEV{4IV(bt(3E2CxkWJHHxipviH8|PSJ}XI0chiVLU{pmPE(nbHJc2YOmvc*&ZLTy9ie_z7 zFIK#I97C^c=`~C4{g)AU->M5-S$d(cEIuN|5g2H%TwttSi@Rpss99ClsZo^}!bnQ4 zlhi*oy`|tvu#M)4VqQbtmQ204DsVr~j=B^+sVC3sckPg#ill4Zm z>eO7bl#O8uqXN-#X|?!R;9^@1rx$Zl+qC4Hp~lbAc4vC4k0G-v6!a?41TwbiYW1?# zQm}3sjhf|tr4=^!SwLx7xAi@rIc6Bz+3s&(a-l9Qh zhP-o7b!^k7eXj;d&4pw6K(mEhHgtuie}PoR4S8kWN}l)EwHmA zhE&>=BD+$_<}3+l!DRjr?D*+8UNST|VmT?zyDFmS;i%}Go)9cV61~9zIgBf>qX26bS9kGnhw(Li2D-9&XBSOu5XE0#_B& z=FFu0fRAMWm56OPjhbOf>DZyOY@Lu31i&x3dS)(APIb#PYJik^zzm~ z`WP=i!_=e1E5~^C555Uv-Xwur0nC9G<^Wzp%E!FGJMCoe_~=SH6F$atC)EX3ycmF0 zTCj?zLX&Ey3-(9SiIC!~B%RJY!Av6iE3W;C?8@w4==aLFAo^d7=$L{7Zm{ z0-+$!UzRTir3t&(-|*xDdegsP?g)#Wsu)aF@<^zRWSmc8P#X9}X!kqOY@#{OMO((O zZvxF{6eXjXpO~`Q`yMa-Vc>GKMTK+HMdj3*ER614>*Vq^Yx%~5>$c`PHkfWu&R7@l zL%-i~saR%w;s_5qp}(d3zw@A*or||R7iWhhH0aHT?67ouoL$~#=VZE_u5@j6j2&UO VGuij7rh+|VFZiU1J=g1e1bU{PXQ8wc@Py@~`< zAD|C~n6(WAVT3Q%yEC)j{PWxYAMgJG_>OfO7GX;JHQ)6wWa%i`?5Vmu)hd+QMusqX zBW^`W`K5za7_`D_sHJGcc|y-G<*9IoFtk>At~2+y*G~ve`OcL=sC=(!qmMB1T=D1N zB}2&Ua&sG5!hEWf&bAKvk;|eRJr24sXm&${iPzqp#gT@5MR{_+)u>5*ENXR07_RuP zsGkU}%sB~W!fVwe6f3C`;%T>8>m|=d$i1DFO?*{grvELQu2wiPa35Kf^~U8 zD7?AdQA-$2ICbG&mDp+JT_uEBLnsn@je>pAhz5!L?5rh>r4Y_z5laTKz~4*+f%I4i zo%1)U`Yr8Bqna@O{ukIXJunYqzs-~39or8Jc5>>4!@DwPEPfAseL(-&MjHcdCM)HZj8IvA7stFv=&s#*uMG8+d`&ROCbo@&_Y-et?|9bb>5$yHE7aq`=Dz z-}?YQ7nx%8F1&*ua@5$Bi_MsBV=;wZ<*AP&`dnQ7;zkZJoe5aR3iAo8%(Jle1g9Fh AP5=M^ diff --git a/代码/robocode/robocode.api/target/classes/robocode/Robot.class b/代码/robocode/robocode.api/target/classes/robocode/Robot.class deleted file mode 100644 index c776141c36aa521c383b7fd6ee6b55d21ed8eb99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11677 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 diff --git a/代码/robocode/robocode.api/target/classes/robocode/RobotDeathEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/RobotDeathEvent$SerializableHelper.class deleted file mode 100644 index 39ce28db009905e6527f657c22770cb5dfb5a761..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1685 zcmbtUYfscb6g{(Bc44XPLr}m6DxlkaP(XZ9VTUBtH`@FuZ@=YE8WKZpN8i`gwr*{ytHus*dTFE><}B{1ZcB~O+)lJ- z+Ll^73C57RZ(64JfFW5_8Vu4hsmLISK^bZEGi2+g#aH%r4emS>A{YvFyQ#MuItinB zxF~tsrpr*RN8G>9L?d?BJm9M>hKI%auf?w!9rfJN>c`X9lv)~R8Af~2XHdY1jB_~8 z(62X}+;yjB8D@$-1#3!-W!-a3YfH;u3>VTEXDI!-S{XT9WEd%)#8YYvnT|=^VW|8~ z6{vi+Z@%#4L`BF^`pYohJ41$nh@7GE4;EOatuDRu_|jghb-FJNQM2nZCUJwR7S^D5 zSXgLr6jO!|N|g(eI~K$+xXEMkpZ~x7xZ^=v`Hoj*%s^$x$M^!B49e*l#gU@3Q^1^P zs`(ygL3E#`@A@6qbu)}+nC*R3Pq`&Dg$hq4qVu(G?>SBW#1y?de5@;H1QCN=vn=i` zw{_R$)WwBPt95T3Tp_e1J$-a-^&ufH2bvAgOr?>D)zT3%AL%0jncgXX@iorSw;XK1 z5VAC*>kD~$i{MuTD$$s$d_!SHDpx;Y_zq)ZUtgYQ~ zQF-L|@Bk91Do8x?z;8l`GvkdDIZjhc_Uz8wd*1~i1PU2k#0%41Tr+RZi9%@HPs80E46A1%r*PI_KsA` z3q4-D=KEbOH5KHog;QWBKD;qUz?#~Z{f^!ayl&v>r#8a6K&tJ9J*nM8fxY4hYb&Vd zYZdHESA|afz6?FrlBzU(rJZo!F*Y{eJ*5JtZVz`188@s9n8+Wr^B|DDLvF3qDy7yG zZlIXNqQLyn+dSy;S7lH_nMoskd%rE6h8Jq(t3aSc`7VI59${q)?_oKKn*s|j<&c4c zTTDdPZyI*CmIdBCCD6&fy@Ig`Oc-n}aN{CY*4b17E8WONIbKFoX6qnQlcJ23m?oW} zK8qLeh}2=%F>mho4`nYZ<5?=cWBb$l(N@>)(;iEnO>v)P<_7F-wdu9n%0IR;`MAS; zjMm1W%Oe!0er#@9W>a-~DySs!nZS~fZrt#gKkJdkD%MP!lFP00Q!>WWW+^3IR&+Se z{4SsGT^ZY%>78yraMgxq2Egn{4J@0%!=kDCtj=mjhM{6+b7up<`y4E0bj5KM6S%~; zB;R64@jZ>H;d=%-GktiL;@%9h{C&lYJle*%rpwQeD=+Va*an!vbc`<$n_^$n}3bM(sL{b z+)d0S{>Ic?qWm07F<RHm)260=}fM4=KhL^4PY>w+G%ssR~TiiX~IP2e@s8EZ`14 zBuT^a-(;qJNQ3a?${IQHl7Rgt9mq%GYB;N#Pzoja*AMlfdMkSbZ#>;q%d~ nd}9Gv2-y^>s6}oIT+dD9wPP0svQDBg*3tv6X}YZPyNUGw0e;RB diff --git a/代码/robocode/robocode.api/target/classes/robocode/RobotStatus$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/RobotStatus$SerializableHelper.class deleted file mode 100644 index fc8b594529d64405143bfdcbca58fa2b2cf57e6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3263 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 diff --git a/代码/robocode/robocode.api/target/classes/robocode/RoundEndedEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/RoundEndedEvent$SerializableHelper.class deleted file mode 100644 index d4cf1fcc77717a5553ac345b5149f78dcb386ed5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1678 zcmbu9-A~g{7{;HobsLOMa55Yq!gSM(4GM^;45vUaE?Fc2T;gT7ooUHzP1}*ktuco9 zk*M*%@Ir6EXkxtfk21ce+sXo)pBFt}?fabH`<(Ok`;X6G0nFiM03L?4X_SnzQQ^vl zQP(SLdWBckcDQcGH@T^)HEmZd)%a~*d&JEEB!+=)bw^cds(xQtFKzR(9e|%rt%EIR=V6| z$o!2Sff$aBBD-VS485*0L-8L-b)UO!rgkQ14k`IhjBrn?~I%^IMvz!oef; zH7%|!gPhlOZm!l;%i^?exK%WV{|`)%nwK6Q{eXP%h%%>HFU=I{nOL1XK=30CJdmmN zJBv>cqOsig04LB-Gx`zXB()-VnR+kv-ht42>e@q}I-wJd*UeD+5Mi8hblx3ZpwS`gkQ1~=%+HDK1xD}^alCQ><{N@8 zK*9w`AcaW+pzRzKFU5}|jSM8hnZk4vYL68B^i?dK*@u#I+67{x$%5|-qW8ukQp9(F zOCMYZ!XyE_rm!~z@s{M@IWW0~kP8!YVPZ`fKSr^DE966nqOQ_NqCSLcH1Z9A&TX-Y hm7re0i*w5!deMGv;cyp^tBo57{se)Ij&1+| diff --git a/代码/robocode/robocode.api/target/classes/robocode/RoundEndedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/RoundEndedEvent.class deleted file mode 100644 index bbcec8dedfcf4c7ac813351b53a002f978d0ec0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2449 zcma)7TTdHD6#m9G*w_m=hEOh{S1$IFuw0U+jcL+w3!6GX!MKH1t(NrwOUu!GVc7Q$ zJ=-gDW5=txVT^fgY^9z#0dzGGEN+z%Yj-7{Ai*kgv?70(TX<%*J3 zsqrrIFF%azSJ&1b?iGsPZts{|J7#g8?9C{hxeQ&tj7X!X`EJ0F6rQju#rmRq$#ETV zpP@Tznr5!V5L+RZNklQIA&u({(QK~N1BSOW^dco^BO3bZvoQ_*NHO#m9G7p_&JMX> zv<@qrAye>dx`0L3pmn$z6DJNa7%epJ+m?+yL*keVwW}hV^^K5iFP#-z*k@?H%8#sC zMQr5Aj3C9ldg;VRPWmw+}Y`ki$$II>ST*Ehn!DrQs%SF?o;_}Gt4x~r!C$Ga3k>LE=NQs&oMTuYKga0rv>(9@`W>QJz#Li5qlf+>`ml%r>b!B<)$4e?jdy58 zo>W|>W-@X_&1CE-#e5g*!rB#>y2Zny7Nj;Rj60oFPYjuOrHN*QI!Ncv~wT|Eq zI)X>r!J8exX-qW0w?f*{wA&6XwLqgG>1&vL6X-V`plM8DnxaXWex~e53G|s)$j-b( zmf>D(B=!npnc0!pbId)*hrgh2B=!$x^_N(RK#CV_5$}j(I)(;^h@H}#f2Jbdu6u2W zr{hyRR9V-tj1?uGj#aFYFO3lEctn0Sly8=!Ix_J%qIk`1aZ@djFFHal)!Fm~gy?>$Nblo-#w1bOqVHEo{ttlP`0@Y% diff --git a/代码/robocode/robocode.api/target/classes/robocode/Rules.class b/代码/robocode/robocode.api/target/classes/robocode/Rules.class deleted file mode 100644 index 147e220e592260ac35e739f85a73e9d8bcc2a242..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1810 zcmZ8gO>Y}j6ulEC6WbZbP8pJ>l&Vz4a-h_0S}3KV{*GhtN3h3E3kdUUkKCyzGnF$g zuw%myfDHm6*6a}Kf`9~6ERk5lz8jWEY!TwTXM6nOx3J&+IOm>w-<{w7`|)QY+NSrH zX+fdYq1$o0ZqH2CN49yiOp6M|?z4w1X)~vvtaa|2T~8q`lgky#g?h#))v5|9d4(c5 z*E#Z-fXX@=nE>mse zT52}b^k z&#kkb#hfDm68Wus2(R<9MrTRow;LLrAKz|jbdgjjC|izM9UXSep}{(~snDsi+hul( z4J~d@oa&Cy5~cv%)@X+=f!@1kp-QZLa-D7|w9+>{V>EQ?%)^rWHJ&P0UeIWls|>IX zkimzh?RG8iBh-`-6a8VxeM6%R&yOK|z-)WZ^78DE^~D$}8da$VvP1TvLQ9D}xNv2eqat2QhS04ThQ=WcTiyuCatdd3@Dd%oe`w2`o6{k)9mqH z?rQY*xV+^k6h=aEl;&Tm)ukA8_HoA)D0?1mWO>yo_zdsDK{z``n^)+RkG`Om?|VhI0plK%qySQFuY zUh>D`Pe}F_g`oXKx`a+%LiQed;pePQXO8LeBf75BIdOSKrwiip>UW4Q&};ZTMT_`t zg2TrB6MBX|rCTD(Gq7wE)+GKF_?KSzo?f59`S=L!aELZepcJKHh4}iw!zJB-TrMgC zNjhcY$CMxRzlCG0VNCLsL=vH*=sbjOrX<_Q<|IMDOK4*r|BZwX`uI0}{7rPq@ljr0 zrxiEaUp=PsJk2ACChF7d`!qcan~&_YPH)8rrFiu7uPKrMUp(3$bV~`&7m!B#6B_vi zvw4i=_*HPP3mK=WAzD;1c0S7 zw(ts_Rw3}$>FxF`$1W@#c1DQawrtD$f-sQHZ4k6Y#*x4PPU?suPB>k$Y*F2L*%0oU z1VKnu9MfoT7z~Wx{YlMxZgmKSN)Y>faw&5Bj`d2cv

ymHzNo8$JBOEmqzopqN{V z;Vj|&@cz3|8N#LhMJvl_lQP;AVfg51<*xH-9W!C) zvohi}9dqHyYjSd4$7kWmIXQV#$F1<>bvb!k$LHWP)$6kPe*|2YfJ+kaonrylm|Ggo?TT|BD$u0bQ|CC*Z!02jI><6N=ZZ8Xcc6^pW<1wjh9O74vv(+hHD^f;co8{s7#1G7e~lqHrYXZSF|0| z@_6+rt5ai5clVUO^X@ufwqG9~q5ehLv|MCXjGD9Kn&O@%HTm2jwVjf<3HlOWDDGn0 z=yU|@bE+qy2loj+W`6_xALJ`(5D_W+{C0xh3j8EFJN_DppV){%=P@cL=^;+Bt#=n- z2&egtFD9JfQEs-_sm9NA{tu+8+Qj6~_+THItz>pf+xme&be*N-B3i~ERgt0@95~Kdh<1SGrbqANj6T z2&~z_x*k|J0;{->FAs9RDs!V6-?nQ=(mG!P8yKTUEHjUBgEp~1b#CS-DuuZ&kRXNS zAcbWtV3AW`m@1h8=JdWwM&mTfxa%kLm%q0(k>AI?Di2@X)YKSNV_c01HR^KB*YiWa zBDFc0(K7K&A`{K%>7mzH`!S$1U>@6gCPbt7& z3b2=a>`~UeM|jNiORd~QorzCj3QyRIB7-cxWh>4_8^w2QCAdT*c*>TJ2`=X|Y+)z~ kZa2fv_6k2GC$ild2b71~O@5BRRAUo@pYk+tUxNX^1(CHyV*mgE diff --git a/代码/robocode/robocode.api/target/classes/robocode/ScannedRobotEvent.class b/代码/robocode/robocode.api/target/classes/robocode/ScannedRobotEvent.class deleted file mode 100644 index f34f53d60191034f6cf76a1666ae919ce648de6f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4955 zcmbVQU2q#$75=Uz+p@e$6vuXzG?0YGjwM%B;x?32P05dvTCJM~+c6|?0a|b{l0t7 zch5cNO8@xZ@Ba*73P0;dkHUVpvDm0JmaNiT&2$`VX_n94`5Ttw^&_dUD;U@B6tYdr zwaxm1hxbGcekP|qo3&NZB-XFA@3S>LdFxq^HY=U2{OICFVs{@SJ4>Wj10`74}X zO>iu&kaWy7OJQi{HS>m9s+-PAY0h(PXQiyrXE~O;a+9;ULjS5|F7Z8kiV{Qs)NGHlGj?;1w!1gAA4Fdz)zh|Pd(S8&Ch`jk>58@PS~b(NmT1B``kscu z0Rs==V+s#XbX!xA&sD+hp0OS4;>Oyd<<6Unb!~j3MmcDdJo_(`-m2Xs=S-kpm%4Ou z|AUswFQk#c5wR#YK-r zuUOvMwssVv(sz3KP1z&#ogO&+{(PmFQ`pm)G)uuvhfWOgT_uoufKTWBoe|3E_QnX* ze+Z!cd^ck+Q>A^g8;)nMSqpa4rc7rXr{S3%1BeTZh6L|y4fPTDMI9l-6Zz1jAVzj` zg5GD}G1?af22Kh#+n&<)TLxzgJSBs{qQ18>_M(BO zw=C+9buYSABEilXI3-x4y{ITA0}BSqTLwf68MtEL49mvie!{zC&F^aR(wS%OsveDQV%pbx}6=qLJGrFc}^D)`<6cc^EcO- z9vCK!=h2#LF)L5oOG}p1o+W#5f_o5+hgKQ#SxVLRbVTw6SH4x2$lwWmVHHYZ}`}$iW&(&V76WdBG%| z;ak8cs9o|&+{eSe;d2i@&i`q)z^AzSNgR|}t+_ZvYk6NG+b6cL-6EU8k!)ddBA3kd zs(5I8c0R*)p$JNTOgb1nv#M ztllx;$td`ZSTHMb4ESgi{8lWOcLN_B_PzKZ-`@$5bbRL}A;yAY)PkRfz#ZS8Avob5 zl221M5&1M*39Yb{T@L*smX6ntz!u)INh13&_G@;+oA}FE@VOn?au1cLYrl=9yYNxz z{uoR5><;Osqt^W`mhQP7(mfxg`)4fO3p=E{7^VAHEZwD#O84(ry3g#8ZZ>M&e`4w8 zcSv_RO84Jby3aCbAAAPdVSEpti-z(0v2<5=Xx&Q@>r^t9j+ge}NOe+MDGJWSf=8If zTXmwuwtXIt-`#p1)k87hJ#yXm!MB;2rC_tb+=qGUz`N)@aCh>rQ14<-;U1o!{0kJD zmACIEggT)s>V8T7>LB{mA%3Sn3`31!uNuc;mDkH1YEk-WSZa0+OI)yzwasE3?!hv- z_+!Kegi765!K!ahk*zqB$fl#N91ppY@VT?FSvOib+$OL53NbqQ9D$wBB_DOA65~n=U&C!5n%4sI8ubUFmS)4SoG{*vJK(Z|A?~o;K%q0Te+s);onb@{y$CbK)nC} diff --git a/代码/robocode/robocode.api/target/classes/robocode/SkippedTurnEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/SkippedTurnEvent$SerializableHelper.class deleted file mode 100644 index 3e724c6c019ba25656ead4994d51564b31144bb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1546 zcmbtUT~8B16g{_Fy0Bdf1<@kPhk~}Huz>hQjR_EqkVX>0Ci=E5Q(UOKWOqv<@5TqC ziScjvpf6xFF+TgFjCZ!%7WoS5!_J+VoqNx@XYQS!zrKD4FpXIi5kk&&N>15X6UNG> zwY4SIR%@<(e_Po8$ck_+vuf>_rK)%+s$0TU5hZkOnA@gNHSKj{xwIk5zKR%O$`-!i zRg7jhui@=mj%_R+4n~OGwQS43M^Mt4A|blKG&CrP>rl~7=qy;acvO2)67H%bLFg_x zWwTl|nHaCb&8Yv}@(2@!CiW>($uqoX?TFEZgT8R{g@gI$Gm8YRk*{!B z)W3AvG^Eh4<038*+RbuV zc;3h)VIY0H;`z*yhCvLg7$Rg(uda@BxXfJAbtMjPUy@}KD+P%VdXGHA)x>fV`cEK7 zh_8u#vOf8LSu=;PPD2(s6=Q^+;9CDoM#nfN2Wau&BdtV;*v9%y<2ow?7JDYd8D%TkNU?9UlG-n} V{2jr~V7!IfY-K4BSJ@qCzX6C^b+iBg diff --git a/代码/robocode/robocode.api/target/classes/robocode/SkippedTurnEvent.class b/代码/robocode/robocode.api/target/classes/robocode/SkippedTurnEvent.class deleted file mode 100644 index caeb26aade0984516d06bd8977a5c97b22bc73ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2041 zcma)7U2hvj6g^`*v9aCM4Q^-%w8W%|?YiAIw0zW|;Mz&E!9bL_7UcydyOU;!*|m1p zLFIu5-uVIi2arGlRVfnUiHH8EiaV3_X5$98mh9cR_n!N4?!Duu&z}4ZU>WT+5)8AR zyW?7}EsX7b+3yRxGw__%1K|W|q!^|mwU#jyeBnvn>k7}8u5;gPF|ZAWGfmg=1MUP} z-W!Ms3ZOoW>|3jAjr;A+SDRbr=UZmy0oj{L(%B3-|2QPWMGYIJd*OLV77eu2BCj&s7}Kd!pt^Y(ZqWky3)dOOH=4FKyX_7< zORPzCC!8Nm?wZ;uhP>&}v^IO(_XTx$`uUV;%!od^s*-pe6PTn^nobF1=$u6^I_EL1 zZY0vF>uCyS>9;_qH9{(Uw)z<7s+aym@pp}%q2DR3X(5GGLapI7lFg8Bvc?6>(o?-D zuXJHjyt&Y)K{kwZ6V*RZ{FPo31cNpMHnp4lkwNI@9Nxg2A^0ji6*yV2e;I*(5rZZ} zXaN^r2Kx1>&`WqLjQSJhsQwX3wL{D^{EWFP|6u756^7fX+0?(t&8Dh{xSD{XC#mb1 z(TF{wMxuy)BBY0TxH{6!BX1E+CA@>1x~>v#;ayE)3Gd;3@>L`XKfrCGxvqV)dFspx z7Q@tP^i+f-Qloqv#EMEpp+3Z&5P3{xc@+9X3_7GTgOBiW2(9SW)3E%7#sl^k&EHf8 pu{Qpw9ndTkGBg?YLfB=p`QOg33?XE+uHBi~pl6mK4f=k9?0*RI%u@gW diff --git a/代码/robocode/robocode.api/target/classes/robocode/StatusEvent.class b/代码/robocode/robocode.api/target/classes/robocode/StatusEvent.class deleted file mode 100644 index b410504920647fba070e1952d65ed6dc8714538d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1540 zcma)6TW=Fb7(L?)b{r=$Zfp{u#oQ9x0Tz-#1BP|mNX1?#tIcL6aKmY&nZvgYSok2oiGVr&3$KR3G zrm|HpTzw`zl|f2iJl-*D0)CN8k`Mc$z@D6(6%fCaTY(!HDaw=c?ZXrmMq4YHfkk zGMVR)#7}ulU{WAit+hu$*gVECE-=w@J^4rP>9!2E?Cp*eD7JiuB5X?GJX%btefJ=l zJ`bauWJdO6#7tnSS{qJ?*bG~dyLPXm9t5r*xax(W)D+0>xM9~;&c49*fFLbixt@~2 zuIlt|y4Z)CUJP)Sb)0<}TK!(mKD*ce3>^$cnPXTNi9KOv7f zoTE9u*Z2G2Z4cgozU{O*TVUp^|HIjAXsNumOvoyuC$!;5%p{S$$VHkl)LMpgVqa#z z$0KruJwhqYli%%bRBw~Io=i8nFUipNwqA5uo2=eD8C+%AnrrRY-k!A@1b&bO)yy5p zsQ9}TU9}a()Cxz>SCz2W?fQX|J2@=jhVBVAP^sFNV&FDa;Cg#35rN#M-wPbM=IXX6 z448dEpN>mxBi*e@97P(3ILmOBK$i0yM&o%NMcr%MOLJ`k1-=h+w#L{5$6WnAiuJj7 zD7`WHNBAB$$g@bHh7r^;#kF!j8q>trPtKt7pMhgI9${J>1^3eRw7S zn0!AVf+^r<{K6GY=sZUqmn=B1ISi&Y22zu8>Iqb$)K`qwf41`62b>hRmYPoei_z&+ z{R3tb(7KX_NRf(wWqPzq_G>8No;G^zsAzpaQ7$@H;HHVX^#up;WzGNq diff --git a/代码/robocode/robocode.api/target/classes/robocode/TeamRobot.class b/代码/robocode/robocode.api/target/classes/robocode/TeamRobot.class deleted file mode 100644 index 049126aad28512e147eb3cd4431e087ab3e2c201..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1923 zcmaJ>TW=dh7(KIg;>Ovgxj1&>gf`F??A*2m+R{3tmo$M$E}*!IxICcAdN2$2ZnV3O z5Pyi5J`@S51SG^05Bw;^nc4NmDGpj`c4qdQ^PTT}XZG)Ze)|K!yZER8OJFt(jsiDm zE9beAy#p@d0`daoZ2xilMEb63r{Bf}u4mu$B=-DRh2Kb5Mb7>Z$R&Xr{~x$}qWm}# z7~k@IFWwf&)#`@=`5n?JB8SU1CQuZ(()4`wNxyfb!sqg+tH`<;xUzdFLr<^M&3yc= zN3>Ei%bKxi2uvS^fo!`nil3<{k{zNf)|%hR6X|$?(^7=$dOvEoh9*(m{lQhou^0GJ z0cC-?LFE3Y*_R0jEZA5?m86fA3I&|Awl}qv;T&u5I1MO>D5m z=kS_d6gP^f!_l6&b=Es`dMD_1$%)M}y(_T*t(i%tPby#crbfgIl{U^z%4K18iqMm> zqNV0*^{{XoLHFRIBqtl zaD{U_3BWXFxMKG)$EXtLd9LOSjK>{|J4>s-pz;^y^y^P7t)1cx3qN7}S6tKJIRjoM z6A-3Apc0=7L8=^evT_2GCLIxjiLt9-5v6}yt=*I9|Y#L92;x130}&bLlxt!lVo zy=p@cR;CwCn4bJRJ-L|BoX#lT5g5sDgZwtB&@HNSdkB2-Jiiig>D@GoOHR5M)g;SI znuWc%Z{Y=H$h|OS={_ei++~`3Y{Gpk;K5KEs#zPVXkd%@sUY*5eu(Wf;T*9rO^7I0|iDGCl94n1bgBxSX&r4cM=rVkdWjm3GMgDf#b`{~p`dD{fy8FGLc{;i0*CLGWLyMCn(AmCc)yw)zCG z%k4wBxD_ElL~u8^`ime`B9!10sy&s+chm7eX2)VMlB}qg#$wbLnKI`*=;>2+PH0{C znrn%LHE+~&Fzb9bLId{*3zJNxnbMyKbihirJZHF3s;$#<1fdvm!$vz diff --git a/代码/robocode/robocode.api/target/classes/robocode/WinEvent$SerializableHelper.class b/代码/robocode/robocode.api/target/classes/robocode/WinEvent$SerializableHelper.class deleted file mode 100644 index 9156b4acaea6b061593641a772834a55320c05d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1194 zcmbu8ZEMs(5Xb+MOD}2eYTMKLSoLhLaw%faw+r-%u6{)WdwqO5)@tr<39z9JI_ z|DZIKk+bz76_y{vD0Zakn1!+z?y3?Kn*A^o@pj-PiQuMbl^6W0$Z>gFk|&pgr4qlNPsO~VDOuur&%O9idZ44prkmhmcsZRVR5j594@gv+?XFeOf5Ri;;Qt-$W^ zjuL5p#p=N+ZhYeTq}10FQq78PR&+C`FM+FevtVwpRp+UywWsCgRa4sk{;Te+{wiI`+D`$iSX4G%q-|=X2ZN;H5ngC1Ukq6uL7Vc(bx< zzFaj6n-p(`>8!}mG%aoE&oG1svKtJM1xlYl7;PyuqlKY0FKzK+@BNl=3w*027~1oW zMaempKh^ft&_0i@82K8C1clco%rI%R4itJy_$@eF;9>R8pvF~rC%N+1&8JTfxGcLM!L zhBHN_kWx*N{zi2KdXRHzQr5fYyd1cxReB3#7D+zSG1@e*89GV(HSK-*kt%oW!a?(PIS?# z4H;Yv2u1>eaJu-JjzUmyl^+<|yX5MTWO3YtJoGK8FdPUA7X6GSjc-x(zS0wiB@WdHyG diff --git a/代码/robocode/robocode.api/target/classes/robocode/_AdvancedRadiansRobot.class b/代码/robocode/robocode.api/target/classes/robocode/_AdvancedRadiansRobot.class deleted file mode 100644 index 2e4579b2006849e9bd6603407823f3c4b443674e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3320 zcma)-*-s=@6vn>`Ej>UnY)#WFGK)F`C^Vw8ILykh%?QY_MIUr5x(g_TYSL6Q<0LLI zafyjbOk853(FeB&9Vao-@xl1ygMXCqJKaT5g?+1i=&F0`o_l`hJLlZnfB*CQ9{`52 z97mNxPd>Mj%jB|F`sS7FuIXf~?7W$^O=oAG3vL`Sh4wNwvZzpV-ga#FqC$0V-?BpN zDjn6K8np%7Uzi6&(S_&=Gxs18FZ02p5dmm%&y1k=tbh->E5X^`| z^P1&OS^Va#d0`gWW3}L#fflqfifzlvE2Q_miCfopTr0n7W~`mG7^JU_nmcx;sB(_; zk$SYDJ&vTpfFH*H*=QhzMuo$SY&4gB*^91@0d*Sak}M<(j-<&pH|;xCcKmk6+IH=n zqtLM6nwgho%{#w%A@59EtFA9E);re6S{+pwst}i7K#?n&>Tv|e4LpP%g?i7o z#HbL@m-4Eh#uQq;wRwAOeIMNDhC`7A^%>|FZ-->9mbQ}z+4VMjE5l3-vnMwCX;q8fHHp@gZZeT(j)cOX@fIkj9=`5vp zQ3_*inQT7)xJVVQ8+ck$+FHg;p?fdUy6v+Do{{ZsWes^<@VjpBynzMTD;*;36S8B$ z7IKAr#+tC@s^~0xBMoktyC#nDcvbTn16ujxUBh{tqcq=2zV!c!L-#nSLLHy73>-&2 zpGL`m?*`6zaM8%8Y+jC7kQeE`cf*8k-aL)-eqZbME z1w1D`&)r3P)l8QUqQ^sQ(1pa^T|y+}^(T&;ymcSPs_`9aNRqHipd^(60|X7SY-wIJ zL%dOji?Aevr5_I_qlXz1%g3)VRHa1937>0w+^!P0b&nf?Jw@zkYCD5=oJA+j1+ZN{ zwkwQn7wkzNyXIj#O4w$3iPm17)(eDQtWKOVX-K`*dcH(9M0*_|ta>_vCyS)Z%#PA%3Vc9q)JSg>_= z=SBb<-JMVQ*a*4jbaJ=IbtpGSx!aVR4{)R9Uhuhkxms+2*j>uKMY*>r_f7yCE%&02 z)g8u5I<2n|`YI3OYt;KX^}Z2+MjyseAF4TwTIQQ%zQw+Mn_}Og*mncW=)-u`XGYX@ zOsDlda^I)U52*7)*7c(RH@dEqK388?E%sw#KcUo5DfKhf_45EWx~@|dE{1EGi{T3r zzhr{HBK7McO?&rDS3t~Y5Z@5-EfL=n@k2CXt^(qQ2Js^iKN0aW5%;1Ii~K{Z!qUIS C)-uNc diff --git a/代码/robocode/robocode.api/target/classes/robocode/_AdvancedRobot.class b/代码/robocode/robocode.api/target/classes/robocode/_AdvancedRobot.class deleted file mode 100644 index e60236302c1a94faea819a790815e36b4af17c2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3356 zcmb_dOH&+G7(JH(CJap=5C#&I#3uv|lf*|<5)xqYK!HR+qLNoLbAi^O2Zx@BR{1EG z{s7(U!YYlGvdYTCg_TtnvHSx*%DwJ&XL-J!X6E)dG?e9Hy8GVy-SeIAe2=;R_jlg| zID*AE>J+*P`GtHYpVg@=BiU=Vo6*^6?s#$3E9@*E`g;nE#~j!3h81G{2j&#&$9OS; z7@90Jpi!Z9!g2Lfab-alX6=QXR%oBdXYAaZU2tR_Y}R|r&YHrWi86lJ`H({An)YUk z1@}zRozRP3S}zr}=AHWfw0KUW^=d(9Y)@y2GhK8&XGPCBYYv@^xNhFFJtyzdJ~{D* zea%kgYeLX(%DwzG~c+$Gj@GrF+f!b50f)D=+@ z4B!z9kBaKaqAO`}?40wi&YoJ&=v9ecA)eikO{EoDW;{Fd=A^wEWFc8Wn|79#D;jrt z6rL>Xg1IjqpRn+x5ZM{FQ0NG-%nQOiW#N!qXb#Rt^VxS;bQ{*Fuh zSVzIquvXZ$q`kA6a=A<80%2vQh3fMbUcgamR?vafx8o!Ye)<9*^0%oI_;=7R>^?x z7OvP1XeCq|zkyx+iETUI0=L2wakFpWTXft*m%Q$xtM4}UynP4zV)z1$xACwziusO` zjLG+MOFAn>TlO#i^z_ENihR5lwkGu7#>#5^+e*~FaK&H1uCTWm~;BuT? zhS{1YIJ-`AOpO{`ddpmT!(8?Xmje-8h665*1AR9!P!T%e$2dh5&KZ6h%YGUIKkT&# z^vFmDH&cC{kzQn^ml)|~Mtap?5FP2^2rkhjaAY$wIg(jn3AikQJWJp$gG_V@JoBH) zY^uzAB=bJWd_XcElFUcjCi5(gGSju2BgI^odhI5jyTKwhd+lT2MRl(YMZ^{=sbke8 z^$APrQ-gM`k~*#T4J~3&Z3LT($Z_P@*tAoBqT`=AHh$sQ_?2Vh zH=jUhSVxbI3lUsG)%?V?|;LRWQYP_Zr0 bGyg|PC<}4bf;QFadn?V78YPkSN00soz{&|8 diff --git a/代码/robocode/robocode.api/target/classes/robocode/_Robot.class b/代码/robocode/robocode.api/target/classes/robocode/_Robot.class deleted file mode 100644 index 51d365433279c6bee96ad6ae87d38a24669cbb20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2119 zcmb7DU2hXd6g^`*cH?XkOcEDTwFUZtlK`e4X`6-yh?9V;6p&LQm4~8e*(MnYPc<3V!{3yh^<5j#~;>fkM-q}0%o^$S*JI`PI`yYT0@nsGvh3UZG z^Xq=Yl<(KL3UkOP%p`*Ax?>ckBpOx^bkp3@2MnCt{!ag(%Ps9S%R6D{g1#-xLBTJX5v7S81Gw!+0j^`js-IExv!(zN~EG&;;v)jJN}72}FsPn>mi%l*kTHXqhaTUt_> z+zEC4`>%96vM$H^ZFk>@jFN)|!5n97(=$Qy5%am`0j%pVY#BO21FMpI(ZMAw$qC#2 zn&0&r+?LN?E{i1Z1BcVaya{gDB*qm^bWB(khk`D3*@MlL?#T#DTI2d*b&pfPTApES zZe~jhv6G3$O-|)=2RUR}LW04Pxzei@LOAW29|toFtgQ_Usvuu;@R}eOm_NA7m{bhh z2dUU_Fm_lmu*(XuV}K)yCGzq+emAI_EmvlLqIWAV$wkYYB}1C?lSWEtxJpUu_D!LD zJA8PHm^Z;ynQz7S*y3Ms{@@~oDgI||@C>H8c6tdofdapHr7=VJ-ki=wxkbJO?i*xm z_Wa^gy#5S@S-c^ufAFS4^U2>hH}!;BY0Ghvxj>2X7BGh;oWg||-+aXPp3PTtgnj=Q z;=2?seH44dlReh+3P+MIlk^j|^BLP%iIEluNehHrq_Sb%-sS$Qq!$z(v(xnBM5pT{ zt&nt+q+7?6mj5^D8G6a1yLf;zE=&MPie?8LZ8zaJ1l5oEr K33t<;ZuKR)a8@z^ diff --git a/代码/robocode/robocode.api/target/classes/robocode/_RobotBase.class b/代码/robocode/robocode.api/target/classes/robocode/_RobotBase.class deleted file mode 100644 index dacbbd0e15b3048b4287b86c362c186a3e450259..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1636 zcmaJ>ZC4XV7`+1_8{;Yx5pA`wwptQUqF8HdC|WF7Yd{auoJK!*CYu3PlO4`xwzU0M z{ZQzs=d|DbQ6BH?VwN}iVQ1&%nfu)Pyv*Bo|NIMJ7Ap=01kOgfrG4F2)t9TBnFZNX z4srr#Uddl&wIjog>XX(hso z%Ndu$0Y5fUDbN=#PM|0-7Kb)4LBhJ-=Ul{>C_9)ukYw^!vhAXRDS=ad97QTL>88MF zxsviu>LJ~&S(s}su49H5HWbq#{nu*|t3kjkS6=M9ksU2|RF}ZKd;_x%ZVFt?Vt2&M z#Vvf5qAx46soN{EOZ03C*Sc}3j8oGqvCSRi{zOoFlJz0$B2_gvh^_sqB4+EQU#;QDc< z2LiLtd#!*60=iuBx`|k?rPg(%yx(;kc~Kl@2SG1krrOs$9ochF(k|{%i6^~8u&0x* zC3$HQ1se>V*Vd{RP8#oZsJA`YVpq*r-it1lY@iE9r+SLGjX8lKlcsb0|C7mvNExT; zDIF2W?kPT_3STV+_8l0`8f(U;B6pePKZpSgfv*yuCzdZqVf%sqA%1LRu7^3R@-OV} z)Gp5a$;kjp9P`QMRh;GAO${)Lb6kzuCZyGQ&T~AukigvH>;ufF8B8(pe~*UukAWJ& zC49zfmd89TE!X_i^j{c1jIc!34-Dyh@rgt!3THvsQA9nHZKboge9A^T6 qpE))N_zNT3!~~ubzKKb$ZFH?5hdV#w5m%=fke~3FBn0XS&hmT2(SL{l diff --git a/代码/robocode/robocode.api/target/classes/robocode/annotation/SafeStatic.class b/代码/robocode/robocode.api/target/classes/robocode/annotation/SafeStatic.class deleted file mode 100644 index f7869f90f6a9afa417b073a390febac3b50b8a91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 392 zcmaiwO-sW-5Qg8W*46sadKB>k4?P<2>Pct{h5A7fy?ENhv25AyO1dfZuX*qX_@l&$ z2jd~&VPvy5BNf^xaN=H_^ zS#+Pzxd;kdgtKP)M|$(?Lg=NwDhnPP%Y=SodRZ$8M@i*^S@4rtn%r`uToO*Et?rpF zXB@5x-IcbLxL&k#vE>E3kgeaihR2h5IwG96!wCmr<==u1|3MzSHN{#$l|0^MliPSm jAZ$o<<)}ah>L+hwN9wWkJ=yI(gBW|*$3fjO`WSozzq@fb diff --git a/代码/robocode/robocode.api/target/classes/robocode/annotation/package-info.class b/代码/robocode/robocode.api/target/classes/robocode/annotation/package-info.class deleted file mode 100644 index 943a46eeb44fa3a7874b03ea753e14610bdc7e09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125 zcmX^0Z`VEs1_mPrc6J6PMh1nV{G|Nk{FGGv#Js%xlEjkC{5<`F#N_P6^iozX9m^37qKuF_)n@tRX31cFYkZ>h#kU+p600RCB;Ca8}xVB>>dNE7R z_w#+9_s8?TpY!{F|9S(!LA-5Xo5H7aT zu7M$i#AWk}IqR5idG?9r%U01hFs!gc@7msM-m2QBV_!3u9gCN1dReflHOimMJ*uEi zD~!x}Zp}AczhF9bD@;4&qj-N=qh7Ktr*z&f`76AiQ%H7fpR(-oimwoL>y-ts?v`o_ zqvg6g=Xs9pmKRK)xQaldwrduB`-<(aowY0699^+X)(O|Dter6{7RA((wvhg=9rvmw ztD3j3@!qh+!sq#YPtR`&%YvMBMdb+nv0dAz+j+~cuTt=yfr4^@0>clA#4&|)ncP;4 zAoMy2-ADt~c4q0wbU|Tgj=5|FR{eJPp^v{WpZ8)=_#kU}UkT`=$! zQtMW4$T^NxHl0VR<$A?({S#M<)~fW72)@Sp=*eWdXu7WFrNTzWSo%N&#})Q<)obsqqes(S z;t{Z$Otjn0Ep12B_eXG2VOMvj>A7%9;qJi~4(z86w#0jCj8bPG>eO=RKn(LZW8iUx zX|b(Or`}5WIG(_h3X!tqw|XfPm5Y+13vt9TB0A5;aZWBpc`4|ua(+IJQH;oJF^=uQ z?CChh5Rtua#F0Q!X3xek9-NwS+=(5sSBzrbf_u(~#XH z5pz8qn)Wdia`ISDL+6RKbe?oHM} zL2N!0ck(3PlcOMR3$5oOlbIe^HC+wbz?#CIEqT;>x|&`L*YUD}m%3iv{94VoDsg-h zuMpp?R?W4dw@QuK&Qb~9<|Da|>e<}Ve#Zpfugz)61bxeOKVj+r;f!tp2Hqg^2RI=& z6k;_QTNtstSFaYWleYXWm<+PmnzC!dlM9gq?aM zH}yz9>X8i9Be|$YvQv*_q#nsfjw9507k2UQZmyOnGsJN;yK4vT-ht2U-M5aZpK)g! z?&aSYM<7F~X?%gRY;YU*;fq{RPAY`DWR~F_xjia1p#9)e+rn|_hge6P^yE+|HJmcm zk?qAfL|un9&M^#YP5p4h&j3d}*Vb$7Ktiw$?c?4S_H}w8QA}o2hM*@(8FB-6&=fIbX7|)& zn07=`QMHZ(y@nL1`n)z|K}W6A5Q(zHJ1|M&5SSFwGciei`6Q(`wVV*+B=$+27ims> zJOh)|ALzgxJZomx@uiuY82JQ;7stN3jt4$XMK_m6gXPB1`>peb^hT_SiBxPO72Wtz zYyT11-`&18C(EhWyFX|hpOE!rm@NC==GJ4fHEtvhZmQ17Mt0_x_<93R$(V1Tklo$D zh3r%VOWDbA0~fR7Mgz}e$0H3qmrX?*Sk9(m4U{B~A+O&`fsvz@D^CX(cep{2dT z+NQiCq|GJHrx5uM6-3Ez1M_Mqq&Suh`iRlQ&e82-38vM?zulE(M_eFlDSNLXM;Va}& zfV|2Ylx**z*~>Q(Rv*b^<2SfEFO$$rNUwi|Ycmp&fU*<1aR11n{Sy=aXXg1YO!!|l z)I^}J<>VMk`BlHmk PeuI?kLVr`|=B@t%M6z#_ diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/BattlefieldSpecification.class b/代码/robocode/robocode.api/target/classes/robocode/control/BattlefieldSpecification.class deleted file mode 100644 index 78912c6b484358f24f1eae24b29d9be0944e30a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1023 zcma)5T~8B16g|^zX}h*U3;5Nd%cpHYwo!aQ5Tb~&rs_kr>f>}7+QDU)Y^Q4c1wQ&0 zOnme~6A6hX`tFZX@9b`bC?;;QJ9o~^J@?!*v)_Mw{tDnS7Sl*DR0F@`JN}li9p6)d z@7g!HQm)vR!rf}^2}f>Ahb!rOX(Sm&cKCB{yWH#A4>~)-QE3b@jD@K5?Uo26cjYVI zaRqJehtswQ`jr2uaf^Z7Wyo*%USDxfwYfVGDH5X}#*lg;w^WZdH5i6^LUwzKf>r5B zwZ>pns%?hk25B|HFq*?K#we-MXy}FEru4-9!EQ$c52NzMrtfgK%}El;iNU1m$v(q; z^S}FEF=61Gt~QcJnPKYCf`;pgE_ZJP-NCN#)aFY^>}jhqIL|O0c4O@h`pW8vYt~Y| zZmnLoB9wxw^?Kbz36`dwWEihB51CskkY0DC+Rk8_VKy@3FRmDl$+G0iYz{f(b#yU@ zlgN|XEybN@_xN6HK&C6yK@C z8X1bSbdU*{C~6fH7qtc&le9+u(YHXeVAH5mQngQ*c~3zi)G!o+t4CT-{ce5!*yOoClQ)k|UI0u$)+p*H4pv(f0UT) zu1H-Ez2uSPy_tD4^ZE7u0RWe9+JFjyGp!=U)Eon*q|r(Qqe<~{Cu1(L0aXH>1x;xn zsEmVgv_NJEbm@G4LyZv_^2DG-P2j={OW`m@X_8>H&K>$Q0)34yD#i650yQR7f&{ia zM{31rW~dXcq*Zu+_*=@x%A zFJ_#&3HE5Dw7FerZKw9*pfy!1&G4SP_V)km$H2{_PQcE~t`$Jru1gK-;MS&5;5Ia~ ldkc0lY{PDbd$3<%C&MoE3Op#VpW$JlKXPa@9ow@4C*NLV%tQbH diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/RandomFactory.class b/代码/robocode/robocode.api/target/classes/robocode/control/RandomFactory.class deleted file mode 100644 index 5a364570541df515f3fce87caa72b4dde032e724..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2740 zcmah~SyL2O7(EvTW@wrv6F1c0h>5}w8P|w_MphMuMF&wxG--y*(AZ3m-90GT_w_B0 z{sCX|5VdNclB!hRQk5T&-;wuJrE+ff4AZEUJkXbW=lkw=&iR)6$3H*+3g8sJkD^AP z-LV(#ti2>tSv&7Jww1bWM` zrE^*4rDM=sAfEPZi=J7zs9&J%zTxD}d~VA2GQ~o{c09S1wsSeTBp?<9T1qaz{Myou%zqfoB(2BxS|m%Gb4gnEY}sC-T9n87vX zi`D|i!g`gH6N+8QAiFZ|NP0ZeyOGXub!!uDsHV)QwBFQ_#v}{Gm445UtJZl-M-;Ib zZVPDF2d74+Co`j?Ed6(Am$&n*Gy~Zv7Aq|uRP~1I$u%8IplFROuNlWKNXOd{=ncaz zSAPih3;Lmaq#*}0ij|##{PxkYio0x1d9P?#oD3BSL$k2IYaxoY9ZeM6J5)5SCF#Uq z3tXLDk%^`7j7tRlp2$^ZXJT0zUeS>W(@o@UFX2`uWnyt7q2^Lzd~UK&(_rDA5|)L% z15JhBTnx;iKV*8=*Lv0^r@5oFTvw{yf2JKPUe61q0&VDc5ATz|Q7G`9|DP~BnD@u< zAqRXShL1T!R0}CUd1Fn+@M(Fj1rQyVou&eQuHy@Q$?o;+;HuCx4No;S2)@?wjZ#6Y z&I)cacG1boG1DLPLFJd9vL1y1hgo^GeE({psrP~ZX{rqUm6M#S+G%K{oz7hfHT(jN zzo2P;6D>~>f6Q$ScJZtEKX!0Eg5CZp=*E|5+nM}%UYFd&o~m2De|W%m(E|hQ#XcJH zAwe6zDsm53hn=}^GUEN;j=A#MJNjj uN>CXc3se{LiuKVy5A(h!Wh`)I#@GUnr`0ih`S9w?f diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/RobocodeEngine$BattleObserver.class b/代码/robocode/robocode.api/target/classes/robocode/control/RobocodeEngine$BattleObserver.class deleted file mode 100644 index aebb7cd82e4763a0f05b81b8a4883215ab1837bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2338 zcmah~Yje|95IyUJC^3p-2oNX)3Iys$h!Y-dsVNZB1VSAiaWFHyW@P1J1VYM4O8!fK zMrWW9KJWwhQ62VPNsb)Jcs#acY4@DnbJlym{r}}FfXjHQAxD_=+_r1Fo1$jAPT;wA zZ9TfN>~t(g%-k`8z!neNzVLR0r(u|IA(bO`gcJC+Fm`d%*a}>aFlt+VARNJ$=NqY< zn5Pj1)d?fP8_S=WC!Fmc9+oA8Z&;2M+$7AD21b`#gyALbatwrV9U4aS7{Y{(F%$_y zB^fZ$;C>%$zi$g~!)V)raJb=`hTSqeOa6{-4$C45^MgqDDaRETT_;p%g)8^ph)qVx zsJ%zbICNPmTraosIF6q*oFG(FiuO;`aT2EpW0t?zcD+C{bI;GD8mDy}z(^iH9p^E_-WsMUd}Y>ZMi0F?^>SLQP>JT2Fs;{?X#|$*)DPk!N*aFQ0q9#r zJT5xQsIZxBHJ{zK${EFEQAxuOD8UGq($)2sl6@R+28Q`=&De@2;!y1ClKXzk7E0cQ zj5>NiyRpk%XBTiq!)3y3s`(#e>bQz)JX;+RG?lgM!r!(7p3sw}^7FmULJ^{e^*nyV zbq&80rc-3nyC4eG@dvo$0xt*t_s4e$^-^ExBx!P|#L3F#KXu&1Ed~zli^U*h4O5nX z3HnSD>F?ZL_i@Y*gyc3SVk6ghw2cmLfZ8A%qsToI|H6ufWkMyTYY%raPsd%{Bjnk_ zF7c64x$)N6F>1EqbZX7Ovz(4n?!Jz{(dZ6-H{ob09WOQ5c71zwS?WYgXDOtE6gB|h0(-JDdFpszZ7 zFfG}J?+gB~6v7#ck2&6kydn9R%<+rYBTy{LLxb;(@EvZ1pC9C3S5*X%uT(!muY5w` zUzK%8MG`<8ILy~N$8!`WafH7KM{z7dco`uaul|Rre=u43fN6f~pK)dv7jlqzLy&j{ zSrI*lMlUc$uN3Yv&ITU|A+EftVwRCFsVth}%Q@5{sz(fVP0fR xX~RgR`UwxSrR7SCqj-$X)#nDD@V7LS*!C83-vL=ifCB&k diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/RobocodeEngine.class b/代码/robocode/robocode.api/target/classes/robocode/control/RobocodeEngine.class deleted file mode 100644 index d8164ba1e0b65d0697e494836cdd23753d479db9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7438 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 diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/RobotSetup.class b/代码/robocode/robocode.api/target/classes/robocode/control/RobotSetup.class deleted file mode 100644 index 6e1c29dc145f677b8de3e6fe8f92bfea8c208513..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 828 zcma)3ZEMp|6n;*dHd{$;m(@Bu=gVHCjnjbmMI3(F5S5}}HR#9N?9$y4b4Qwp`l}RH z27d4d_@l&gZzhATh=Jrj=iKL<=R7CBe*gFh;34k1s1VjOJ=U>4lwqvXJkv?|h7&`Uyd zU#HVtq8&?U{{vcWg;hF~zO@pp`xKg5Z4=pqat)WWgtK#EWW^YT2{!qsvi3Ho` zQO}c3ex#;^jp0AG$*!D<%-{3!`h&|um$x4X4JJMR>%1}2MHb6v%51lF@oOHKo#778 zT;;b02R*o0V!X_ot)Kzlm}2Z3OZH?#d^*f&V}-vyM+tKsK0Cn~R)c#pbc5X))`I&p z^uBYxf*btpvI1Dm!6x_L;*Q%`#SS(&8q8Rd#aM%zq!+s9#~?j5EW>-oFqALU7~rO)T{Y1(%)$C*`idEJF||V6(vJNW>ypSu{q5nrGIu}mY{~{m!JtOAtnYK?S^Tml4K+ki>F9^ zB_#&MHxh?$FhZ*m7+@4*w4))630lSD_jH#cnf;E;%i_{Q0%2G<-h$%9?OA4_>6;_B`jPO*fhN%7I)&|La{u8-zQ0xywm<5u4 fj8xK%9=9OIprqnDhDZMT7*9xwW}|;NY$Ej=Qc&`@ diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/RobotSpecification.class b/代码/robocode/robocode.api/target/classes/robocode/control/RobotSpecification.class deleted file mode 100644 index 64f73cacbd5ce337374a3031a098f832a1a24636..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3388 zcmc&$-*XdH6#j0SWYe(FQVJMADA1NPF^AORH$NHKuW60C}{-Q2X>rkl9g6hV3Q z)fXRpaC~!o)fv+|GUFo;{2l%qI-YZPlWx=KbbO)HeM~c@rq`pA!FnQ{|SNJWxFCb z*%TNkbXv>{L>+U5^oQTgc&_a%(7U+V@D{7Cfc8Yr*USYvr>*)P2=uk$41A(@OQw5+ z%#vH>Mx`=UG3)g^O8btItXr;K! z;bT{IOo0d-uSjRXTU1$`)^I~${{}&Q=+%Z@DM^=6H+4*dD6g$D)$f)CM!T@4OE^hf zM}g~gTVQV(63{AB*4s{)hh?KH(Ec%EDRRk*7De9mtv>g(RwMq(%!u8zy;ND<{s%aZl_@G0uxZDl4O zZh{~W8){AqT-=_Tt-0eYx7<1NzuXBLnC8_?wc%RQzkK#HpEuvP6Wj{a5z~$%UDZXB z#-$$S431Kkdgv3w4jh1n1j)U0nMRPLnN8E3c2qqD>4NsaO-EMk?M! z+DK_l7)C15MAk_4HZk#w(tMJ>C&+hT6j7WY-_zu6hHe>yEREp^vKYZQNfS7Q95w4n zT7fdfN4Dwr%Nbf(;#h@}INFGkINly5al}z2am@Ua;{xAgh%1TX)|AANCzQmo^Q@rz zB8WIgD_e*ezhdZT5+dXbNCj_RRBq}1fxs=nR}AfNy29YmPVn`vU>ZyT_*;sCR1lx(A)Wa+|_}JPOujO$J$`CD>&T=e%=*4-xWOE z3I4h(*y;*C)(QTmE4b7K-=eH>-u6(=c#5z_w9s6EsqaN!Ak*F5H&JtO;lLw8l?071gilyQyEtN?1 zuH*BKZuk8eZEHxN4lmF!LTjtT4tE+o7=kpg8bC&gncVDg9zn9x%y0I7i^G|j9OQYr}Cxm#R`c9 z55Pkqj>k^zB$`ZFc*Y+8=lgxmjL)CHzkUN~;Y|SR`?t*X8lvkBj2vdcCiV_pAQ&}vL-lIw!>0vg&&)fRbi39Ug z^2l{p49{&YQ{L3sUTPEHrp9+7gkf=Hyl)0xm~2z$8VM82n#MA%Pwngh_k!V-b~aWf zj=CKk3y>)uh`2I>l){LrFMtx$O+X{Oan0CbGnSkD`F${i7S0-GW3~b53)#zm$7>2IkCXEcY za9f9Xr$nqu#2wt#A-0u>dlGRU4|IqfCE}q(Ji=ogqN7ASk%*@VcV}ifKPnN=CE^8M z>Ja-%#F|9B!nzLeRf#A|LdJ+qA3vuHgt%A60s=}EqSb8{{!XF BEg1j+ diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleCompletedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleCompletedEvent.class deleted file mode 100644 index 5633ec327606d5de5c9b0afb558943d6bc912384..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1524 zcma)6YflqF6g|^cmX?+B5Jd2SBH9PCfNzT^Ade=ECSYm|pSER!OO`I#-4ZeWC`}}w zM&oCHl<~}Lp#{|VVRvWloO{o`=ib?$zrK72FomLln829tRlKUVF0HCp3w_VEYvt@zAJj+WVj!N}iOws_m9--%~aJ*U}TTbC7vIa5& zeNEaXg4{Xe*_(hRGV#_pnk9;G%fz^XaZGlkAIJ_&V9LNGrEEr3coVmAM}>3Vv1x2D zr~4k~?&R1-QmQZyOgzLRh7LWgl|bf?<^MqvJt~Q+x4lbITLjRFt6@JjGP~P{W0O09 zoj%q3#>CIC|K03=v9>PX9t}VWb9iQ8{;-p}ORKv3U{N4xtFA|hD)fdTz-#>u|0Huq$!48zI*5ZSbR^=Z4#aQA)TXTIC4WD`nh8OO(XP55yePw9s>;; zi(hqiCie;H4_rjS+qChK4roSzMnD#aL0VLf?@1NoH}@4ouNk2G0GIYLQpz9T2A{Ef z{xd9rZ@Bvz_ha~hf?|lbq`$!QmbhPLN=41qA4P1irFm1P@tAxw^i-KdmM2^ZJUz;! z%pz4LgDQ*fBrK^#JRjHl1I*@|wRLKNUQ)C&Wq8%XI@n-MqMNMknq!GkV_5zT+~jHU diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleErrorEvent.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleErrorEvent.class deleted file mode 100644 index 04a18d91e4b8b9ffcaab413114d2fe74ef18a12c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 529 zcmah_O-}+b5Ph>OEUXLo0eD6(3nXshRpUVeC*lReeOVi*4Ov`uA&gs@(2D!J z`Uv4vt#l^F(#~!F|D&_5)P;t#LHw*kc_C1 diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleEvent.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleEvent.class deleted file mode 100644 index 52ce50445e044c5f428a3ed2d56f96c10c92dae0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 310 zcma)%F-rt75QX3DihZ>4k+qE>r|31WIOK)CG&y^|E}@1Zv~#mE+MDpC z@A^60Oc+gFaQT8TI6RsW)RmlRFu?j4LyQQM&IP_*zVw_POz)Yn-9>Bs%p_OxZ>jRL zTM!Pqf1sQbn)|p+mTz1+*#5yhDTHbd!XpntoC=3%E$Qqh1HY3qeLd diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleFinishedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleFinishedEvent.class deleted file mode 100644 index 2841173b3265636c46972510e683ec6a0216f6b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 480 zcmaJ-%SyvQ6g@Xd6C2akXAxY9sC}RTw~C-*SHX>vMR$1&G!iqAO#4-C1VwP+2l!Fq z%`_W9Ixuq|bMCq4-tV8!F97H0J1_|2QpPfosqhn7s8Z&>ScpPZ{!OG*E+$!#RWp&^ z)ky~y;c#_<1`^s?bsfu6iIhN7f_=$E>WW|uro)iUEw^-GV%>uSk6;dlVHdzP#x*LmfALP7Dc*dH3@1KFs zo}xvB1D0j-%2-0JjXi^X2W$McIht^6uyscteD~kcdDWO6zg=B<1PjNEJ;4U&`b#u6 qnXf*sX5~Gx-EKI2w#0v}(HlB1>=>x&Y@PHqjkg3eG=v?E+WiH;HDU(< diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleMessageEvent.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleMessageEvent.class deleted file mode 100644 index ba3234178e4a913e691a892f2c1af3348e753f1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 539 zcmaJ;%TB{E5S&fZhK97|QQC9qr4K|Tt{@H|dMaFsdUt~rjM7+2+1swLaI4lE;lMExBnoK95T+7tt;f*jRk@qssMJ(?u z=D{WOck>G(!CP+X2uITwu@+$>(m0%%Or`N9p?0NGWv&S)gYDztoZ#NFBOev)2k;OO zDudy?4ni|P6*WR@s#5u|S}tVvC>DvdjdUcExyY2wOVBmXDkq#xcf0<7OSb37(v%RP zJs56#WX?>lvPe#p?cLpetaE#9^w@HRUz_b&-yAs{d)VW(&e?=>hj)MU$#eXH##_N@ z@!BjZdvI~e+&&H%>ulIKWIa3lLX}wU80}Is-M>u2z8KLMGS{N*Vr! Hg4Ov0($RND diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/BattlePausedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/BattlePausedEvent.class deleted file mode 100644 index ad965490f913c3134196b4a583638887fb25bedd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 347 zcmaJ-!AiqG6r7hPO^vB79(q*7i>=T=Jt`hr>M4kz^u9?SxFu#`v&nyX5rzA6~ZT6 zcE|TYLjO*e+T9a+SJMr_U&;OmJsiad&?k&iUGii7ma%Lw}j}~)Hde_-L9Sd`^9{x8ifl;H@O0YsqG{fin`frAeen%@GgdjNH7ux W&fw!5$1=qdlaTOGm~bNKVe||B)Kz5w diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleResumedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/BattleResumedEvent.class deleted file mode 100644 index 82dfb6b977e063616988082230102c8442ef8ba4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 350 zcmaJ-!D_-l6r2~MX`@x?rMDLGqEZ^DM@tWt_7r+(i}y`@;Fg$$&Bp)oB=pb^@S}<^ zp$9?mGV^8_-kaV1-_I|ANAv@Dgo!nYNzIa@)a1^ZEaDC4u83Zga~XedQLcIUT6qC{ z!ti{)4iZ{VI@j)*&=`#u1b;3ELNsvMK@%-PFV;D~m+OS>mr61wT*oF=*+N-e>3`FA zD_s!oba7!KT8*l0~{O<7F*PaZUpn0W99 z_@j((OCy9ddfAGy(eTy8lJl~wD^D_*Zeh&t9tw)L);v+_=BZCF|aPVq)ZIXoS`j< zX)r{OOxqO448=-tjYhZHVF;g5fCLnzRV1;%pj4`zIWS~YL=cr|Nkt5CiE=9DkYGqR zO`Bg0?+xx=>xRWi-E?}o)zMv3o_#VbZcWOtGwJ{DLs7ES4Hr{c848u^q{7sVuWd~y zr|Bs>t@I{|wlj2l{KAw2=EuhAPuaWEA9ZX}E`@$oK}H59l#y}0ox;){CPfk|t@CuU z5F!Rx(%zBMY9lOasJ*$z_JMHYJ~_$>Lcf>k<6B>OTC z$&Mip$r%)4izxY>>$FQ%M0>;H3xRQ~vGu?!Er%q5Uz(wewE*+-^Njf<&>X{hfH^yB Mz6>;Pcr7-6070Fb82|tP diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/IBattleListener.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/IBattleListener.class deleted file mode 100644 index b8fc7a155d8331831ccfd5b2c1f86d1ce54af5c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 951 zcma)*OHaZ;6ot;O z6GEFiQH87df1&f*X3`bG-vY_A@z?X?Q$CX~#rb6T<>K_r>}-F}%=hV#t?;H2raw5E2Gvhb_Cm`F@K_yhb= z#l?r&jxtCwG-5FnBQfUfk%(k0!Zx4rNKV=hVj7LR(U_0B zipaoZI9VsY@udv87BZw`Wo2Lq$!^R zO3>=93%_*f6+`xkOU>#abcP}p;qwaqJH~z#(|E-10u`XLH0%7upZPeZ_y+yCfs(q0 zP)XgQD_ug>Bt;H3y&KepND%{6+)p@eb&i5to1^H~=P17upTai1J2VS8CFL1;8`wk> zWweL~+{BMv>`_OP^j@Zs+MLoz?KWuVJ`NU}+f(Z>71e^Bw*HhmLr= diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/RoundStartedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/RoundStartedEvent.class deleted file mode 100644 index b44c58476b8dd6dc283540eeed86597d6c8ff9d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 745 zcmb7B%Sr=55Ukm3o^H%Tjjsrbpn0GRxkfxF3W4Ckgn-9QGMJThM|LOqDh~<W zt~_NpD*aiZQSLC9=j14b2+|gkSZ0Wn%AF(_vKFFH7R?c;Dqg+v$3o zI!)1Yyp9vN>OL)+a^Qvx)%kZU+824r-g2o|IP*sWrT;7=K?3?Cv;*2mswIX&k6*g# zp@q3WI=*v84)(}ig#Oq-Ub&?#ue{P3p-vJhic566A%wzZDzC6A)iEW-F>=pTGO$81 z50l~n#Y3W%u#7TRsj@qvVGRYkk$@hGRO>9v`z41Fa_xOWc|CPM0QN=Ga|YAU=yNgb=m6AK}A;*I99?8&K^_EO)1 zN!b4ld+uu;i3~_^G-nQ_f0xXZCbR}WvXcDKyG)CGLQe>#(@=)`jBwQab5?6iFfUku zjRMvkSa1l1W@}sqq3WQB62TpWQe4e%Cn6sClSmM@1}gBQu^)%2p9f7n3lqYM;wy*3 z9lO^;e-%OKH2j?v20jvBxqB{9)X3s)a3sZ3}CBmf7pGZ}4rm zpLutlPOAA>G4hcR%}0_a?gf=l&+Ko QyBUqM1mrY?oeWj~0NgE;kpKVy diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/TurnStartedEvent.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/TurnStartedEvent.class deleted file mode 100644 index 93045647276bfc600c627be755d17a3e23d987a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 344 zcmZ`#!AiqW5S&fY#>Uo);8iJJY7YkN(c(eTQ}B||`%AjeC-FUaed&MoROq1};71iV z#Z#e|nVn(S9rpLI+XHyUb&P;8cDA&YU2s}igxxAFUH3B0QW+ zzbWr)J_ZThnKs(L62kH0oDjXs`UD|*eRR+z3^Q%`tNAI}6{@V6aFf|e)pO-^tN+c& zFZGHr$<7@;t@uJna@)9yKXtqH_B8PHt=0-7NHci>gsE*L7>k-7HPD%Caj_92Kq8n3 X19ymUk4u^Q5|fbdK$vhP7-0AZ-bPfY diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/events/package-info.class b/代码/robocode/robocode.api/target/classes/robocode/control/events/package-info.class deleted file mode 100644 index 6412e7058bdbb2c07e0c2d8341c4622a2805b2dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 129 zcmX^0Z`VEs1_mPrc6J6PMh2Cl{G|Nk{FGGv$c&UdLYGO3=E76%s^W}fRTX} JNHQ_70RYs2AF==d diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/snapshot/BulletState.class b/代码/robocode/robocode.api/target/classes/robocode/control/snapshot/BulletState.class deleted file mode 100644 index 990cdb3a35eb5092576bac6664b001b22418c692..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2000 zcma)6+fo}x6zoBlU5N!NO2Fn~V`DHvToi14i-Ou%K9RDyc^97o^fNs|tD`RZ`W_Y|qa0^yzbE|N7^*4*+f>uc1d^vR>P- z6>HB+iDJ!h>$Pg4;n;_b7d1Dr+N@SfuI1WpNrPXY|D}CoC#tqnPNbdYfk0rx+)1ws zOl7(vNeTqBxxBf(DG=T=cfZSrmUn*8BPQ`sB;EPS?1^jFDKt~`9fk6Y8 zafND^+Dk6SGUvHlZoT4^lcqVH4{`CZfdGO!GzqR6&?L|$xNbm~ASA&}10e~*65KKn zmY`RHX#>3y7!u4HFc6ea^9C*f;wBv@#@b0>F`% zK#lBwHL~^9$gWo-8(xjc zA%#Z#euYLAx)um1G^WsvU{IlPg(fsjp-F|NbX}pCLh(p2;;o&DXutCmUkgK4!QaBD zRS2{&W)*@hj9Ue*g-NTRw-B=m5l+omZ!q@@we=vu|3}mh3{d|d^SQ#OA&g=KH~AmO zH7sBZ4{!s^7{>-CSlvnNVhZ0NhUd)nQ^h3N`1xsPzeR8ToHyb#qi0x%U;Pz}=O^|n z=V$5S96uuSieZrZxgPhFxAIB4>m%QNp6+>?;3&8%5Pyrs6LqXiAgCrEC>q0C(54CD zAwJ`bEXau>19pagCIU9qzuXPXFeK9*#(hSTvCLSbqo?$fF~%5YOfq7OnbY@37NVb@ zVfhcP^r`)~__dVGvoNV9gGJ;heg{j~!wQ~a9nW}$zwJ=E<24ahxi1WT*601Gd5x<* zal5R`7MfhzV`~m(bc5=>FL^6)M9`?z@7p6Slc1Az}FW*yTT4( kNZ2JjBJ4rG@*NWn;H2WG#Lozak)NJ^Rty_yRT;Gx81C9Z~<$DjA# zpXUp}21SO1uynSv!rmkk)_7+%>kMzZyY=j_lU1)S&bHF|A;Xw3YxsjR&5dH`s*%DI zQYHOS4ur*Wb^77byV|HNArJh@buS4;X?rK+zSd!x|G!_yXi6ZALOUP{wh2;1YZhl9 IdAwu#1)Bph7ytkO diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/snapshot/IRobotSnapshot.class b/代码/robocode/robocode.api/target/classes/robocode/control/snapshot/IRobotSnapshot.class deleted file mode 100644 index 2d12b02b31eca315af2f29b84d69911d9cddd654..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 966 zcmaKqT~F0O5Qb+FDIC6zfZ_*!fAtu&iMQU#L2P1#P(whk_OzQ)Qg%YvD;GAgCcqutSoN}Zq}SMIAkRf5*S!Iz8k#MwgU9|SExkQ^J!sy@O4Wt&T> zd8EE6dD_`5BJwxKI#XwYZiIulb7?i4T!Cl{1*^(Q?KnA$Wa6YlEg@?8e`j4|trGRk z;jeA2Y~J|0hJxC94peEy>D7g)-slx(|XyXE1$@Bw@%<8GNA zKrY&^{r{PEW_EslzrF$B9&Ris5$H=X5w4gr+ZCabg4d4@)$=+KlBC!Dmq{+6y?c} z2<-H4M+D9@HI_?%nYry$f1{Cd5>LpX2;+!A<_%-cnHtf6dJMnXO!HRWtIs)RbyDY( z27xYVEv>a-7V=I~>)Dr)(!bY*zYsW0WryimPPLu|j%U6!f(dzwrDUNhRF^92{hGQr z9IU&WJ6rlSv%tK69rto?ThC@7n2L6x>qAGx(q+%SIotaBa@?8IB~W&JFQh7#I^v;l z;;UU56qI~Vw!}RS^it`m>T6H0YE3Vm1qWajundO@kC4a63i1SbimW2fpqAv-kqzWI Z`WMJ1vW09TJIJmfl%SW~FX1ZT^&eKf>U01A diff --git a/代码/robocode/robocode.api/target/classes/robocode/control/snapshot/ITurnSnapshot.class b/代码/robocode/robocode.api/target/classes/robocode/control/snapshot/ITurnSnapshot.class deleted file mode 100644 index 0df0e869c19e56fd355ad66975ce6a6f4b4e0881..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 440 zcma)&%}&EG5QJw7#BKO1g?FGm&`4alaX^ZM1R}X{N}W}q3N~^a#IteW0eC3H+61Y+ z02hycc0P~h8V=_9ALj4DHFqNJ^0pvsO=me_ z7=v`CCaCZt*$Kz8E3ETems~v++B*J6&N#RB(}_@WQ}gR4CM|5|G+#Y7Oqgu6H4jB4 n1PLcy14_!OAl0E`$LeQ)l;gQK(d0v9vNN0A=id9A`<(NfyZP(y-`)bai5(q70?CGV z;MKe*R<`E3e#3LJP1ihXKK1se_cRJr7OhVB)2evQ3$+i;5|&R@U_m8$yBLJs_Zvxx1K8&)0GGpPZ|g! z6oxK?X#=_p!ZMgO5SBqi2J;3Y2+6mr1`Lb{jFoKHde}NVuo`>jfkQ&El26o~h$qFqGVKorAd;Xk#T)UR&&m9|J^N11frQwUayP0?FW6HpizohtfbIUTH2t@7Xw(TpE(GDuuHywv7)Lx{UPNfHId=#G|uVX`C zyi2Tn()6uE1NX4W4a`QvJgIp{Cjyz?(svJ@Sv5ab>~X@sLv#WqR@Ll&Be2?=)^W># zn#*>7W?&230=If$HXXCs%=PU3A8wb2JZ(HY(X!WS)U5lqwA5Jla4yT0Bv`iVuIaZL zoW0WnD6`iFbH;jZV}(Z6_<0CzOiB9#eA4;qNzAYU~|NJ4fsl;wrin2&iaEMKi&miV`Zi915vuPXC>W+8N^IYTyi04u-c@`kXif&bgJAY z*8s zK=K*RaGxI#47}7NtM(pkR{K48!yQ%p>+oW%TwkoI z{#Y+A!ir!GcRPCBruSvL;%B&0eV}FDR@bDNceI(;SigSCnO;NiFIbI$KHg%3+L~uN annzS3M4$#O)TJSW85B!5*503854N%HiL-0;T3rcU^Z-3n zG)IlVZaT0tJHt2MZ_fGrdj9}$hPI6i;YcfA1!^K4`5MUQG*q#3=_{Se$>^tH!y;6k z#EWnu5l@|w)=CqqiPWKpJgF0&dbqhF&@G`nRB@7uIQ2v{mpNvcLxlWA7>DVAknMCm zf;D7n0a-EZH`$q;&2PSMcHci<-vFGUVUb6h@x65Ab08m66-Vw^igYpgDs5PV@`HF1 zZYZL;JJCAUgi0c{5}_}3!aa9aV**_hN~1VRQW2%T2v;)4PG%7yf1x6k4hh*_-zQij z_H>ZNei04|?BJl`d35IP(6Tdq8OPyzjZEsaDZ^ z(D#jN!?@N6_EIK^m~Y(vpaf?cuXG?Um6@mZ^IuL4k1qH{=7s1WhdgJSs|@ydb3Y0k zi+pp=nK6!H9OC+B%r4xUoQZbF?Z2U7R!6DQh z#Ix{Yk<9(EG1?I7sWeK&p)@HUySo|@=$cR+>LkrXl7%8($O6OcLxkdmN>nx=B%BNoG_s z?{`BBZdq`XQ?p%TQ$%nldSN1YscaZ;0V}Px*gIKb_pgJ;@V%9Tw^n^S PupS=oSol7l&f(w-6n|%| diff --git a/代码/robocode/robocode.api/target/classes/robocode/exception/EventInterruptedException.class b/代码/robocode/robocode.api/target/classes/robocode/exception/EventInterruptedException.class deleted file mode 100644 index 0feed93cec7fc6d3a8a10a79b39570d64b8d1826..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 560 zcmb7A%T5A85Ul1Q%0mzYAE=2p*cdnQs_~+jV2B}6xi2u$F}Op9!RXBo@?xSf@!$ve zQO06HZyuaO_w=KxtNZio{R6-rHdBZRcC6`|p6M%J-S^bcX%qU5I~BTS=#;hNp;P_F zPbGzfAb%6w1^yriul$C!#tI4}Wpyy}+MOH- z+teDT<`~wI#2lkk6wNck1){%jzZ@%zjM~h{=nLK(@?Np{ijr5Qd5${Ev_&LnOSDU5 zSVkUYRG6tuaah4BBQiw%ye-x^d&=(93u{U51*Io`Vgw_S1;QpY*=fU!Mo^8qHogIl CdvNyv diff --git a/代码/robocode/robocode.api/target/classes/robocode/exception/RobotException.class b/代码/robocode/robocode.api/target/classes/robocode/exception/RobotException.class deleted file mode 100644 index 368ae2889a1cd0f089dc7383c08856dab4f99619..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 507 zcmah_!A=4(5Pbs+m<0q`LFGog048ptM+_IlM6>ZAy7#g+ShH?TcQO8!ClU{SfFEU? z0>-EZn{=i#ee>RH-#=d8034xRLXOZeda5IRD}DJK$;V9T#J}QJHvTG0a0s<~@g)3M zBr|_(j5dUNDvc6xC{4;UH|M7Wx*$|XI!QB;WTA-XvcO7q5utdZ5|s@J`ED;HI3w0{ zk;i5QF3PMBs6<}QAEwe=i)kzgjX*~%AXtX$b<@f2R7%(n{`EZ|G`qpK?@4AaNuIGXc)~v1RF2=v*iNu3Hz#nCt z0!E_;n{=i#ee>RH-#=d8034xJK!&hy&BRR2tqkPzR6eH4=-@`_(N|G`N7%X-Pa=qg zo&_UojU`kPX_bg0X%n8fK0hVU1))4NI!T32BN5MKj&7qnQ}g=KY!!UQKAighkF-V$RW?Uz*Pntym=Z$jwS9Kb0*HY z-U8*9C1i`E&oH0{4|P=dR9b;h<(?yDa~vJPfRPTH?;R|#{hOi5;yX)*<_fiDU_6?9 Li$c&UdLYGO3=E76%s|sYfRTX}NHQ_70RU~S B9C`o% diff --git a/代码/robocode/robocode.api/target/classes/robocode/robocodeGL/EllipseGL.class b/代码/robocode/robocode.api/target/classes/robocode/robocodeGL/EllipseGL.class deleted file mode 100644 index c62660d759b26b91f7ea15fe46297423726dd3c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1490 zcma)5TTc@~6#k~PlwJe`MG3_jK91JL@g@xdBU-j;T3SC?J0ELQzdCO(|V@~XWt{+rQU#cmw!hAfdkZ~#Ys0TH3ro&obpHgw2q1cEr$+E%8 zNP*+Jx<%XNW05rdAv&vL1pzR$3XA19mod;($O$y(5jws{8&oZsG@mw{@1#z)0=sJf z+U~A#Q@3j8Ub8A?iMA^?Vi|>Oo9$uXccrwfmrn@8fD1kkE zPk=ll-XYgCPZjQpdurRE^DfJW z%@WOFJ_5YXNHnFez^GTZ$S7?{ZbT%XxaTL4tQeA4MonMgRY|1oCYE{*=yjgX`HBtP zHApJ%RD3Lj5oe-J#v+61J5%U8<7W{$<7G$AmT@O?_KaQP{{lhL5G?U71a?Ru8s)lH zaCZd4RK+!xCO{N$&p;HhdKtvp1c(x6CMxb@ErNJSopOB_jI0}o)t<`{Bk@ToJh&We zV*;3rSl-ayh^M%(<6)#sMm%;tn-k1!pv+c9LF+vZG|+z$gb{5-Y|M(^`TMD7$G OU7_>I*v@T(|M)*X;E`p!4pX+ zqlrwl$%|q+d(v~liC8K6N7|4;JmYQeC)DOD%f%3!ELnxEUVnSqL7My z$}R3cGsmIJZHqq!w#4UD+1i|4vM;f(oW8?(Q_1K7nLXFQ4qn%wVV we~r1|y1~$2MC%uV)(HM$f$(rpC>gLfOD(VUx}fgc5Pjn&bv_C$Ewr?ylt7UJLReJgRK%qvxmX+sYT@W4tJKJ~CD)HVJI}0xa_xyR5c}s@^w|&e{eVnTo0y!r5Lf~BOE8^l_m`uwBHKNmS zn4Phyw&m0#CW<4?9wkwd3f9{Gr{Hto1(%s;j}Fy927;B@1f_;)aA`TC=)lsterFsH zEXNr|N}9N4`U z3-{{N@2GtvaM0kYX>ZZW2F$hMWj7d zu}YNJtr5A*-=3QESfM5|+ue4_K&A%#Q3?aW#DKp_VZaA34DMjPxW!9~Ya4$V>{x?! zK8apCzrLakYaqCb&60$zn(cA-8i_4zlgi%|JO7esT_bTHyH?_Xovn`JnTk(ng9R* diff --git a/代码/robocode/robocode.api/target/classes/robocode/robocodeGL/PointGL.class b/代码/robocode/robocode.api/target/classes/robocode/robocodeGL/PointGL.class deleted file mode 100644 index 4f9bbd156fe00ccb9732a54f192e26b5ae9665e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 900 zcma)4%}x_h7(L&#WuUEsfECdyRTkA4Co#Cf=z`jACWeS1vYbwD>NUgMWI7e_p-5br zxZnYNDC4=8L7Ju|F7Ee#&i6C(`_Hcn0I#s^!xKEnOy9(2pn@x-7Y6%Ar+F{*Q5LkW z;*$j*RXR}F`$Qe9G#4zq(W%bg3QFx~hl27R`Kl;ksg4R31k0gL)rawMUuB=7exd}c zp^2m9Fv_&`i(onbqDO*eIICqb)2_fDsr*2HCri2Ab^S)pldhn~+`bvSYJuscp;$LS3dOFESy!+{xRvFd7jlX|h@ON&MeY{L%)__TONN}papE!36g zKe70OhKDMpO#|zwQPwXDsBh5|+{QAc1;6I=Y-}3XaKOf8vH)7>3hq$0u!^;U;vM0Y zSri+NV#^K9Wn6Ddv5vcx)@slyQQyM`<&E=f&Y9;vHVNf#i-!fp3+HpK+Bus{9-}#N h4Da7Dn*V`p%|t%JGj7ird&_-J!4o&))4wh`g1P_z diff --git a/代码/robocode/robocode.api/target/classes/robocode/robocodeGL/RectangleGL.class b/代码/robocode/robocode.api/target/classes/robocode/robocodeGL/RectangleGL.class deleted file mode 100644 index b03b095c1cef74a71cfb0b9ff54e92183a1dc8df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1497 zcma)5OK;Oa5T4DWZXVFkLJ6g`X(`2hP)n$sfeiRZX zBo6!leiY)HwbKMQQ5z}V*`1m1F>C+%`|CFmJ*GX4a)MT)up8Q;BaLCuHjOvZj;+A; zW!u!KAZTrv`@bk~Wc1RPr!t5I%{=u2FMcK{uWua*DjWc_OnE9*sYo+|=1eb;uluK6 z8NIc-z7#ZXhPLG&S&_&4^so^3yfZMGlPS-2H3ezF0`*@9}>jG&SasmBRS=}g8i!hYaDR24D1NK*w}fz0Am zVG3H%vtX>QXfq>VQP}c)Upg3%e!{7l59wZ<2&ynVMiP5rfG)`95)G#v?;GY-a3X7< zNL+tk*=d`teqcAbEa&>{C6f_UcF`V3Uf{k{SJN6ldXG&f>_@hQE-=)_E`E<0XpPW? z*M+Ex2p5T`hMj>`U@dO{q}d+`a#Y5X(?p9@!IK+Mfb|+yZoZBuHy>jyac)v`T{Z8c zeALX*9Mw|58;Dp_k>(L4bqk0zMRGGG`GmDPjburYyi#h03a?7Sb+_PAIiTAhE`zFm z?ydt;&WY?;mdBj2HXaKPX6Q`N&>6ms)ETZjb#{lAQfE)l#r`i4tSEv-+y%pq2v{Ru z*Iim3gHTmjjg2V~_h6VIR%rDyi1jHD4fQe!TBrLd#B=E6>$_lNLqRkWmt#hf3T*Uw>?n-n^T?&{ Q1npd*)0o(~tMDKF1Le!N=>Px# diff --git a/代码/robocode/robocode.api/target/classes/robocode/robocodeGL/RenderElement.class b/代码/robocode/robocode.api/target/classes/robocode/robocodeGL/RenderElement.class deleted file mode 100644 index 793dca0d74a5cbc28799e076698d17548587664b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1077 zcmah|%Wl&^6g}g-+N97Ilv3JK(=HNTmJqCp*dUUP1yYM5%5H2At}DluT&Mh0RjI2= zEcgIE3UOxQh9o3pF*Ck%?m73|JMypJKYjvug@YO_0Xs{*)K3HD+TlhFC(ohd&TC`U=eW4-By@oNKj+;*DehpjHb_mmV^cB4dn?DssC zeU@I#n>9D}W!#lnq~qeU6vp3JV^T<<`c@ZtCs1m(x^ z@gVF_sG)u3j-;0oO2>f;(i1}7v<8I2DHk%3N41V3N`!_JD0w*HXjmf#YMn`jby@;uOcH@=Q}pznxn9wpBY0Y=i-Vk~oHvn960?i7`0c5*Nn z^>3h!8e@G%V7tOm6{~1)MvF~m>#y<(x|^c;#Qt}EC(~;VVGXUh>L_Dz?svPbjNZwL Q(!8CPwz1Ag*vN#PPhbFn2mk;8 diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IAdvancedEvents.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IAdvancedEvents.class deleted file mode 100644 index 95d66c9ccd301a20f6c0adcf640dbdd1afeb2b7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 245 zcmZ9Hy$ZrW5QJyrPc$M}*w|Rd#(=Grh=L$kMC>n@RTAS}NG^Fe3m?FT5|b1X?3S6G z;hXp8`2w)Q$c9C5GaYEDL-y*!M9Oe>6_RuBun9|{B!|0_mC0>%36ofq!b^m@d8Z&| zX$WJj{Ckw99G;6z5$5jkSJ^U}lJ(-!1hz$P^rMjovsR#GG{26oi%jx9N|-SHBU;ul ZeFC9V4FaqRu!lZsP#c3vAq;CB&KJk(MB4xW diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IAdvancedRobot.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IAdvancedRobot.class deleted file mode 100644 index 25e6131ef1762d67e6759343da495a9ccc5ffcc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 260 zcmX^0Z`VEs1_mPrZgvJHMh5kw{G|Nk{FGFE5ThhBuOzi7EipN@Sl`nzr7SToIW;8+ zB*D(W!pIUWb*CQ4i9km&GB5)%E6}Hm SK!>w4aDZ40oIsL^feQeLRZV;V diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicEvents.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicEvents.class deleted file mode 100644 index ec7ee74d1efeb90f347ccf794f5c711ef39f97ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 711 zcmZva%}N6?6opT!?eyP{Keer`1wqh_18&_F6$M4GVAtt1>XadYPFnEQT=)P!l$g2G zHYvKv3Fm(2k{j;#&*v9_OY}VC7*1zutU@&rL3+`V)MEC^Ly-jc1D-_T%|b|>c-UrW zO!B zC&SSuO|C^tgpPO|Gjuk|)U==(ZWwYY#bnvn9nP)TNL5K`gfeLbRni*jq&sMk`q(Ai X!#?Q&nxuzlk+#t>oy~umGl%Xk&FjYD diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicEvents2.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicEvents2.class deleted file mode 100644 index c1b011943af9d8fa0fd2ec5228523e7dd67ee4a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 234 zcmX^0Z`VEs1_mPrZgvJHMh3N_{G|Nk{FGFE5ThhBuOzi7EipN@Sl`nru{bl?wJbHS zq}Yg^frXJlASQy3ZK zG<@JXktDztT5EOyS* diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicEvents3.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicEvents3.class deleted file mode 100644 index 571c2dc5105870929ded177745ef4c278347b180..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 233 zcmX^0Z`VEs1_mPrZgvJHMh3N_{G|Nk{FGFE5ThhBuOzi7EipN@Sl`nru{bl?wJbHS zq}Z69frXJlAS+X911FGV HV&DP*>CHj- diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicRobot.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IBasicRobot.class deleted file mode 100644 index c4085310f598072989b9d9155114b00d5f147cf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 371 zcmah_O=|)%6r5PQ+uAQL7JonwyO##MdMi{Y2#SLDZ2FXlO-hpW$Mw)3&>vNNiIjRN zy}b7rW*#&1_5JY)V1&C89f1e$8mHYW$#g_xBl)$`6y(d33PvvyTB0k^->SWmJ7qU= z)@(^fhBg#4VbNNvnjHz;SM~Il_=ArH2F%SLpZ8?r)PzWuyg`MG;2&k6IH#l< zRey`#nQ`hqDaQ3mpkVo|W#7Z<=+QVi_Z)c{J*l_M=`CIBHBC$k(?99pF{LU51kSiV cpv#qFq(E{F>k5E7Pp4L} zR4$(N?#yVs{#ty_0rapNpu%vHsgaUuOxzYaPBmrELQ>8L16vEJoS?Kt9HbFxBirq1E)_>rOM*msnWaP-jKA7*b> z+fwOJO>;U=V)<$t2PQ#ny)L=Iqc--)~iO}`y Z9vdE;9$OyU9y=bp*fP!x+vcob=NsZwhsgi{ diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IInteractiveRobot.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IInteractiveRobot.class deleted file mode 100644 index 837601262870db6bf176e66205ed2abd0798b5a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 272 zcmZ{fy$ZrW5QJy_i^j&v#@0eDJg~JB6aoQ3pWt$?;X=4T?##nk_y9hXcxNR_id}|X z=40mhx<3GHFpkh6tm-PORCQqygww`xeU*x>NRptXa=PJD_(kXuCWUOID5c58F)LX4 z>wqwCr|hKF>f1&?OV5e}UH_t4~Mh S`sw@Di1yd*h diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IJuniorRobot.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IJuniorRobot.class deleted file mode 100644 index f3e4d181285c495de0a4e748c3a0adfad6f50e59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 174 zcmX^0Z`VEs1_mPrPId++Mh4ZQ{G|Nk{FGFE5ThhBuOzi7EipN@Sl`pDG%qv1C0N!WKh9vfKy^|W-?emBLi1(erZv1s#|7GDkFm+ cve|kdV}S-SGB5)%E6{BWK$;y$GBI!f0QoI3ng9R* diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IPaintEvents.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IPaintEvents.class deleted file mode 100644 index 5b949df4420257ec47374442639dc59f37294fac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 175 zcmYjLI|{-;6r2||t5({10UfASej-oAs#)VOKV5yqkpw@KE9=mCZ1Z`Mmjj zUvB^@1_BXb>TG7UJ+o|x&y8nyQJO2cJ*aT4YBs(S=n_VSs+BC2xypT3u=WIDP3s~| zl3gpSr2fhU5r#+maGKY7$%OHL?YxP^1VSfF0w{dxA#NB%zzF>xhR`lh diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IPaintRobot.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/IPaintRobot.class deleted file mode 100644 index 1942dc44ec778d9df508166b2ca35e70b4131c61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248 zcmX^0Z`VEs1_mPrZgvJHMh2Cl{G|Nk{FGFE5ThhBuOzi7EipN@Sl=@s5y%SyiLx`W zFfs^aC6*=X=OpH(>-#5Vr6vPK+3@OjN-WMy2J2^J5KT`l0h{MqmYP@MlUZDnnwMI{ z$e^jA=|jK;U>(KQj0{}C`K3k4scxA$sX*5tIZqGdGN4-+8JK~X73e!gpnKUFI6y20 KP9Vv|zy$zTmPrTz diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/ITeamEvents.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/ITeamEvents.class deleted file mode 100644 index 17ba440b43f8533e4cf8319eaf709549f1c1bab7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 185 zcmYk0u?oU47=-Vy+NhJR&JJ}k;OeX(D1wT6n*NrSnm`l#a1K6z4<)7|;&Oa&@ZCLM z_XmIl1_BXbTHDlWo3U)c7shjaQJS6HoLF5~4IA$Sx`a`w8YL@ba=A}S)}Ao7X2;H{ zoDZzIXgDKGlI>6VEkBaw>`WLQ?XA|lE-DVfzlC`#j|qfMI0sM|>>+LmB4mXA8!WXl AumAu6 diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/ITeamRobot.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/ITeamRobot.class deleted file mode 100644 index d244175154a0fb0cc7ee212e772d9df6fb8fca77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 247 zcmX^0Z`VEs1_mPrZgvJHMh4}g{G|Nk{FGFE5ThhBuOzi7EipN@Sl=@wH8D2`B*@Od z!pI;W#*(ZGVmjurw4Kw&@GG%%s|Wv^c*A5 Rz3dDeAQl5BkYr-u0s!c5NM`^5 diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/package-info.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/package-info.class deleted file mode 100644 index cb041d781e029c5d7a97bcb216dbe21fa6409a7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmX^0Z`VEs1_mPrc6J6PMh4ZQ{G|Nk{FGFE5ThhBuOzi7EipN@Sic}KIXf{uRW~y) zEuWo%g^@uZE3qt5KPNFSUEe<`D>b=hTSm^wd_!{vr%5n3m?FT zvh3;1CJUhwFH)Vq=kITNXLtI~-(SB0U=22NaLIvHB@d-91MZnWT11+wZ_MYhcfz^y zDy5*oBA*9Uv$}_=9P~MmKVl8$g)FLjpAL_>uXAv;*u6fo6hIWQ&SQgD>S`dt$3 zNVO${(=UmN9JuTj4jhct9`*E_tE z7kCR5Y>x%OHXg7%Cb$EmiXY>npUDmTA!n)-hUAIyp>czZ9CHiJP7*CbZ&$>+h{swJ z^@!<2Ve|7HhK=^46STOAB_oK%uRtepy3sCWvlrN?GbbX`2a= zZz8_3_E)jkgV6F4U>pI&EOVy6r(LXcW1O=S#=P{J&!Wfax18Qp1|Vjpmv)MTQ3 z-sDYpj?@)%$#H(-bi&^ioX)d2V{>o~%&hIValpnw7^3`j7^XM^d5WVpj@dYFgVu+`hN+pD87aw_Uga}b^PWZ1)}KF diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/IBasicRobotPeer.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/IBasicRobotPeer.class deleted file mode 100644 index 25be59d69b328b718ca540c0d5a90d1f2a6c34d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1167 zcmZXT+foxj5Qcj(5+EFcfOy6uBr2@p>4LiuIam}>359w&*=;sMZFZ>1EE*rp3m?FT zvh1F1qTVUYE8#PCdQB#PG=77iHfivo*~+Bx1stv zYVp<~*<~mNP(4-WDojgN6JV`Djv`n7G zWOA~8O1F(iQO>te!;h)2J#$V*sn%p`%u#IaDE%2;Qe4_Q(U!9!m%ZUs zH1ae>$A7SoZp%AN(u&V+n$%dTw^sac^~Hr=+Ta^1a43H>iOcuobk06@_LgJtx~8acJk!VnlrRKKP!@=pIMp7 z|EHAG9<|t~Gy<4to7_e;FDbX=(lc1&2_FrBnoCa!V3}UURTu?+9c38v9ESx^)+ldgnZ4&!iMBwm zR&Po!m3@)ZMNK-EC6HX_2Km{E$=jLY*;z5l zseYh%Yw8r@U9w~6ht9k|uu9-;!!#AlvEr9H-=hA?x^tJjrg638vHfkYSJ@^T<3I7) i<+T-TzQi8#5<2KMxQ~Md57+slH6CZ=x*p#xocsW!0c0Tn diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/ITeamRobotPeer.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/ITeamRobotPeer.class deleted file mode 100644 index 4dfc1b65f019ee942f7ad6c3d96c5d2f528306ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 582 zcmah`+fD*85S=Qxa#0b)%O9}8xW-qEi4T~NU@)%nL7%$aaZ|E%Nn42V(|qs){3zoT zaJ@j{Lo?HvGiNU6{p0lw0M6jhgEa=nI*T%q#TYopN@Y<$ae*cnBkG`chkSJFGB@<~ zpunIuyKs+8TLY=P{y X(-wCBMC#C>$R1(Vph@2T%sco5Q=g%u diff --git a/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/package-info.class b/代码/robocode/robocode.api/target/classes/robocode/robotinterfaces/peer/package-info.class deleted file mode 100644 index a0bd3ec9665aaf4e527d7087d5374d96d7603ccd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135 zcmX^0Z`VEs1_mPrc6J6PMh2~-{G|Nk{FGFE5ThhBuOzi7EipN@Sic}OwMf4pF*!Ri zJyka|FD;*)frXJlAS>KK4FAq*@f0%qVPyb?Pi>Ua2@0tBcY1qdNOsUnaq^& zI1&;PNC+q(@sN-J!9JTxEek}%0(IRbJ9bF$53mCvA_p3?YUij@`92dtEONT*EBCOpksH5r*mOe4Cd|ZuQD5-RrvMGDz)LR#snn zfq|(EsU_R$yWDa++#Kjq^_cQkTRl6=kZC{Ps@G}V>Pn~HTBRJRdiduz-+EH{i6If3 zzVPQLM{d?@tyQ(&XxF60-~RaS=C2#Slizv6GTcRmaIw^3h%8Z=GQyZi;s~+~hZ=^Z zHwRl?-D&f#sWTjI*cvxG+%ZJ#Pe$Agqt9@(F#&afcEGZoEpFDjecK$kdd=zyrASdN z5oMJ4MVPwca&7Z6zu{{hpOB>LJxAC3Qg!=n+F)QT-O^3&8rwr@sTvxZtJ1b;zi{#f6^3|EcU#U%iz6;%meTJD3u&cALJ0v8Q$>pq9gF@(>PW zjnK3jCgF!C3M>B-Rt^Zy|DW(9W8qD|;!2?685-xm{Kl*Nq?qsRAWQGUf6`nGm{tNb zaYSd;a46vs6(<^xh=g$|V66DYj|Pkn(l#H&`0UvDo=?0+W+UTKj}+~aC}9`pzCw%! zxBY@n6w=;YG%aQ--dLf5h~`GC=R~B8*X?zCo(>?eh8()oQVn^m<1y%%!!^vKhblIp zViQf6XkiOiVc|8r9>7`)?5B(vosM)Sl}gYNnV-mY@aze${HW5rs8n=#Ki80vxID_l zXmvuYp1LpBJH+)aalJ=e?-SQe;`)H<`jEIjBCd~#>l5Pol(;@4uFoHci+*7KooZ6Q zBD8;*Lb11tr?SXU;nB#g@GY7QUZ)*TIOko!49KjY8hV3WFV@J)<9subua9 aGW|q$QN2TQp}_6D?H+6Z diff --git a/代码/robocode/robocode.content/target/classes/ReadMe.html b/代码/robocode/robocode.content/target/classes/ReadMe.html deleted file mode 100644 index 347ead6..0000000 --- a/代码/robocode/robocode.content/target/classes/ReadMe.html +++ /dev/null @@ -1,233 +0,0 @@ - - - - - - - - - - -

ReadMe for Robocode

-

Updated 06-Mar-2013 by Flemming N. Larsen

-

Robocode Home Page: http://robocode.sourceforge.net/

-

TABLE OF CONTENTS

-
    -
  1. What is Robocode?
  2. -
  3. History of Robocode
  4. -
  5. System Requirements
  6. -
  7. Getting Started
  8. -
  9. Robocode API
  10. -
  11. Robocode Repository
  12. -
  13. Community
  14. -
  15. Challenges
  16. -
  17. Competition
  18. -
  19. Command Line
  20. -
  21. Links
  22. -
  23. Reporting Defects
  24. -
  25. Feature Requests
  26. -
  27. Versions
  28. -
  29. News
  30. -
  31. How to contribute
  32. -
-

1. WHAT IS ROBOCODE?

-

Robocode is a programming game where the goal is to code a robot battle tank to compete against other robots in a battle arena. So the name Robocode is a short for "Robot code". The player is the programmer of the robot, who will have no direct influence on the game. Instead, the player must write the AI of the robot telling it how to behave and react on events occurring in the battle arena. Battles are running in real-time and on-screen.

-

The motto of Robocode is: Build the best, destroy the rest!

-

Besides being a programming game, Robocode is used for learning how to program, primarily in the Java language, but other languages like C# and Scala are becoming popular as well.

-

Schools and universities are using Robocode as part of teaching how to program, but also for studying artificial intelligence (AI). The concept of Robocode is easy to understand, and a fun way to learn how to program.

-

Robocode offers complete development environment, and comes with its own installer, built-in robot editor and Java compiler. Robocode only pre-requires that a JVM (Java Virtual Machine) to exist already on the system where Robocode is going to be installed. Hence, everything a robot developer needs to get started is provided with the main Robocode distribution file (robocode-xxx-setup.jar). Robocode also supports developing robots using external IDEs like e.g. Eclipse, IntelliJ IDEA, NetBeans, Visual Studio etc., which supports the developer much better than the robot editor in Robocode.

-

The fact that Robocode runs on the Java platform makes it possible to run it on any operating system with Java pre-installed, meaning that it will be able to run on Windows, Linux, Mac OS, but also UNIX and variants of UNIX. Note that Java 6 or newer must be installed on the system before Robocode is able to run. See the System Requirements for more information.

-

Be aware that many users of Robocode (aka Robocoders) find Robocode to be very fun, but also very addictive. :-)

-

Robocode comes free of charge and is being developed as a spare-time project where no money is involved. The developers of Robocode are developing on Robocode because they think it is fun, and because they improve themselves as developers this way.

-

Robocode is an Open Source project, which means that all sources are open to everybody. In addition, Robocode is provided under the terms of EPL (Eclipse Public License).

-

2. HISTORY OF ROBOCODE

-

The Robocode game was originally started by Mathew A. Nelson as a personal endeavor in late 2000 and became a professional one when he brought it to IBM, in the form of an AlphaWorks download, in July 2001.

-

IBM was interested in Robocode, as they saw an opportunity to promote Robocode as a fun way to get started with learning how to program in Java. IBM wrote lots of articles about Robocode, e.g. like Rock 'em, sock 'em Robocode! from AlphaWorks / developerWorks at IBM, a series of articles like Secrets from the Robocode masters, and "Robocode Rumble / RoboLeague".

-

The inspiration for creating Robocode came from Robot Battle, a programming game written by Brad Schick in 1992, which should still be alive. Robot Battle was, in turn, inspired by RobotWar, an Apple II+ game from the early 1980s.

-

The articles from IBM and the Robocode community behind the RoboWiki made Robocode very popular as programming game, and for many years Robocode has been used for education and research at schools and universities all over the world.

-

In the beginning of 2005, Mathew convinced IBM to release Robocode as Open Source on SourceForge. At this point, the development of Robocode had somewhat stopped. The community around Robocode began to develop their own versions of Robocode with bug fixes and new features, e.g. the OpenSourceRobocode/Contributions and later on the two projects, RobocodeNG and Robocode 2006, by Flemming N. Larsen.

-

Eventually, Flemming took over the Robocode project at SourceForge as administrator and developer in July 2006 to continue the original Robocode game. The RobocodeNG project was dropped, but Robocode 2006 was merged into the official Robocode version 1.1 containing lots of improvements. Since then, lots of new versions of Robocode have been released with more and more features and contributions from the community.

-

In May 2007, the RoboRumble client got built into Robocode. RoboRumble is widely used by the Robocode community for creating up-to-date robot ranking lists for the 1-to-1, Melee, Team, and Twin Dual competitions.

-

Since May 2010 a .NET plugin is provided for Robocode using a .NET / Java bridge, which makes it possible to develop robots for .NET beside developing robots in Java. This part was made by Pavel Savara, who is a major Robocode contributor.

-

3. SYSTEM REQUIREMENTS

-

In order to run Robocode, Java 6 Standard Edition (SE) or a newer version of Java must be installed on your system. Both the Java Runtime Environment (JRE) and the Java Developer Kit (JDK) can be used. Note that the JRE does not include the standard Java compiler (javac), but the JDK does. However, Robocode comes with a built-in compiler (ECJ). Hence, it is sufficient running Robocode on the JRE.

-

Also note that it is important that these environment variables have been set up prior to running Robocode:

-
    -
  • JAVA_HOME must be setup to point at the home directory for Java (JDK or JRE).
    Windows example: JAVA_HOME=C:\Program Files\Java\jdk1.6.0_41
    UNIX, Linux, Mac OS example: JAVA_HOME=/usr/local/jdk1.6.0_41

  • -
  • PATH must include the path to the bin of the Java home directory (JAVA_HOME) that includes java.exe for starting the Java virtual Machine (JVM).
    Windows example: PATH=%PATH%;%JAVA_HOME%
    UNIX, Linux, Mac OS example: PATH=${PATH}:${JAVA_HOME}/bin

  • -
-

You can read more details from here:

- -

If you want to program robots in .NET or control Robocode from a .NET application, you need to install the Robocode .NET API plug-in on top of Robocode. The plug-in is installed by double-clicking the robocode.dotnet-xxx-setup.jar the same way as Robocode itself is installed.

-

4. GETTING STARTED

-

Most documentation about Robocode is provided thru the RoboWiki, which contains the official documentation about Robocode, but which also hosts the community around Robocode. It is highly recommended to read the articles on the RoboWiki for getting started with Robocode. These articles are provided from here:

- -

You should read about the anatomy of a robot, the game physics, scoring etc.

-

To learn more about developing robots for .NET, these articles are a good starting point:

- -

5. ROBOCODE API

-

The Robocode API is provided as HTML pages for both the Java and .NET platform.

- -

The Robocode API actually consists of 3 different APIs.

-
    -
  • Robot API: Within the Java package robocode and .NET namespace Robocode.
    The Robot API is used for developing robots, and is the only part of the API that robots are allowed to access.

  • -
  • Robot Interfaces: Within the Java package robocode.robotinterfaces and .NET namespace Robocode.RobotInterfaces.
    The Robot Interfaces are used for developing new robot types with a different API that the standard Robot API.
    Note: The game rules and robot behaviors cannot be changed.

  • -
  • Control API: Within the Java package robocode.control and .NET namespace Robocode.Control.
    The Control API is used for letting another application start up battles with selected robots in Robocode and retrieve the results. It is also possible to get snapshots of robots and bullets (like position, heading, energy level etc.) at a specific time in a battle.

  • -
-

6. ROBOCODE REPOSITORY

-

If you want to try out new robots than the sample robots that come with Robocode, you should visit the Robocode Repository.

-

Robots are available under the Bots section of the repository.

-

The Robocode Repository is developed and maintained by David Lynn as a project independently of the Robocode project.

-

7. COMMUNITY

-

The community around Robocode is using the RoboWiki as communication channel. At the RoboWiki, people share new ideas, code snippets, algorithms, strategies, and lots of other stuff about Robocode. New official documentation from the developers of Robocode will be put at the RoboWiki as well.

-

On the RoboWiki, these strategies are provided:

- -

The code snippets are also provided on the RoboWiki:

- -

8. CHALLENGES

-

A good way to improve you self as a robot developer is to try out some real challenges. On the RoboWiki, two famous challenges exist for testing/studying a robots movement, targeting, and gun abilities:

- -

9. COMPETITION

-

If you want to challenge your robot(s) and yourself as robot developer, the RoboRumble@Home is the best way to do it. RoboRumble is the ultimate collaborative effort to have a live, up-to-date ranking of Robocode bots. It uses the power of available Robocoders' computers to distribute the effort of running battles and building the rankings.

-

RoboRumble is actually 3 different rumbles:

-
    -
  • RoboRumble (aka 1v1): One robot versus another robot - both picked at random. These two robots a alone on the battle field.
  • -
  • MeleeRumble: Ten robots picked at random all battle against each other..
  • -
  • TeamRumble: One team versus another team - both picked at random. Each team consists of five or less robots.
  • -
-

In order to get started with RoboRumble, you should read this page:

- -

Note that the RoboRumble@Home client is built into Robocode and can be started using the batch/shell/command files:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WindowsUNIX / LinuxMac OS
RoboRumbleroborumble.batroborumble.shroborumble.command
MeleeRumblemeleerumble.batmeleerumble.shmeleerumble.command
TeamRumbleteamrumble.batteamrumble.shteamrumble.command
-

Two other competitions exists which are:

-
    -
  • Twin Duel: Two teams battle on an 800x800 field. Each team consists of two robots (twins).
  • -
  • Hat League: Two teams not knowing each other are paired together at random (like drawing names from a hat). Each team consists of two robots. These two teams must work together and defeat two other teams that have also been picked at random.
  • -
-

10. COMMAND LINE

-

It is possible to specify options and predefined properties from the command-line when running Robocode. The usage of these can be listed by writing this from a command prompt or shell:

-
robocode -help
-

For example, it is possible to:

-
    -
  • disable the graphical user interface (GUI).
  • -
  • disable security that is specific to Robocode (but does not override the security that comes with the JVM).
  • -
  • enable/disable the debugging mode, useful when debugging robots.
  • -
  • play a battle based on an existing Robocode .battle file.
  • -
  • replay a recorded battle visually.
  • -
  • save the results of battles in a comma-separated file.
  • -
-

You can read more details here:

- - -

Links relevant to Robocode are provided on the home page of Robocode:

- -

Other links are provided from the RoboWiki - especially for challenges and competitions:

- -

The is also a Wikipedia page available about Robocode, which provides good links to movement and targeting strategies, competitions, and other sites about Robocode:

- -

12. REPORTING DEFECTS

-

If you discover a defect (bug) in Robocode you are encouraged to report the issue as soon as you discover it - the sooner the better.

-

A bug report should be reported on the Bugs page on the SourceForge site for Robocode. Each bug report will be prioritized among other bug reports depending on its impact on the game.

-

It will be a great help if you describe how to see or which steps to do in order to reproduce the defect. You are very welcome to provide a screen shot, source code or anything else that will show the bug. It is also a very good idea to write which system and version of Robocode and Java you are using.

-

If you are a registered user at SourceForge (register here) you will be able to add a "monitor" on your bug report. This way you will be able to receive notifications when someone add comments to your report, but will also be able to better track the current status of the bug, e.g. when the bug is fixed and with which version of Robocode the fix is available.

-

If you are a developer yourself, and have a good idea of how the bug could be fixed, you are more than welcome to do so. By fixing the bug, you will become a contributor of Robocode yourself. You can learn more about how to contribute here. Note that we accept bug fixes under the terms of EPL.

-

13. FEATURE REQUESTS

-

If you got an idea for a new feature or improvement for Robocode, you are very welcome to share your idea by summiting a feature request.

-

A feature request should be put on the Feature Requests on the SourceForge site for Robocode. Each feature request will be prioritized among other feature requests.

-

It will be a great help if you describe your idea in detail, and how you think it could be implemented into Robocode. For example, will it be possible to extend an existing feature with your idea?

-

If you are a registered user at SourceForge (register here) you will be able to add a "monitor" on your request. This way you will be able to receive notifications when someone add comments to your request entry, but will also be able to better track the current status of your entry, e.g. when the feature has been implemented and with which version of Robocode it will be available.

-

If you are a developer yourself, and have a good idea of how the feature could be implemented, you are more than welcome to do so if the feature is being accepted. By implementing the feature, you will become a contributor of Robocode yourself. You can learn more about how to contribute here. Note that we accept implementations under the terms of EPL.

-

14. VERSIONS

-

Robocode is continuously under development, and you should be aware that three different release types exist for Robocode:

-
    -
  • Alpha version is an unofficial "snapshot" version of Robocode that is under development and not feature complete yet. It is normally provided for the person that has put a bug report or feature request on the tracker for Robocode, which needs to be verified. Alpha versions are not meant to be redistributed at all.

  • -
  • Beta version is an official release that is considered feature complete, and which intended for everybody to try out and test regarding all new features and changes, but which is also considered "unstable", and might contain some unwanted side-effects due to the changes made to this version compared to the last final version of Robocode. Defects or undesired behaviors should be reported as soon as they are discovered so the issues can be fixed before the final release. Everybody is encouraged to take part in the testing Beta versions of Robocode.

  • -
  • Final version is (as it says) the final version of a specific and official release of Robocode, and where new features and bug fixes have been tested. Note, that the release will not state "final" on the distribution files for Robocode like it is the case for Alpha and Beta versions.

  • -
-

15. NEWS

-

News about Robocode is put on the blog spot for Robocode. Here it is possible subscribe to a RSS feed to receive news about Robocode.

- -

You can also follow Robocode on Twitter and Facebook here:

- -

The RoboWiki can be followed on Twitter as well:

- -

16. HOW TO CONTRIBUTE

-

If you want to contribute to Robocode with e.g. a new feature or bug fix, you should read the Developers Guide for building Robocode.

-

Note that we accept code changes under the terms of EPL.

-

There exist no or little documentation about the internals of Robocode, and the code base will need to be examined by a contributor in order to get an insight of how Robocode is implemented. Thus, it required a skilled Java developer to figure out how Robocode is put together.

-

Robocode is divided into several modules. You can read Pavel Savara's blog to get a good overview of Robocode here:

- -

Help for Robocode internals can be provided through the Robocode Developers Discussion Group where you can register yourself, and start up a new topic. This is the best way of getting information and asking about details for the internals in Robocode.

-

If a contribution is a somewhat small change to involves under 10 files, then the preferred way is to provide the contribution as a patch file that can be applied to the existing Robocode sources. Otherwise, you can be granted a Subversion branch for your work, where you can commit your changes. Later, this branch needs to be merged into the trunk be the administrators of Robocode and tested carefully. Additional work might be done by other Robocode developers to finalize the work.

- - diff --git a/代码/robocode/robocode.content/target/classes/ReadMe.txt b/代码/robocode/robocode.content/target/classes/ReadMe.txt deleted file mode 100644 index 1fe94cc..0000000 --- a/代码/robocode/robocode.content/target/classes/ReadMe.txt +++ /dev/null @@ -1,471 +0,0 @@ -## ReadMe for Robocode - -Updated 06-Mar-2013 by Flemming N. Larsen - -Robocode Home Page: -[http://robocode.sourceforge.net/](http://robocode.sourceforge.net/) - -### TABLE OF CONTENTS - -1. [What is Robocode?](#what-is-robocode) -2. [History of Robocode](#history-of-robocode) -3. [System Requirements](#system-requirements) -4. [Getting Started](#getting-started) -5. [Robocode API](#robocode-api) -6. [Robocode Repository](#robocode-repository) -7. [Community](#community) -8. [Challenges](#challenges) -9. [Competition](#competition) -10. [Command Line](#command-line) -11. [Links](#links) -12. [Reporting Defects](#reporting-defects) -13. [Feature Requests](#feature-requests) -14. [Versions](#versions) -15. [News](#news) -16. [How to contribute](#how-to-contribute) - -### 1. WHAT IS ROBOCODE? - -Robocode is a programming game where the goal is to code a robot battle -tank to compete against other robots in a battle arena. So the name -Robocode is a short for "Robot code". The player is the programmer of -the robot, who will have no direct influence on the game. Instead, the -player must write the AI of the robot telling it how to behave and -react on events occurring in the battle arena. Battles are running in -real-time and on-screen. - -**The motto of Robocode is: Build the best, destroy the rest!** - -Besides being a programming game, Robocode is used for learning how to -program, primarily in the Java language, but other languages like C# -and Scala are becoming popular as well. - -Schools and universities are using Robocode as part of teaching how to -program, but also for studying artificial intelligence (AI). The -concept of Robocode is easy to understand, and a fun way to learn how -to program. - -Robocode offers complete development environment, and comes with its -own installer, built-in robot editor and Java compiler. Robocode only -pre-requires that a JVM (Java Virtual Machine) to exist already on the -system where Robocode is going to be installed. Hence, everything a -robot developer needs to get started is provided with the main Robocode -distribution file (`robocode-xxx-setup.jar`). Robocode also supports -developing robots using external IDEs like e.g. -[Eclipse](http://www.eclipse.org/downloads/), -[IntelliJ IDEA](http://www.jetbrains.com/idea/), -[NetBeans](http://netbeans.org/), -[Visual Studio](http://msdn.microsoft.com/en-gb/vstudio/) etc., which -supports the developer much better than the robot editor in Robocode. - -The fact that Robocode runs on the Java platform makes it possible to -run it on any operating system with Java pre-installed, meaning that it -will be able to run on Windows, Linux, Mac OS, but also UNIX and -variants of UNIX. Note that Java 6 or newer must be installed on the -system before Robocode is able to run. See the [System -Requirements](#system-requirements) for more information. - -Be aware that many users of Robocode (aka Robocoders) find Robocode to -be very fun, but also very addictive. :-) - -Robocode comes free of charge and is being developed as a spare-time -project where no money is involved. The developers of Robocode are -developing on Robocode because they think it is fun, and because they -improve themselves as developers this way. - -Robocode is an Open Source project, which means that all sources are -open to everybody. In addition, Robocode is provided under the terms of -[EPL](http://www.eclipse.org/legal/epl-v10.html) (Eclipse Public -License). - -### 2. HISTORY OF ROBOCODE - -The Robocode game was originally started by **Mathew A. Nelson** as a -personal endeavor in late 2000 and became a professional one when he -brought it to IBM, in the form of an AlphaWorks download, in July 2001. - -IBM was interested in Robocode, as they saw an opportunity to promote -Robocode as a fun way to get started with learning how to program in -Java. IBM wrote lots of articles about Robocode, e.g. like -[Rock 'em, sock 'em Robocode!](http://www.ibm.com/developerworks/java/library/j-robocode/) -from AlphaWorks / developerWorks at IBM, a series of articles like -[Secrets from the Robocode masters](http://www.ibm.com/developerworks/java/library/j-robotips/), -and "Robocode Rumble / RoboLeague". - -The inspiration for creating Robocode came from -[Robot Battle](http://www.robotbattle.com/history.php), a programming -game written by Brad Schick in 1992, which should still be alive. Robot -Battle was, in turn, inspired by -[RobotWar](http://www.robotbattle.com/history.php), an Apple II+ game -from the early 1980s. - -The articles from IBM and the Robocode community behind the RoboWiki made -Robocode very popular as programming game, and for many years Robocode has been -used for education and research at schools and universities all over the world. - -In the beginning of 2005, Mathew convinced IBM to release Robocode as -**Open Source** on SourceForge. At this point, the development of Robocode had -somewhat stopped. The community around Robocode began to develop their own -versions of Robocode with bug fixes and new features, e.g. the -[OpenSourceRobocode/Contributions](http://old.robowiki.net/robowiki?OpenSourceRobocode/Contributions) -and later on the two projects, -[RobocodeNG and Robocode 2006](http://old.robowiki.net/robowiki?RobocodeNG/Archive), by **Flemming N. Larsen**. - -Eventually, Flemming took over the Robocode project at SourceForge as -administrator and developer in July 2006 to continue the original Robocode game. -The RobocodeNG project was dropped, but Robocode 2006 was merged into the -official Robocode version 1.1 containing lots of improvements. Since then, -lots of new versions of Robocode have been released with more and more features -and contributions from the community. - -In May 2007, the [RoboRumble](http://robowiki.net/wiki/RoboRumble) client got -built into Robocode. RoboRumble is widely used by the Robocode community for -creating up-to-date robot ranking lists for the 1-to-1, Melee, Team, and -Twin Dual competitions. - -Since May 2010 a **.NET plugin** is provided for Robocode using a .NET / Java -bridge, which makes it possible to develop robots for .NET beside developing -robots in Java. This part was made by **Pavel Savara**, who is a major Robocode -contributor. - -### 3. SYSTEM REQUIREMENTS - -In order to run Robocode, Java 6 Standard Edition (SE) or a newer -version of Java must be installed on your system. Both the Java Runtime -Environment (JRE) and the Java Developer Kit (JDK) can be used. Note -that the JRE does not include the standard Java compiler (javac), but -the JDK does. However, Robocode comes with a built-in compiler (ECJ). -Hence, it is sufficient running Robocode on the JRE. - -Also note that it is important that these environment variables have -been set up prior to running Robocode: - -- `JAVA_HOME` must be setup to point at the home directory for Java - (JDK or JRE). - Windows example: `JAVA_HOME=C:\Program Files\Java\jdk1.6.0_41` - UNIX, Linux, Mac OS example: `JAVA_HOME=/usr/local/jdk1.6.0_41` - -- `PATH` must include the path to the `bin` of the Java home - directory (`JAVA_HOME`) that includes `java.exe` for starting the - Java virtual Machine (JVM). - Windows example: `PATH=%PATH%;%JAVA_HOME%` - UNIX, Linux, Mac OS example: `PATH=${PATH}:${JAVA_HOME}/bin` - -You can read more details from here: - -- [System Requirements](http://robowiki.net/wiki/Robocode/System_Requirements) - -If you want to program robots in .NET or control Robocode from a .NET -application, you need to install the Robocode .NET API plug-in on top of -Robocode. The plug-in is installed by double-clicking the -`robocode.dotnet-xxx-setup.jar` the same way as Robocode itself is -installed. - -### 4. GETTING STARTED - -Most documentation about Robocode is provided thru the -[RoboWiki](http://robowiki.net), which contains the official -documentation about Robocode, but which also hosts the community around -Robocode. It is highly recommended to read the articles on the RoboWiki -for getting started with Robocode. These articles are provided from -here: - -- [Getting Started](http://robowiki.net/wiki/Robocode/Getting_Started) - -You should read about the anatomy of a robot, the game physics, scoring -etc. - -To learn more about developing robots for .NET, these articles are a -good starting point: - -- [Create a .NET robot with Visual Studio](http://robowiki.net/wiki/Robocode/.NET/Create_a_.NET_robot_with_Visual_Studio) -- [Debug a .NET robot with Visual Studio](http://robowiki.net/wiki/Robocode/.NET/Debug_a_.NET_robot_in_Visual_Studio) - -### 5. ROBOCODE API - -The Robocode API is provided as HTML pages for both the Java and .NET -platform. - -- [Java Robot API](http://robocode.sourceforge.net/docs/robocode/) -- [Java Control API](http://robocode.sourceforge.net/docs/robocode/index.html?robocode/control/package-summary.html) -- [.NET Robot API](http://robocode.sourceforge.net/docs/robocode.dotnet/Index.html) -- [.NET Control API](http://robocode.sourceforge.net/docs/robocode.dotnet.control/Index.html) - -The Robocode API actually consists of 3 different APIs. - -- **Robot API**: Within the Java package `robocode` and .NET namespace - `Robocode`. - The Robot API is used for developing robots, and is the only part of - the API that robots are allowed to access. - -- **Robot Interfaces**: Within the Java package - `robocode.robotinterfaces` and .NET namespace - `Robocode.RobotInterfaces`. - The Robot Interfaces are used for developing new robot types with a - different API that the standard Robot API. - **Note:** *The game rules and robot behaviors cannot be changed.* - -- **Control API**: Within the Java package `robocode.control` and .NET - namespace `Robocode.Control`. - The Control API is used for letting another application start up - battles with selected robots in Robocode and retrieve the results. - It is also possible to get snapshots of robots and bullets (like - position, heading, energy level etc.) at a specific time in a battle. - -### 6. ROBOCODE REPOSITORY - -If you want to try out new robots than the sample robots that come with -Robocode, you should visit the [Robocode -Repository](http://robocoderepository.com/). - -Robots are available under the -[Bots](http://robocoderepository.com/Categories.jsp) section of the -repository. - -The Robocode Repository is developed and maintained by David Lynn as a -project independently of the Robocode project. - -### 7. COMMUNITY - -The community around Robocode is using the RoboWiki as communication -channel. At the RoboWiki, people share new ideas, code snippets, -algorithms, strategies, and lots of other stuff about Robocode. New -official documentation from the developers of Robocode will be put at -the RoboWiki as well. - -On the RoboWiki, these strategies are provided: - -- [Radar](http://robowiki.net/wiki/Radar) -- [Movement](http://robowiki.net/wiki/Category:Movement) -- [Targeting](http://robowiki.net/wiki/Category:Targeting) - -The code snippets are also provided on the RoboWiki: - -- [Code Snippets](http://robowiki.net/wiki/Category:Code_Snippets) - -### 8. CHALLENGES - -A good way to improve you self as a robot developer is to try out some -real challenges. On the RoboWiki, two famous challenges exist for -testing/studying a robots movement, targeting, and gun abilities: - -- [Movement Challenge](http://robowiki.net/wiki/Movement_Challenge_(original)) -- [Targeting Challenge](http://robowiki.net/wiki/Targeting_Challenge_(original)) -- [RoboRumble Gun Challenge](hhttp://robowiki.net/wiki/RoboRumble_Gun_Challenge) - -### 9. COMPETITION - -If you want to challenge your robot(s) and yourself as robot developer, -the [RoboRumble@Home](http://robowiki.net/wiki/RoboRumble) is the best -way to do it. RoboRumble is the ultimate collaborative effort to have a -live, up-to-date ranking of Robocode bots. It uses the power of -available Robocoders' computers to distribute the effort of running -battles and building the rankings. - -RoboRumble is actually 3 different rumbles: - -- **RoboRumble** (aka 1v1): One robot versus another robot - both - picked at random. These two robots a alone on the battle field. -- **MeleeRumble**: Ten robots picked at random all battle against - each other.. -- **TeamRumble**: One team versus another team - both picked at - random. Each team consists of five or less robots. - -In order to get started with RoboRumble, you should read this page: - -- [Starting With RoboRumble](http://robowiki.net/wiki/RoboRumble/Starting_With_RoboRumble) - -Note that the RoboRumble@Home client is built into Robocode and can -be started using the batch/shell/command files: - -| | Windows | UNIX / Linux | Mac OS | -|-----------------+-------------------+------------------+-----------------------| -| **RoboRumble** | `roborumble.bat` | `roborumble.sh` | `roborumble.command` | -| **MeleeRumble** | `meleerumble.bat` | `meleerumble.sh` | `meleerumble.command` | -| **TeamRumble** | `teamrumble.bat` | `teamrumble.sh` | `teamrumble.command` | - -Two other competitions exists which are: - -- [Twin Duel](http://robowiki.net/wiki/Twin_Duel): Two teams - battle on an 800x800 field. Each team consists of two robots - (twins). -- [Hat League](http://robowiki.net/wiki/Hat_League): Two teams not - knowing each other are paired together at random (like drawing - names from a hat). Each team consists of two robots. These two - teams must work together and defeat two other teams that have also - been picked at random. - -### 10. COMMAND LINE - -It is possible to specify options and predefined properties from the -command-line when running Robocode. The usage of these can be listed by -writing this from a command prompt or shell: - - robocode -help - -For example, it is possible to: - -- disable the graphical user interface (GUI). -- disable security that is specific to Robocode (but does not - override the security that comes with the JVM). -- enable/disable the debugging mode, useful when debugging robots. -- play a battle based on an existing Robocode .battle file. -- replay a recorded battle visually. -- save the results of battles in a comma-separated file. - -You can read more details here: - -- [Console Usage](http://robowiki.net/w/index.php?title=Robocode/Console_Usage) - -### 11. LINKS - -Links relevant to Robocode are provided on the home page of Robocode: - -- [Home Page of Robocode](http://robocode.sourceforge.net/) - -Other links are provided from the RoboWiki - especially for challenges -and competitions: - -- [RoboWiki](http://robowiki.net/) - -The is also a Wikipedia page available about Robocode, which provides -good links to movement and targeting strategies, competitions, and other -sites about Robocode: - -- [Robocode on Wikipedia](http://en.wikipedia.org/wiki/Robocode) - -### 12. REPORTING DEFECTS - -If you discover a defect (bug) in Robocode you are encouraged to report -the issue as soon as you discover it - the sooner the better. - -A bug report should be reported on the [Bugs](http://http://sourceforge.net/p/robocode/bugs//p/robocode/bugs/) -page on the SourceForge site for Robocode. Each bug report will be -prioritized among other bug reports depending on its impact on the game. - -It will be a great help if you describe how to see or which steps to do -in order to reproduce the defect. You are very welcome to provide a -screen shot, source code or anything else that will show the bug. It is -also a very good idea to write which system and version of Robocode and -Java you are using. - -If you are a registered user at SourceForge (register -[here](http://sourceforge.net/account/registration/)) you will be able -to add a "monitor" on your bug report. This way you will be able to -receive notifications when someone add comments to your report, but will -also be able to better track the current status of the bug, e.g. when -the bug is fixed and with which version of Robocode the fix is -available. - -If you are a developer yourself, and have a good idea of how the bug -could be fixed, you are more than welcome to do so. By fixing the bug, -you will become a contributor of Robocode yourself. You can learn more -about how to contribute [here](#how-to-contribute). Note that we accept -bug fixes under the terms of -[EPL](http://www.eclipse.org/legal/epl-v10.html). - -### 13. FEATURE REQUESTS - -If you got an idea for a new feature or improvement for Robocode, you -are very welcome to share your idea by summiting a feature request. - -A feature request should be put on the -[Feature Requests](http://sourceforge.net/p/robocode/feature-requests/) -on the SourceForge site for Robocode. Each feature request will be -prioritized among other feature requests. - -It will be a great help if you describe your idea in detail, and how you -think it could be implemented into Robocode. For example, will it be -possible to extend an existing feature with your idea? - -If you are a registered user at SourceForge (register -[here](http://sourceforge.net/account/registration/)) you will be able -to add a "monitor" on your request. This way you will be able to receive -notifications when someone add comments to your request entry, but will -also be able to better track the current status of your entry, e.g. when -the feature has been implemented and with which version of Robocode it -will be available. - -If you are a developer yourself, and have a good idea of how the feature -could be implemented, you are more than welcome to do so if the feature -is being accepted. By implementing the feature, you will become a -contributor of Robocode yourself. You can learn more about how to -contribute [here](#how-to-contribute). Note that we accept -implementations under the terms of -[EPL](http://www.eclipse.org/legal/epl-v10.html). - -### 14. VERSIONS - -Robocode is continuously under development, and you should be aware that -three different release types exist for Robocode: - -- **Alpha** version is an unofficial "snapshot" version of Robocode - that is under development and not feature complete yet. It is - normally provided for the person that has put a bug report or - feature request on the tracker for Robocode, which needs to be - verified. Alpha versions are not meant to be redistributed at all. - -- **Beta** version is an official release that is considered feature - complete, and which intended for everybody to try out and test - regarding all new features and changes, but which is also - considered "unstable", and might contain some unwanted side-effects - due to the changes made to this version compared to the last final - version of Robocode. Defects or undesired behaviors should be - reported as soon as they are discovered so the issues can be fixed - before the final release. Everybody is encouraged to take part in - the testing Beta versions of Robocode. - -- **Final** version is (as it says) the final version of a specific - and official release of Robocode, and where new features and bug - fixes have been tested. Note, that the release will not state - "final" on the distribution files for Robocode like it is the case - for Alpha and Beta versions. - -### 15. NEWS - -News about Robocode is put on the blog spot for Robocode. Here it -is possible subscribe to a RSS feed to receive news about Robocode. - -- [Robocode News](http://robo-code.blogspot.com/) - -You can also follow Robocode on Twitter and Facebook here: - -- [Twitter for Robocode](http://twitter.com/robocode) -- [Robocode on Facebook](http://www.facebook.com/group.php?gid=129627130234) - -The RoboWiki can be followed on Twitter as well: - -- [Twitter for RoboRumble](http://twitter.com/robowiki) - -### 16. HOW TO CONTRIBUTE - -If you want to contribute to Robocode with e.g. a new feature or bug -fix, you should read the [Developers Guide for building -Robocode.](http://robowiki.net/wiki/Robocode/Developers_Guide_for_building_Robocode) - -Note that we accept code changes under the terms of -[EPL](http://www.eclipse.org/legal/epl-v10.html). - -There exist no or little documentation about the internals of Robocode, -and the code base will need to be examined by a contributor in order to -get an insight of how Robocode is implemented. Thus, it required a -skilled Java developer to figure out how Robocode is put together. - -Robocode is divided into several modules. You can read Pavel Savara's -blog to get a good overview of Robocode here: - -- [Robocode modules](http://zamboch.blogspot.com/2009/06/robocode-modules-as-in-version-17.html) - -Help for Robocode internals can be provided through the [Robocode -Developers Discussion Group](https://groups.google.com/forum/?fromgroups#!forum/robocode-developers) -where you can register yourself, and start up a new topic. This is the best -way of getting information and asking about details for the internals in -Robocode. - -If a contribution is a somewhat small change to involves under 10 files, -then the preferred way is to provide the contribution as a patch file -that can be applied to the existing Robocode sources. Otherwise, you can -be granted a Subversion branch for your work, where you can commit your -changes. Later, this branch needs to be merged into the trunk be the -administrators of Robocode and tested carefully. Additional work might -be done by other Robocode developers to finalize the work. \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/battles/intro.battle b/代码/robocode/robocode.content/target/classes/battles/intro.battle deleted file mode 100644 index 8bcded0..0000000 --- a/代码/robocode/robocode.content/target/classes/battles/intro.battle +++ /dev/null @@ -1,8 +0,0 @@ -#Battle Properties -robocode.battleField.width=800 -robocode.battleField.height=600 -robocode.battle.numRounds=1 -robocode.battle.gunCoolingRate=0.1 -robocode.battle.rules.inactivityTime=450 -robocode.battle.selectedRobots=sample.Tracker,sample.SittingDuck -robocode.battle.initialPositions=(50,50,0),(?,?,?) \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/battles/sample.battle b/代码/robocode/robocode.content/target/classes/battles/sample.battle deleted file mode 100644 index 2be49ab..0000000 --- a/代码/robocode/robocode.content/target/classes/battles/sample.battle +++ /dev/null @@ -1,8 +0,0 @@ -#Battle Properties -robocode.battleField.width=800 -robocode.battleField.height=600 -robocode.battle.numRounds=10 -robocode.battle.gunCoolingRate=0.1 -robocode.battle.rules.inactivityTime=450 -robocode.battle.hideEnemyNames=true -robocode.battle.selectedRobots=sample.Corners,sample.Fire,sample.MyFirstRobot,sample.SittingDuck,sample.Walls diff --git a/代码/robocode/robocode.content/target/classes/desktop/robocode.png b/代码/robocode/robocode.content/target/classes/desktop/robocode.png deleted file mode 100644 index 99b0d5b7a52090568d08ba99242da7281f175746..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3918 zcmV-U53%rxP)00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qRNAp5A000iXNkl z>CSFvXLe`ykDY0o{lWK6`trrqe7fDKzj?+ti}goO(iwzjtJ-n}~| zC52r2KLgcN;sl{kNN&FfTqoe}?oNCR2R4&D!4uH?|6-lC#owAI#LUcC6d(9jab z`21*k0y5bY$F0W3uF}#Itk*j`?})`#9DU-30@M^C#1&xht`pMI($drG>g#XC#5B`Z zTzq!LiVKdfQfU@Ffv~XUj$8Zp-?dr~IKDF0(eX&BoKsX(MBGrYTCIc-SD*lW;Dl+@ zrlqC5TVH=8I=YFr;^H$E73UparP7JRCs5|NwSRxV)!OR#%2-FoL#1*yR1k-Kf%HsXdtPEHOX#1#z<4R@SSP*9MXT2oio6BV_awxXhw<>enaz6J)4A3lL) zj$17)eTj+9j<1Zhx8GMNX71g)m$;#TB_o8mV&A@fzjwmYrAt#&tG93Owpe!3R#@0s zUVc`mi;Ir7CM0B7t!dc$+}vEOA99P;ni(ITX0asdblLm%^(H1Zv0iU)zZVpgbMW9n z;)Vj2j1Y1i(b3U3tQRj{{EHJ-tXN^QRh~OHP+NPIwu1-zmoGnKHjiDrcyV1_9aKNJH~jSar*RWkii@X zIah$>b^iSM{{H^oI$_C@CE?*KOs03AX|7Cw^@_vf@@Z(_h#LwwZrlKwdGqEGa<1U; z;lqy~KW4Nf3kw!3z=@2E+zc}qDvick%4%GgK>F}kelofI&0V{85jPa>-@gwsWo2cA zoGU;q!uR#-*FSOsx^Tcw&G96T5Q8jaPoxi*1euQ&|DB2BP|Sky`7sq06~qk% z%mHL@ED1SR@b=qpBcq|Lpeyc3}dk!(Z8g^v?t&iZ@a| zaYF%>1Z1E92su}P_76OefPdu#lgShsx;Qd&lV1OhQkjPj4#S?9&0}6P0b4}GM*1zJ zf93;GS~sI+bccM8taLU1U$@1By3CDF`4hkqLaLcCVS-R-P^%XY&3qdEg#`v?{x^?=5LZa0QuMVf z2m}JPx(M+D3kg{y6zb4(?AfyivIiwor3%sOlMDu%$pqn$5fwEaW;SOSjcJjQw(xLF zFcu00595F(BqRz1(TE(md@9V}-z1aCh#LwB2SSJ|a9)u#SEi%^k{*xS_!9 z_|m}fM^vzYMB(eJ^YrvKV(FryFuG7^L^zqv+hORuG#W!~ZSA^s>rzuwBO)wDqh-pJ zDbOY>SFV&uB9J$kCqqM*NF?ES9V>#w;NjuL<7rDuN{AZ@Hk*wQavg~NkdTlqTeci` z!i*U+aO`+Id2DPMx=Vw>fM{V#DGnmS1M8ZRk%0ymd1go|??8B9l30#Sn>LBXMuVY> zd0wSjh;1~PV&mgij~*?TNKz3|#0>?A7m(q062S7Ux86cK_lXlAst^ofaiGOAyQJib zSgZ~XMl~3$L?Y2R^n|D(NK*_&%Bn=7v4{u6G|tA*^Oy`mKefF4u1*)v#Ge2NWpN#4TTFAE`SWT#MzJ^<<$}1O@cHMTgAB?GA?FHCojUc+H{YNe z`l}Og7Ey_D{xAV#Aw+Of(;v>Cw_m$vzkK=cn>YU^Gjpa~ZbniUi4qVMSXZGip3jd| zt7CFTgv;UJ55RQ;v{{ErZCHO{I%VgngZBH*>wqL()@9VQadSo9M`2Ob2Kc70)+unZZ z$dRk(&fV+p|88L5#|IDWy}kDCZu`ZH_NuCGFE1Wq27^F53Waf~0|*u3h637RkXg2D z86oEis;jHdo;?c@`^X8!#l=`rFRwsIZus83d9#m?TB(d~ZXVnREbWaOgDmgfwS(@% zhl6(izP-QSe*3n)r^kNfioL7LzJ7g|K%f^0lo$a(#Sn{=uw&R&;)cStYu7*qM~;wl z1@q_6U%!4m+L~@B;1VS^M$hKjh~(`1?m7hbk1|%mh&B0s>Nz#E|ug8wz*;WKg6DIai?5=^#Zx5e+p9 zxw*NFZb9H;Xv6@I7pzj{Be8&1dV1;Jy?<+Ow}0?~{lgFKM~@Evd*sOA*TaYH)z!Z< z7$#x^(FwtHy2v5^tw_yKa=4DlL)=h6+5j23Tu#Wj4%Ef>oG@|XM7ca$Ac#TWGVT!x z*a60b!dNda|CE%n^70!E4gYFv{IRj|hi%)wD=t1`vCQ!B@P;&Eo>R$zn;cSmL4o zAn3ikL{R*W$E4CMXar^i)MK<0Lg82hI&nh*0+tZs3OK;#vH%GL9@uUKF5_OS)niX+ z!*cTZ79LL-5TFu?f_;2KFlVSe`WYlmXe4F?#5blS5RAcM6E_rI{!g@FVPOb979iQt zyduG4XvRGR86p@LIT`5Y<>fIWU|5AB7h$Q@Y8fvy{`Y?*M;uEe=?GlLJ%llmAf!Jh z^Ye>Dab-p@7|fUeY8i3x>hSRJ@bvV=4q$azfKbJHV-7gYjC(`^e52xWGE@%~b!G&O zCIYQJpC9#1kH|kDgWi&ma|LN>X+v5qZ>|%dpRs<3as)2p9*^;OVF&>70pORAa|K9ekd1JFT**R0LIUKpOg0743ExAKE-oo4DTO1@41pFi z0g*_>)D{Rk;)Vj+Baq3;$|B@k!OopKQNRx!It0DI0wM<|7%2r=628&Vqc$@)mK-qUM0nl0xB_dFEq18qsJ*6 zKYl!6#2qM7CX)%xr;m>k1N!+Ho>__S+_?iX6%`ePoGZWtzWnmbzP>&pM<`&uk-|}i z{QM+1VT>kyX+TPahK7232M-Mx+0f8H+)#j?0~u};KnQ*M>8EHT9y$SP6uK8#$jeJo zQ&U5TyaE<2T7-5C1N!>vu^hw=h0i|w3}m>45Mr^hu@O7)wG(g)vJsgSnMA7{Y{6a; zGMNI03Ijr(pdTP^D0Fpofeg1poSK?CYt}3r9nut0K=Ou;Kp}$-W%Ohi!~&8a^Vt;} z{=AJD4f}vjkhr0M;|?<1(kN5N4jee}#0h0(Wsr@K@3bMQi$qDRi_bAXKO@$gb&6+1iFNTgh9ww18j&;XBC6ptf0fA3 z&nJYqqN=J2nUn<#ClCxa;FKi|O@O}gLQ5PqO3b>*<7v=B5jPZ&xCtSyKo#tCLQc-0 zXh9-!*pM!e(N|nCPfsB_2l@)s(Z-D%i5m*p+1Z2;S3vP2idaD9^7l9695aT=AQ-^L z+gruSJUo1GY7vc&p>VR7E?r98PpNGl{#qJGPg& zp@1%jJi!$~K|y$#1(ixgZvO-~r81AJNhIw51dBvTd<=&`ARtftY;YU;36Y!O@Q}A( c1#i6ZA2VR(3ARaFB>(^b07*qoM6N<$g3~4%yZ`_I diff --git a/代码/robocode/robocode.content/target/classes/desktop/robocodeMeleeRumble.desktop b/代码/robocode/robocode.content/target/classes/desktop/robocodeMeleeRumble.desktop deleted file mode 100644 index 2b6a8cf..0000000 --- a/代码/robocode/robocode.content/target/classes/desktop/robocodeMeleeRumble.desktop +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Type=Application -Version=1.0 -Name=Robocode MeleeRumble -GenericName=Ranking system of Robocode bots -Comment=Run MeleeRumble battles for the LiteRumble -Icon=roborumble -Exec=robocode-MeleeRumble -Categories=Game;StrategyGame; \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/desktop/robocodeRoboRumble.desktop b/代码/robocode/robocode.content/target/classes/desktop/robocodeRoboRumble.desktop deleted file mode 100644 index f366fdf..0000000 --- a/代码/robocode/robocode.content/target/classes/desktop/robocodeRoboRumble.desktop +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Type=Application -Version=1.0 -Name=Robocode RoboRumble -GenericName=Ranking system of Robocode bots -Comment=Run RoboRumble battles for the LiteRumble -Icon=roborumble -Exec=robocode-RoboRumble -Categories=Game;StrategyGame; diff --git a/代码/robocode/robocode.content/target/classes/desktop/robocodeRobocode.desktop b/代码/robocode/robocode.content/target/classes/desktop/robocodeRobocode.desktop deleted file mode 100644 index 89c34f6..0000000 --- a/代码/robocode/robocode.content/target/classes/desktop/robocodeRobocode.desktop +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Type=Application -Version=1.0 -Name=Robocode -GenericName=Tank AI programming game for Java and .NET -Comment=Build the best - destroy the rest! -Icon=robocode -Exec=robocode-Robocode -Categories=Game;StrategyGame; diff --git a/代码/robocode/robocode.content/target/classes/desktop/robocodeTeamRumble.desktop b/代码/robocode/robocode.content/target/classes/desktop/robocodeTeamRumble.desktop deleted file mode 100644 index d0f1e25..0000000 --- a/代码/robocode/robocode.content/target/classes/desktop/robocodeTeamRumble.desktop +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Type=Application -Version=1.0 -Name=Robocode TeamRumble -GenericName=Ranking system of Robocode bots -Comment=Run TeamRumble battles for the LiteRumble -Icon=roborumble -Exec=robocode-TeamRumble -Categories=Game;StrategyGame; \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/desktop/robocodeTwinDuel.desktop b/代码/robocode/robocode.content/target/classes/desktop/robocodeTwinDuel.desktop deleted file mode 100644 index 564090b..0000000 --- a/代码/robocode/robocode.content/target/classes/desktop/robocodeTwinDuel.desktop +++ /dev/null @@ -1,9 +0,0 @@ -[Desktop Entry] -Type=Application -Version=1.0 -Name=Robocode TwinDuel -GenericName=Ranking system of Robocode bots -Comment=Run TwinDuel battles for the LiteRumble -Icon=roborumble -Exec=robocode-TwinDuel -Categories=Game;StrategyGame; \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/desktop/roborumble.png b/代码/robocode/robocode.content/target/classes/desktop/roborumble.png deleted file mode 100644 index f1560d15acaa753cf5b06cc5c58bf4d9295c6c4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3401 zcmV-P4Yu-$P)00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qRNAp5A000cQNkl|`x*$lfFVE-Py|BQg(B8gTdB*SBBD|k5NnG%qEu;ZpIUrx zw009Mgn6eX(|PkcZ{|&3UxG6|!(<@&`Tl#qd(OS*`+@Km{=yr~ojX@oS65S0Q~vYY zg?aPlty{Nl+qP{^PEN=~{_fiXZEfw%n>UAqgp`z&)YsRO$>jO-=c}r!%0Hgv0B5#t z-Abp^larG_{P4q(k&!cJ&gAFkFI~D+e#LBthK9zLEnC9E!otJDckI~F+uQr>*|Yoi z@Avoj~5T)EQC%?%ODfC?ZJ zKR-Wj8Z9j?4LL9v47|U6`}R$nHZ5GZ5DCkFS-C)e)YsQX!$G^0g^td{X0wBWgM(SD z#H7U3@bJnKVVOu2$>Bi94Gj&Qot@yAmX?-$31wluP?ZcJ(h*e3J%6= z^o||rTyB1VU%9bS9o@U7xmhR_f=GSm&VBv$*B35aaB*=_=5Rn$H#Rm#5THtAWF+X0 zSH#U`vG9FrN=ijUSc|23%VO;gb=7ultyV5a($s{RaPZ*42M->6{`u$73Hp^1h=g0B z`WUW=04&F@BVsO>iweAvFE>9szl7n}uzICfo}mI~3!7L={5AfSgpg?v6A^R=m|DJ3NZMF91&`!t##E5K0@Y2M7xYTl+QWax5T zEfd$QZJIx)OHHMH?V6UH>>9B+H#ZluM&{<`=1{+UT}1*rhwgsq(j}1L*s)^}fIkqx z^z&So%u;K~R2^(5{OvU1`^%~~KVGsc)5Xu)ZqGuEcaejcX=||nb%=|NMT3HrD=RCZ zBKf+Cgq@w;jT<+fK7BekIEWqf@}e=kErNZFIKl3Mtp-^>E5!M_L!E^0hY6F{)s8fo zMQk={S0^Bcy=JCGsi~P+SrOsk)z#JK&!0ba>Xez8nS5Qv0Ib#1(>r|lFh*=wS65zM zp0l$v+1ZiiO$*u{R7$ii+-_f$y=re7;qY$4!!v|mt`qh|YV6fiZP!v45Umm;IaDeY zHfdmB;NioEmoHx?5{Xz-abm!o(1mzB9&$iyhkQLeJg8JR8ja>kbq%LD^S6=qRXjTs?A>~NHZ5D7z{`V62E1lpg6X=@QNH#Q&UmHz`(%Ot5+)_0RS@r6zcBoPESu4i^Y#0JsQ4t zt)jBh-^(kFOe%A*Yk0@7e$DDM_NHi-k-M84iS%pe0Et9GC$P7-haT3hT?-p4Ur~{e zi2=s5xw#oMC@(KZCa?^M2_bsAy9Y5CQQlrb9<+#HE4r(pBZ=(fM8Ze5wzlXzh#SBb zDAQ9Q2hcYzF0Qn+6uN{Q5xtd_l^c~xp}3HK4cFez&VlS;>Poh9Bsn8`^c;`}2LtRn z43&H##Y1N1FikOri;9ZimLX+if&+l#8z4%+37oOFx3M8QI5^td+aUoQH8I7MMtT`= zZ5MB0)chG8)m7$@bGWQ;UBf`NK(YLm? zGMP+WU0u8hcZoJC5{cl|+S}V9?%xuyv9STQ&~}lk@=pSQ%+e($CSp5RtXLuQWY8i! z5(d-l+qcKZ#~T|Py}Z1@8ANYnWQ4Y}e*OAc5xorH08WPgYA3-fZ14vke1PajM@KOe zP!ROW4I4H*Cq7kDok26FhhB9DISS2uK6+ShQ#n92hDyE3!fengoKY_JX7Cl$Vv| zQbECVb=8ER@N7l-*|WW9;Sz}?BO^oBK+qgbOiXZiuc@hlSy0ZSgnxscs!H6l#n(Jt zUhA_aa>6{Z)ZUPm&=7MTfTfbE=FsDFF17Q5G<#Kg@rP0jI8!6 z)#g+guX+^B_$7-c&Ciw=Wl1 zN&$xhR|5@bYHBJ?0CQAT^_DCNv9}v9E|l)AoG!{o=+eBbsqFO09DYY`jzm=66TM?J zjP;De?xTAqFqwQlA7@q^y$&|(%?3sqT`g&tyaS-!oag9`1G+iN@DHBR_Gk?iS zf1Z`mEfjR0IQg+eA_xmDV6zImJq3}R&W?5*&pSIiQHPe67M$Fb^Vd>DucxPHYhx1@ z5z)X7eoBRV&ob0|>?ycm6Zzm=O zuUu)9NLs6^isIwCTAHt1xgxHqNn!YL!@`nNQv;byC>X|A(RIL{ty;AzGb;;&Y5dDC zPaipQGa=@uxTv$yJ93hej>bj*;OBWVGW_q)pFes0_}cI=zV?g7Wr+#=q~v%S?GrcW zN)M{fwr#<|!D(q}d-v|enNZPl07Dday?XWP(}{_pp&>CZt&Q#_jE$*`=HB-6{*g{C zqIrEWKK}CM%e$kaBO@dI=g-&k`Q-ur*>u`78ub>{G1=86H6x>~t!;2{@Z`ypvZrW( z{09G5$nIorZrxqepn?)r&4xpwEyt3yNIK6!He`gPb<`RWP-h>MPX;=~D@m4btU zcsyQxZEas>`VVy1887Dto-S+#V`zBz^{ZFo4<5XKVyk^rrKYP zU|;F)2MGr*Uc|4Xs`8~32H1hTygUkp5)cp&$>9_h6*V+AUCQDAM5D}jyL7scc&RCf z{>69SUA}Z_P$;++84d+su(kZo*?Nj%``pF$SWHxBM@MsWGo~^cgMujZ8=z*~5)L^s zGP0tgqPSQ9W78yQ80IBUVvoJZN2%n)NeQDLcRwAwcX#mWyA6%anf&V^fj8|erDW@A z=dBMMx9nyGCMPHR(CG#S2FjUhXdr=sfe_-wix+EaYs)JtS|yU(@!V;5$0;xJKRjK& zVKXn43Jgzel!x?PxiT(8*Ra zcAKUtHd9foPnir4Lj!fFNWO-$0e_*Tr3GK$;o-q%vvG8c3Jnzzt-o?1PC>6E%W335 z+&JZC2iM)U36v9Zz7(Vm`Dds33SZ7n3m2J1A{aF|Ejv--ghcmbH0n8e1$c6D`$ z#p0BdR0@&!&Z0$XZ+!pT@L1~&G&D41e;|UUR~Q - -Eclipse Public License - Version 1.0 - - - - - -

Eclipse Public License - v 1.0

-

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC -LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM -CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.

-

1. DEFINITIONS

-

"Contribution" means:

-

a) in the case of the initial Contributor, the initial code and -documentation distributed under this Agreement, and

-

b) in the case of each subsequent Contributor:

-

i) changes to the Program, and

-

ii) additions to the Program;

-

where such changes and/or additions to the Program originate from -and are distributed by that particular Contributor. A Contribution 'originates' -from a Contributor if it was added to the Program by such Contributor itself or -anyone acting on such Contributor's behalf. Contributions do not include -additions to the Program which: (i) are separate modules of software distributed -in conjunction with the Program under their own license agreement, and (ii) are -not derivative works of the Program.

-

"Contributor" means any person or entity that distributes the Program.

-

"Licensed Patents" mean patent claims licensable by a Contributor which are -necessarily infringed by the use or sale of its Contribution alone or when -combined with the Program.

-

"Program" means the Contributions distributed in accordance with this -Agreement.

-

"Recipient" means anyone who receives the Program under this Agreement, -including all Contributors.

-

2. GRANT OF RIGHTS

-

a) Subject to the terms of this Agreement, each Contributor hereby -grants Recipient a non-exclusive, worldwide, royalty-free copyright license to -reproduce, prepare derivative works of, publicly display, publicly perform, -distribute and sublicense the Contribution of such Contributor, if any, and such -derivative works, in source code and object code form.

-

b) Subject to the terms of this Agreement, each Contributor hereby -grants Recipient a non-exclusive, worldwide, royalty-free patent license under -Licensed Patents to make, use, sell, offer to sell, import and otherwise -transfer the Contribution of such Contributor, if any, in source code and object -code form. This patent license shall apply to the combination of the -Contribution and the Program if, at the time the Contribution is added by the -Contributor, such addition of the Contribution causes such combination to be -covered by the Licensed Patents. The patent license shall not apply to any other -combinations which include the Contribution. No hardware per se is licensed -hereunder.

-

c) Recipient understands that although each Contributor grants the -licenses to its Contributions set forth herein, no assurances are provided by -any Contributor that the Program does not infringe the patent or other -intellectual property rights of any other entity. Each Contributor disclaims any -liability to Recipient for claims brought by any other entity based on -infringement of intellectual property rights or otherwise. As a condition to -exercising the rights and licenses granted hereunder, each Recipient hereby -assumes sole responsibility to secure any other intellectual property rights -needed, if any. For example, if a third party patent license is required to -allow Recipient to distribute the Program, it is Recipient's responsibility to -acquire that license before distributing the Program.

-

d) Each Contributor represents that to its knowledge it has -sufficient copyright rights in its Contribution, if any, to grant the copyright -license set forth in this Agreement.

-

3. REQUIREMENTS

-

A Contributor may choose to distribute the Program in object code form under -its own license agreement, provided that:

-

a) it complies with the terms and conditions of this Agreement; -and

-

b) its license agreement:

-

i) effectively disclaims on behalf of all Contributors all -warranties and conditions, express and implied, including warranties or -conditions of title and non-infringement, and implied warranties or conditions -of merchantability and fitness for a particular purpose;

-

ii) effectively excludes on behalf of all Contributors all -liability for damages, including direct, indirect, special, incidental and -consequential damages, such as lost profits;

-

iii) states that any provisions which differ from this Agreement -are offered by that Contributor alone and not by any other party; and

-

iv) states that source code for the Program is available from such -Contributor, and informs licensees how to obtain it in a reasonable manner on or -through a medium customarily used for software exchange.

-

When the Program is made available in source code form:

-

a) it must be made available under this Agreement; and

-

b) a copy of this Agreement must be included with each copy of the -Program.

-

Contributors may not remove or alter any copyright notices contained within -the Program.

-

Each Contributor must identify itself as the originator of its Contribution, -if any, in a manner that reasonably allows subsequent Recipients to identify the -originator of the Contribution.

-

4. COMMERCIAL DISTRIBUTION

-

Commercial distributors of software may accept certain responsibilities with -respect to end users, business partners and the like. While this license is -intended to facilitate the commercial use of the Program, the Contributor who -includes the Program in a commercial product offering should do so in a manner -which does not create potential liability for other Contributors. Therefore, if -a Contributor includes the Program in a commercial product offering, such -Contributor ("Commercial Contributor") hereby agrees to defend and indemnify -every other Contributor ("Indemnified Contributor") against any losses, damages -and costs (collectively "Losses") arising from claims, lawsuits and other legal -actions brought by a third party against the Indemnified Contributor to the -extent caused by the acts or omissions of such Commercial Contributor in -connection with its distribution of the Program in a commercial product -offering. The obligations in this section do not apply to any claims or Losses -relating to any actual or alleged intellectual property infringement. In order -to qualify, an Indemnified Contributor must: a) promptly notify the Commercial -Contributor in writing of such claim, and b) allow the Commercial Contributor to -control, and cooperate with the Commercial Contributor in, the defense and any -related settlement negotiations. The Indemnified Contributor may participate in -any such claim at its own expense.

-

For example, a Contributor might include the Program in a commercial product -offering, Product X. That Contributor is then a Commercial Contributor. If that -Commercial Contributor then makes performance claims, or offers warranties -related to Product X, those performance claims and warranties are such -Commercial Contributor's responsibility alone. Under this section, the -Commercial Contributor would have to defend claims against the other -Contributors related to those performance claims and warranties, and if a court -requires any other Contributor to pay any damages as a result, the Commercial -Contributor must pay those damages.

-

5. NO WARRANTY

-

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON -AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS -OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each -Recipient is solely responsible for determining the appropriateness of using and -distributing the Program and assumes all risks associated with its exercise of -rights under this Agreement , including but not limited to the risks and costs -of program errors, compliance with applicable laws, damage to or loss of data, -programs or equipment, and unavailability or interruption of operations.

-

6. DISCLAIMER OF LIABILITY

-

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY -CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST -PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS -GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

-

7. GENERAL

-

If any provision of this Agreement is invalid or unenforceable under -applicable law, it shall not affect the validity or enforceability of the -remainder of the terms of this Agreement, and without further action by the -parties hereto, such provision shall be reformed to the minimum extent necessary -to make such provision valid and enforceable.

-

If Recipient institutes patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Program itself -(excluding combinations of the Program with other software or hardware) -infringes such Recipient's patent(s), then such Recipient's rights granted under -Section 2(b) shall terminate as of the date such litigation is filed.

-

All Recipient's rights under this Agreement shall terminate if it fails to -comply with any of the material terms or conditions of this Agreement and does -not cure such failure in a reasonable period of time after becoming aware of -such noncompliance. If all Recipient's rights under this Agreement terminate, -Recipient agrees to cease use and distribution of the Program as soon as -reasonably practicable. However, Recipient's obligations under this Agreement -and any licenses granted by Recipient relating to the Program shall continue and -survive.

-

Everyone is permitted to copy and distribute copies of this Agreement, but in -order to avoid inconsistency the Agreement is copyrighted and may only be -modified in the following manner. The Agreement Steward reserves the right to -publish new versions (including revisions) of this Agreement from time to time. -No one other than the Agreement Steward has the right to modify this Agreement. -The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation -may assign the responsibility to serve as the Agreement Steward to a suitable -separate entity. Each new version of the Agreement will be given a -distinguishing version number. The Program (including Contributions) may always -be distributed subject to the version of the Agreement under which it was -received. In addition, after a new version of the Agreement is published, -Contributor may elect to distribute the Program (including its Contributions) -under the new version. Except as expressly stated in Sections 2(a) and 2(b) -above, Recipient receives no rights or licenses to the intellectual property of -any Contributor under this Agreement, whether expressly, by implication, -estoppel or otherwise. All rights in the Program not expressly granted under -this Agreement are reserved.

-

This Agreement is governed by the laws of the State of New York and the -intellectual property laws of the United States of America. No party to this -Agreement will bring a legal action under this Agreement more than one year -after the cause of action arose. Each party waives its rights to a jury trial in -any resulting litigation.

diff --git a/代码/robocode/robocode.content/target/classes/meleerumble.bat b/代码/robocode/robocode.content/target/classes/meleerumble.bat deleted file mode 100644 index 49fef2c..0000000 --- a/代码/robocode/robocode.content/target/classes/meleerumble.bat +++ /dev/null @@ -1,9 +0,0 @@ -@REM -@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -@REM All rights reserved. This program and the accompanying materials -@REM are made available under the terms of the Eclipse Public License v1.0 -@REM which accompanies this distribution, and is available at -@REM http://robocode.sourceforge.net/license/epl-v10.html -@REM - -java -Xmx1024M -cp libs/robocode.jar;libs/roborumble.jar;libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/meleerumble.txt \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/meleerumble.command b/代码/robocode/robocode.content/target/classes/meleerumble.command deleted file mode 100644 index f5ac342..0000000 --- a/代码/robocode/robocode.content/target/classes/meleerumble.command +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -################################################################################ -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -################################################################################ - -pwd=`pwd` -cd "${0%/*}" -java -Xdock:icon=roborumble.ico -Xdock:name=MeleeRumble -Xmx1024M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/meleerumble.txt -cd "${pwd}" diff --git a/代码/robocode/robocode.content/target/classes/meleerumble.sh b/代码/robocode/robocode.content/target/classes/meleerumble.sh deleted file mode 100644 index e6714a1..0000000 --- a/代码/robocode/robocode.content/target/classes/meleerumble.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -# - -pwd=`pwd` -cd "${0%/*}" -java -Xmx1024M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/meleerumble.txt -cd "${pwd}" diff --git a/代码/robocode/robocode.content/target/classes/robocode.bat b/代码/robocode/robocode.content/target/classes/robocode.bat deleted file mode 100644 index cdb3c2a..0000000 --- a/代码/robocode/robocode.content/target/classes/robocode.bat +++ /dev/null @@ -1,9 +0,0 @@ -@REM -@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -@REM All rights reserved. This program and the accompanying materials -@REM are made available under the terms of the Eclipse Public License v1.0 -@REM which accompanies this distribution, and is available at -@REM http://robocode.sourceforge.net/license/epl-v10.html -@REM - -java -Xmx512M -cp libs/robocode.jar robocode.Robocode %* \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/robocode.command b/代码/robocode/robocode.content/target/classes/robocode.command deleted file mode 100644 index 3065355..0000000 --- a/代码/robocode/robocode.content/target/classes/robocode.command +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -################################################################################ -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -################################################################################ - -pwd=`pwd` -cd "${0%/*}" -java -Xdock:icon=robocode.ico -Xdock:name=Robocode -Xmx512M -cp libs/robocode.jar robocode.Robocode $* -cd "${pwd}" diff --git a/代码/robocode/robocode.content/target/classes/robocode.ico b/代码/robocode/robocode.content/target/classes/robocode.ico deleted file mode 100644 index 8c469e67c675f43cf369da4a75a653a87391f7b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 370070 zcmeFa2e?(m)&Gx)8hcIb6cq$fii!nPdXr)U6+s0%s94d6y=$z|*u@rm@6p&|?;1@E zQ4=*WiqSW|zqcfB{)x)`zn^pOI?f$-J@=e_F5GjUXWhNe-m|ByGP7pQnl&9dEY@Mk z4lAwHL4RF3Okcc1hXc6l()9awJ%3Bj`u1)9-K|51V}8`3!{EV9zk3Yr(4o`T9XgzH zO7rif7V9wbMDF?P(xFF}#XB5&=3*Us=odwF5iC~vuRN4*#GlhM*S&jpH(=2LxT5Q~^2%k{ zO!s~CY{bSJm(m=3@WJKp_-yTWqn# z%HOXioW1_~>+W~I`<>f;^k{ed{`b?zWqovE`O-H$9uQ?Y8b9eLr>LM7NpVk!CB=!v7Xp zj2bn{jaJ=vQ(F!Z4yOzq>VENyU$}ekz1K}95AnW!m>Mgws9T{Qc5PFYRu+=_dEV2OqeLRKGc6 z$GTH@+|iwT$|>&5*|Xgly64%?gjdpBdF7REN%6DahJ8fyOD?&@ouhVMq557U93H;? z_U_P;Bi$U~j%R0!uB6#rSN~h?S6XSM5>KtL!U}GcRaPnG->+Xkw~^}o1IZK5cn9Bw zxDWHC+deYgGEEXWOg(!-o%Fpsp>`I=!zP=x4eJ1`Dj8Ii=LM=|RiC z7WDxC$h`qLQt}dPu-tNPtmvBr9fcoDzl{1U%ZDrSZ13W($Q(2`SZ|$m+_K;QzFSOn z*g~{|hm&AK@%;Ccb~%-`vEA1u7l@AgvPL>XZpY`-^^tTDdun{N(~Jo{m9(8bIY)!{k42%t%sc)cvrGL8Ws;d&=iYu;g6V+F3sygqs-FD@C$n)KI-*sDxo^j>V z{;RLPx-=FsW&wlL=MEIlpLyn)rT&dEItjq>g%@7vHWv*>sw~Tg>vh*%m)L&j5C4xC zF`^8cuD!M!F8zRZZ>upD-cEusg9n$=Zmlu7uf|$Gugx~wERp`;h5nT>#9%{}2Ms8H zYmG<4HNGanNY$UTL%Vfz>#03!t+iGemRMqmSlk;;&{^o)4Yt(yI9B5uc@9vUwpV_m z#ScAHuO8CHy6ag_-P0%XZkYND(vH@3aPQvbe8>-dz{-ib(sst-8*aFv4C95fT|^J~ zYHPKfat=^^UOWDH_l?T=m!AJhdevl&&pW96p{hUSj~5=gyXAU4|wyI zTW)bLz4THUc2ZfpYRrYFHWN?XtFpw@PKtq3=i;QeIQP_3ZvI0LxvMmeZ=yC*{?6j% z{deBEoDX?kFWsq|=;D{@-|wvSAAR(Z`}EUK%dofFzNh5)s3VSWkDYw7`}Y%1xF;^V z%w2fcVeUlfb|>w%m%I3=qudM9#lF?MYb772oqDRQZ-4vSGVCSYY)9!RH%QOBe#Q(pN;KVGI5}Fpcr-e#;3(aX6RyXof4%3(Bi)7S zt0t)4he%)Z^Lp~hCtWY`g8HDc4>-V0Qd#?{&7*~jG2*8Kbia%6aHRCI6HYk6jh245qx!8r zs<-9C)t{S$qeA1k~v7SNx+`R1GMr$7Cv+fL7E z``${kp8!1dmMmC4T+v1S`AJxZzJ2?;E`VK!YaMMM&49m6OJBW_x3-kd76V&&@bB7Ah^?|7Jw^#Z0{#ezQZ>C5F zEg!DTkI=oXyzmMR=_g2MaG>TZr>V>{MB_7?A+mho-rn2w2+5!2!}Y}%Uv!&@C&O~> zH+}y_7hU8&`|Pta%+g%(e)TM5JHTD8`YaH26eaNorhxS*0J89A+H&tz#u4laS(;Y4S%ktsc zTi^I)Mcr?+%{K0yd+sU2%rRr!9qKnO5pM$bsSo4|eUH}|bb#cMd7=N#?q^8<^z&jq z8C9nL4E^lbV~;Jv?vmRF)Yo6DdH{FR?<>uon)6!u)P-mFYaFn25C8bbZb$W3eqQvi zepylX^pEg}0sRqUmVrONwel^WPU>$g9kv+8d&`F_^C3&y+AIACn|GGht31oJi>gU%BoZb zzc1UyV2zzaHO~3KSQM5!PP#w3MIKK@ zD@dpMezQ$=XX#`It6h0uTlK$`x480HNoA4eHj@3YyeQkBU(dLE>|4k&_Cp`G(Ok&p zx!8WNePC`i_; zo*j1Rp)JayY;5mwb&PvXzss2a{`>Ej=B>{9--qTS>IchHai@|VB3dGqGAfGL{S4OL%>Ew7ts-d)#Dx~?bu zai0a&5wEYW`jU17-478yuuYyKJvc0ndGe8(JEz$wt?pdWJz0x*`|Y>gJMX;H0w&7F zK0^9eSIO%sT5q^i>ou(bbnQ*l252!$dS+PO8*jW(vh}6g^}idFm=j}@ctUoI#~**Z z1&otkH(K@YCj4PT!~TO^#kWEF_q>aPi!Z*|^_TsihxE1~qUm(aW5V*Vdwl%y$0Zx6 zkK?5KqlAaoUVF{mc;k&N>`d62hRJR_Mmox-(hXUIWNnT5TAj1rUw--JrS>!T?;%;h z_P4v{Jid*Ld*qk7_&C|BlIrZgqfX!zd7}UIVGGT*#%sLYN^?)@icN#L8MfU#Fi7@u zWQ;s|ik2fq(-E>W`DJm>+>kWT$**J5J@YAe1G{wyJ)|e>sQJ#evH_6qx#yniI!hM( z_1`S_T~%MchqwC3ezTou+DG%qusp^z>XK!S6}HJ=BeMIIHCIAk7^<-U9O z?z^hbLhi|9bLk$~PnT0aOke3krSk{$KIVMT!iP0f?nL2hl*VCjhpaI6L;pMg&!2z( z`K3Gt$o_$id3DKvUl#XCcAXI4{%>qvtZnQiJE{*GsZI2s+e@Cn9epk1C^7+{i*6-; z?kRrgD|=jD)nP;Rjf@wThHD?SnKgfKFc7<(>c6?Jep%dOd-Cg*^&Wfnsj~O_>m1w< z5Z^=VU7P!z$+CsOyAwnc_-bA8Ko7k?N<4d^%05ry#SD#yYpK5IdJ~ieK!2wH0tdrn z8{ylrvQvfS9VWX();e1{dEN{)ve}TwX!Ser&Yr7O|Y}1)!W{)*2%Z55&r)7zi$DP z)St12d4%kE)PF14K@U@#zE-{Gv)&;)<@~qaa`R;a{?~7Q%WXuj->^VOdJ zy5kPFz3Q{0{2a(*H}T?5s{gUFO@-y5|1btK##sH*uJnnlum1I~e_a5ki3gBh#x~Xt zr;Ao!%MXaU|4w7&+0udc5I>9%%?HbtHduDy(HiUaR=P{k2}J`bChos(z12+=?a(3M zMb?;3l|B`g`T6Icm+HcpnpSUnk8S#e7hWjg;=T9Yb3ROwZ43OLbka#~l4RlU;_auT z1B{Wa2mAZh;)^5IM}=^No^2uf_dw|%(^T)@$Tt6}=2tsO&JUE{L!U5P`1i}=9$P;1 z5Nyy^zqBj5#(C$RSK=Xje09gsdwiABGiC)Y<_Le``Sf!&qtgnq0%|>VpA0}8Gok8V|6aV>TaZf*Cb;@&P{AK*x zTWbYAbQhm6SL!GJV0@$hK!?~?Ji$62c7E2HM(X`ojay^H?<2+gtW#a2chjYJ50ah7 zzQxb3m)gbrcMI{6Ul#Z1Z+Yr%X|Y2yXWLjf^`VpKOg)ju;o>vw5y%ST%y9A6SiPI5 zZ&=6JRrM`_?k6fQ*0343(ao8=4b~dyR>B42A7kQLl3~9r?$N=lPI<5ReTA@+Yz^=; zz}nkk%72i`o}j*b^5n@Soe8@U;|_B;#t{50>1*-tg0DtPZbquE$noyNJ?mo7XBp)k zmY23R8Pz7%6!95he1U#GY$*O_4U#qEX{?oKECp!G7OD$6UsC-Cs^6h+weP?K_lN6Q zFX7uSi~I4?PpC_pkAvS1<`CGvm>>OEeXgTd^Nu3t;^4VSDwNtb2od#;MaqbAw5$TN?gn zsNI&{zaj(EHJ15hagXolpZ@fx(%d?!&i*@OjJm%iJ|AR%l zsBfVs_Mfmk{Df%-V~t^rVE$o6upo}DB=2EQ!s;UDxF?8#w0lYWyP9TeH| z0iTv9G;h5~`j4%tbA42L&-v2LP7n=_7xa@nLqpc#wvw#y9Jp4ryFUjeJpAy(EntFtxzU#|k-mJf^ZTl_8mHu##^cwrkb&m9oyHx*OL>s>>?(vODs%P9g z*1uSbI#ly1AGT26bHDiKCdu*7)n6Mtb-@L0w(5JvhepOv3K^*8?U>+h!t@5wtX&&NrazLvk&mY&AG z4c2h;&YfymuPk|EJ4FX&{>u6ld|c@|dY1C4nFc)zy&KyU^A!BXpaWwX{9VnmYLOS? z9^-e2e`FwwpL8wiR7sv8{wv9&Uf;m$*!Iy~&||Sj)~ha+mWwY5b};n0D4&%|^Nsk9 zN8qP%tpgtL(;6%|MPPnf9kk~);;&{roMpW)Elppo@2Jjo1?DN?`knp8UKv$C_P>?p z{>=Yd0j$YH<&REdb%?rFQ@23Zi(5mFTfd?GN1!ve5_T2t;@XcM99OT_*cZd{un)3_ zGz!>%)kSNQ_+726xy2G1Blw>7VExAGvy^C#J-f5k+E>>+5`W^TI`OQUIt{)Q z7ib<71<-)?SM!(SivQf&&G=w{Wouv=%@y$9V=dk6x= z4MqXBRQ$eJclH6_BYYqIXO-N;Q~ib0@LSfynFB}FiD!B2ifQ=49{``HD8RN(Tep_I z-v|8O@TK&h<-MoPtH$JkpWsh^@{`CqQBQ2uY3<7T9)7}J7zM}%aT$D{MZ2f{c3;UA ze;?#1>f7}t6WBqb>cq1t+Jlm{eR1hn>tb%fo@io9L;?GIsb|zUzJ_c?@IlnOEYCL5 ze5bqG8I=}4LHyXF>clhr|EPObyFwHW=tEc^XCL4fUwjb>tSR7cjGrC=t!zIxeH49z z{my$WeJ|Ov?*?j(&dR~hopso_dNIeP?mcA}k7`?%XUuQdE617%zJ^hNEseeN=qdEk z=pz0ezG~jDqcv^(l_-n7^~9=(suRy1(*9QJp2t5U#0hc_?eRBe%_0i0f74IlyYVCO zJ3cM=zSIKPQxDxK3*S0u991WtVI!yRtW}5Y%KDo%D%MJ&KlYv|pr4^%A0^uSNOeN* zz_wiN_Tvx9`e{eW6lHCwzJc}Ws5_(QU0&iOIf9wBjy$C%p1pI&Tk)clg zwDv)pkxT6E^nKgP_TL&HPSS2#n=@Q?R$qfpDLOZ?Bf|RFZ~CFu_J8a*pbW}q-)a;v zzOe6r7z?!1>d7~Z(ToYL0b*#u=az3*+0XGQVV?!{i>edPD4)9L*`E-~zv(~N$^3nx z{ypm>__)(2vo2!wME}Ni5v9B3d4`^kj$!%I$KaEQUXfHU_Pye3Rm3_6ZHEW2uUkD? z6Gr#rd24`vjy~1$rH{dM_A$v<_# zCz?4Ix)%O`QIN;4C*=F^H?*W}QGk5WPUhz5Le~BsT93qkIE2!E1o3W1^$necvrhW1 zvv?dGnm#m4kM4^sS-$LdNB-FxIz;QkQFY>35BZFQ?WpuOb{2ffqk#T@bJZQajPb(i zxxRQ5IrRZOd3p6`tO0JUezU*&_ALdhY2sVHs@{#z)&GV)Md07^rH=te%(>{}qUyvm z#-B>t8-B-L0(`BafbpODz>kz`_3Wtn?J7PsU?1WNvWFb3G2$8NWPg`F_pS8vZ?z8h zH|@#3SG=>6e8`s8oRj{0=mc$Pau+)rn`UuZHc&`y09-TlnevaS{A` z^uO)Ze)JLiyQwGoS|{-XK6u!E(N$-NSHG0sL&^VN^A>mW%}!2WO~C!ne_nd`Tlr9o zl1w2F=FhmH?6>gSOq$C-^jP-T$RmU8vFpe zDj#bj|JEGAVo-{c?u@Q2uWHuYgVUQaxZ-b+34)9xx6{mZr2 zmiCO4+NAji?fpi6YoEw};3dsb9@So$$0ZA|i7);`?Potm2_N7{^(SuCQ=-AL>Nk)n z@}`g3Lij+pxLI-&H~(k926e|qZ0*T=#lC{y9eXF@>@4VJ_&IkIPeKoTQ~Jrr>3#J< zCAzB}|0({SBcHPg@*nIaS=m^8%~*iWfG&tE_tdjZ<&UNdA9x_i{=@zb>W+_m-gaAh=3B(!A)YEc5C!xz$a!}G_3N+okmqHWR^{AB z;-3RF7u-NPD{~>ne*BS>0KJ~^zMJI!4EeMDxB3D(+qv_l)1%MR$6yykFTnm6RVSW7 zd+LsST6^+d=|8YBvECnNXT|Nc}F8y#2Ri{z&al=q^jmyY%Pb{yX~(ju`*e zRDXZ4#@nG9=h2C&JNr?9V@3b&(gpC{87931dl~eQVqarpPb_x8Jv90$OZTqO5$UFX^*m!!VUEq#y*!y#UzUeA`hdj|~ zI}49XHLnS>KP;+FJVR#=+fnIn_DaB)Q2>7}t@;q}1RBx*GfuG&rkC1>Zp?lwXpJxW zCZaucW6u@7)TBeF*;MZbtDUr&w9p^98KkuE4SB-v%xjjFj!ev4crU6>Jd0bGuLK9o zanN(4fcnr+5y!BX`Zwr`{zrY$2e4Up7ftbz#s3$-z*N<{yLcZPsPO{)*hSB` z)_dZ^4pCc&i6=$~7sEyCp}HTeX9I@aPI^C-e&68vbKMaWWfL4?y&{fJ+i>q6ICakp_ftj*7(6N*SJ=5 z7-GgTE=K`t6O2)eS?WQP_;k&KKxC;3XfYo!Yl2k?#xdsZ9j64 z9|7~o-za886ws$JpG9wrgR}ImUk>>ns(v&sFMH0MgV^&?b>bQLpzib$mA0RLA0EU0 z<(~`S-=oLQ63wqv9ELc!Q2I-r_77A0FOeP@m){k#fujr1FZp%x@3DnacgDg>+mEk2 z-!qpE<7e1!<}9bGuD_KHi~W-!ysAF<9^oiY`-iLjFUt1vH2!T7dA=)~5V`>Ulhq@< zVjHFImBtzJafTfzjDKRkv9Fz`_CF=Pj(JN6cc}lpSM6uszO~lGhKU!3NN-2S!*`ed zlX09_Jwr5?Voiit1GN7V%{#*U`2D(cMdJFfkJ{=HUZ=@+ zrS`KwGlVZ>as~0@$0Q>cq3w z$bE<_^m5`RL;-8xcr+Ha(N89)6Kj;2U zwV&85^v_Xs;#q6#USazgL$Rer0dcU-mYhAS_Ww-$9l||o|3lJK{O9OyA^nLL;HP;- z?Y~ksQ~#OWza@JdIuJIss5)~PhiL>FSc~$MdT7825%{p7 z^$FoI&EGE-4wxetpu2|cCvKL#=lY;*z;{Y_3G?Ik%bGu9|Hm#BRVSYHQD0PPd&BRT zyJOFY0_MidF^Me}2dsC8d4}x|-!r$3%a65P{8|_{qUyvmd${o7*1+4xuM^4e1V&;}bF`X%u@I%?jCuUT8FV=e1~ zO@g@zHbC~0qpMfbUR%q$wt;(+P z*IqF|oQP9syf&rG zp0bKc%UlN^zr27?XI>jA=NSH2K3Q!A@LA7`XZBa;#TDtRx&E2A&PnOlY*O>EJyBPn+$WN@T0DB~@Zd|D!e7u_Y znRr&jbRd>gseNiA`y95Czf4|Sk-jy4Z+;!Cea~7lej9lKdoeaLVoLaN;QV{`1+sq( zT!K^M2V|<=KwktdSJXNm{JNod0e#S~e|XQn62||$xFS7!Y^qJWYUGE%G;2P2fqesM z^bhezA4<$b_E(1QivA5xGG4K7KWo|0pFKr+aYcIejZ}kP)y{*MEpa|eNzZ8$`Y<+> ztTsH-G9EBiWc{XA>DE%+p(p!(vz9@6bo?Z|#J$5eu-de%Mt<-!`_l6QzUa({*=xw& zuPo32KNWx3pJNkuc)2*2I^`z&V8xQ@N@8yY~ zM*QH`#^KFVUQ}9(RmOZZ>V4cZ=7#u5CgCOS-GkaAQf=B*BR_mU!dNv~e&a8)taNB% zDG>)ZE3oFu8~_|={ifRKh}Xe5MBkq$Z|Kh+tStBm({Q$3HRx6CJQ&ZyvwXAsW)GUt zA3JJRV4jT~m@zo(H`PwpQR5GNdER`XKl=-_;3rJO{=aI|u9Ez)*+Mr1_GX7?0cQFA zrs8Cg2k{_@eUcT36G*+WwPgLK+UXd7IJY5hzR(~0ZWjE6Y1p%BIJavh^lR-mtl9Zz z$6=ca_bO)j&3WIfX|slIG0?MI>GzR;`hhIzYmtWWr?bYPym>=^?A}@M6Q*H5q>p#* zTT9DIzQ@;_9Z>%3N6UkuReXcs=OwLE*r=vB=tvQPXh>W_U0o3FKtD{&t2 z<;sgI(i8j2aBkOn&>y)Z4za;+72_FM&I{PHS^vS7O8j>Ne8JdDgplCVjsC=u zHelQ&)(1K+^8@_L=u>M+w`$}KUhrpQenh`TJPZ63tX*7}6aDdf&59#G9eTEpckb&! z|FHjO-*XtNILmKvj{gUGvhUBgyl{k10q?PuU~i;PrEjeUoobN>zB!Cn#EB-ZJ+T1r zZDJnlw+;HUUX}$vVH(Z=vwq*M^`L*K|DlUkf>UDXLVs{XyhQ`n)tO^jp2VXfHVS>K zJ!?x>#wW%p#w*%H-G~!xx~;W~EA+=-qLTVE-!r|>uJxcl@qZuI`4ye(YuVPkw^9!qROs}pgu=?{9!Ms4ll3jJwIUR;qL zJ~N!#wI1|GHu2pufY&)sFE5}+LR0*s$1C;laTyMY!1RSxR>(|ll*%yU>ptX%F zx-Ie5^Wuv1?3Xf}+cl0xwS3NgKXe!a{Qr=FyukiX_W!XrhVuph>}Av)-N5i@SLT4L zYCa84v-(@tG97;3)YanNSv~EFoUAVW*4oAu`V$u?FRn;mIw#M=JNU09o#XOGX3hVA z>$*BCfN?M{5I3zfM;0FKd_>lK(e?2uFg)6oGnB9gU>~lfZ)euLsVlmQe@3d+l`H3C zu?}c$;|l#57xLnY^x%v3`w&N?BA-(qV%+5g`f_N^ULK3*fL|>-A!EIdOYS*?2HwNx zHjmF;Ez{x$0&T*&@*5k*3Zl2QjVttLUXT}8qz7L`(zU3vpgHH?0_cMDDN#0GbRO!2 zy?BVmiM9ajQ6=_c6#bbe;qL?8t$onHD7-E#%qt}Gs~vmt%F;tN2Vu&J`H z+7^KRoq4HWPrJu%#eP-dx?B4eMf%g9p%dl>^alEW^e8(62A@9S9Y@)E(X*jHFBS}SL|FszrNTo zz%%KsebArzUtV01zMAJhRFnR+hdnKM0UN*B|I9|pncK{peLUJdeGF?umNv^3Kitlu z4|+OwrR7C0`YU|c;oBc-ETIncD~#p%qCl@Kd6S0p%vbE3bgL^@&X@(yj8B}M3qXJ3 z!{@~n={bwInslpHUf8qZ&MZxOjvpkrM;7q`1<;q7H~V?f?nf>(U$S-Yh_f=0w0!CseE4t)y#9{4I)J?%<-3vi4d`0iRC z1XfUci5Z`Sm$-MtTCWz(s+kY*j4D~rFn`O7MmKznXNbR$jyoz`~P%~(APTG=vz7hOe_y1346ucl^ z?R51ATS@m^LNqhntbzSjJP=hD&(J;Lm8dlU^8sLfL;C>e&-z(jT#+80v3j+oD|SiF zEzAp?2aNv*^09~TPXEX_&Ai#CyWKNyVz0RAQsEW3hxW`V`zfzmv}W@EL}RBjPi0VW z3cAw-T1SvWSrgbZ-V46bTJ~?mCx-Ld!5PZ}_$hQ3N!e$yuCKT!1NTx9ek`r>fyANu2GL0`dIq4lM9 zg$~$_*fY>m^}0`Xf^X$B;;y;IDQJq*p(IWlC!7|~o8X2Uob!R_ya!0jH>%q_;rk%@ z@-3-83B3dVJuB0$^jYjhi&_I8l@!|goM>>SVDZr9*@=MZzqRuJK zj2P7Ea2}^18Vdr?0n(86mRp*>m4E7d@y1)y?KYRK3OUCp_3w{XruG`lZJoe>^vs|2J#CQ?VgP|D!!oYyari=yT}O zQ-xFTiT#)HVngx3t9oCe8#IK*@|9GOCFc}lM$WcQ2zS~%1iJT{qcLK1Yhug;oPqEpg(bl zncEoPi&V*e2HJyOj9}l`d7OD<4Lu_aBkOn(4X=C7WI(^_#(dk`s=xY zJq^$wdmKK%*y3mpZ8N&t75y4L8$FD)-iQr=d=XcOQl1=o9=ned+lk{Azn@gZ94^MYT_CA0Y0MNfEUDLZ)cROzLa;ER2BhI6~tgZ|jzIp4_u*=G+>UaPKQ@H zr!(eDd;w3uH}C@e13YDXpg!h9>2@1S4`4k9I}>vg<5mBPEn{Vk5Bo@e0H8m1oV>Uq z{oAUe;oPqEpg*w(*o$aDz2f#PCq1`#Cd}LR6K)s>u%)8w`#9tt{hGGY=U=RKwfV?A z{X8^*Hpr{dUFVOLXbxSW_1w8m0e74#>D(Xx=$zsxl!4zo|KJ0sgU6lI9_td1z%TF) zJY;+Tf5B(;GwKWGX|Awwv(Acc8np(5o(7NXBiW~o(7)3C-|YW4oZGb?^k-i-bul0= zMJ4eJ;2Y+W=yc!)`DZOT-0KBiS^HvscY*rO7PMzvr=N#L&zRcbUU;eR&vrce?)(gKuuV)-aKZ6d?1G%Tamc0H;@RH_z$I3r> zfOM}l)VDBiKzG0wgZ-EE$HWq6-iSSpH6_-6z~!>)%e#vgcae?edhO}@T={=%V*>gC zyavyqXVCwsADSz_#5GiR)Y=L*;1J#56M;vj4 zgBJ}x{q)lX>J`Q=iu!HwpP0uTDBQ3%+gW(>`_U6lIH9z@Izf8=znPmer}O)L(c^24 z(NAm4m@0j64UHk-gg&jP{YV7?)qd_nWiWyDwXQ$GJPPlLDil&(Mp}nN z)2B;idZ!F?)n9)6@yEI04apU2=SF|@Xn*aW{*<-5{_=hKALe-I`p_SpPxAkj?k`jS z-COTjXF&(Yo`@~*VA1(dJ+BmI>RWgQ9w1-rR4b^i)3)2ry((V&#?u8$b5HT+t%{3) zt&lO_`Y-xQXoS50`m=Wd{8fUlk3RaSjB~?(J?PIq1ax-;bP@XUyucnt=#R`Ho6MtG zO9Xf5fY=$=Q~&*m*3nA#JZw9XwZDrG&QZU*x@>W@AA3JK6?y}EYlsbelzb9e3;66Y zcChY(jf?tF9`ldUTEl%!^_mYqVsDa-Xuj-@XK8NCH}vte!`5ubi#9@k^yj>|B0c@3 z;oPqEpg;C2VmBLLmk48(X8HY;^l9jie+0O}m(JGyS)>1fWa%Z@mP!(ZBek^*m2Ixnyv%^>P>G&mL|7D$;bwTveN$T(C zN_Q;r=k?dSucfQ*+_!IOK1lz?J_h)6yz(*nQ`ao`3DaORFr3@99`wg=3w#)0$Bm0w zob=q{KNA;)bJ|#AVZO{dH~QW=vbWAxKQLc(eMNe}rp>g5E{x;HX@3jGe`BZr6IypY>k$d>YVK6PqM2aHawFKVqXXHnR3Vbm-919?y~LzyB>e z+dqWA*^2$Jl-|*=?MB(2D{IwYWZO<6-mC(6ZPdZgJ$P33Sf5syA^RtGFK8k&x zzWZ3w-7lN|g&3gpL4DQ7zbyOkeC^YILgUersuMm()QvgrANXb<4yf=-G26E8b2u1J56>=TA_yVisL#JZplFu*on$$2KM8`=6V{?VL`N1ywk z^ouJr{x2(eGhbQSd9-9LPL^4VVLZmR4$T+`@Uw)c=%=CoxxITQ0{UVX=_Az1{CO<4 z$J*kDlf)Zw<-@;gi$9<(ehP!cckhXRhiDE#-Pz-MXt!>q@q#{~5_}Oa$#8Dhde9#} zXG}A|pNYEV1#BhA8GaRe3QzRelZE4Hq8mCk>x`r!-UvD!_>Vp7QT;sY2;km)@%R?M zPU?$pIZ^aMzAsWgVQ_(Xg1I6-TIiJMc=WCC5Pb>r3G8==Np@q)7H?s@CN=@%1^os4 zl-Jf;#T6=l8I4`6TO8I*e{|ctxFS6~Z8*1UJ?I~nNjwYMofpoQo&>#E_hs&n{B{(c z&Mq4S9G)GEC&k}z`!Rg`w(jdRsSj>*ZdNS*<@EZBxW6Zv6#&h}`_=B;Y zd5x_-u-BMx;0bKEQRVUMbkz_05;jEg#@`G5n6vtNi?ZiSQc&{WE8T zu^xjR#?}(y1^f-^*YUq$o`D>)7S9~r=uSH7g&h(;L4OF#u;0itdLs4YOi%n)&|leO z!2AWDfG+ypXha``{g2pyd2vO0Vj5dsZRrZ1)92;|WE6eRZ12`4p(pvzlD-k<&2MxG_LY!7>lLg| z`1PdkpiE)_Tbt}kThUGP;)?Y2hn7!Ux)SFEn`T}BN5~0n!Pg!?D(<0u)c${?8{;c- zMW2B`;AxWi3pJ*Pz`Ou^4Sg?s2A`sz(Fd^i0J_n)pl3iw%BBw3YR^;JFuw~_25Wfq z;p9g@AFlUU9nl?#2}Pd;%{k+M`3PlTtH_Hh(qlK^`?dz`r9wx`3-}SyPt*S&p>du0 z5qcE*7JVrFG-qBKPW>x*hn9>N_~Ed=2EBeN+gl6JGv@2qUs(@g{f{vnoVX;l&FUs74D`oR8FRn;$J`in<{;ZE6 z3wePt82V!yWo~Bx9ZYVCp@xhiPd@$a9-WAJKR6*C6mx{1NxtF$+M+u!Z%0=+S2|o= zTAp95^w^Qm1@Kis2IK0&7;WPRJcU2&EYaQC#g+aAdC7|_(&J;?)@VKP6A?&Zdmc9X5g~wP^iNZZHNB_uJzq`zD0j)w16L=9kj(imA-=gh3Ne^YVDBqGHmFaRe(<-K1=wlv8MWxe7mr%vuBAt zN$llD-zLT$wz_VjsZW2_16jjkY(j^?_J?iX>Q8&%0sHM==^t8ytG4(pa!KEp7mx$m z6UP7c<7FQq+|L$o7|8Xb+~o!OTX2Eh7C(9)h?Phmij9SNTnOmXth?D<0b36Jey!vmU6nC~ z`m#oV-vKlY>&0*C4*jFv!ME5N^Wuv1;Hxdro_-Hp7%+Yknf|5_?+L+pSeX|T#=qRuHoFS^`JlT3$Sq;pog>ekr!wW z^k=NZZsP-VXFkQ%e;#)aZhO~|{!>K%xU$3N_y@uR;d6dNf99ikaYcI8e+=h#tq1+F zyWXY!wg%T|56tP>Tay=P6FM#Q#~$Yc`W^J=>OYUW2e-AP{~n@$T-o7sqrdMbX7|va zJ}NJ+NY8q?;oPqEpg+Dx`1~4B7i=MUfi^*Z^yO2eQ~1Ez8*6OXO#SC^_b2Q7TGKzS z?C?2u3idQ|mPH7}iWoF#P;Oj-TkH;obGz1q{)|P~Q4F5Y{!45ud4WERIXwDu=vU>_ zKYSPU8yeJ-{(FiKqsonX#yS?hicx_4qs!;T73taYZ8*1UJ?M|V$DU6E&MCz=F)v_i zE3KnO*#EJo5#Jko59_;W03B*c|GhHSBdwmS3t>~ti!0I-FT-$d*Lu*OJx$n84X~j; zqW!RW0iQPff7thjEhh??*WqK82B#@aP3fPp9%=Q2{^(D6aYcG!#u(1+S`Ye%^3OhQ z_VVNf&NF0P1N|>^#q*KkHL@@MLLOr?PS1uJxdQsQ+{R>syMG zkQdNlp+9TnasIVgpPwl|jy^S<|4);RF>76t(y@MtKTBR*k)Hk1ruW;m9`q0A|I~#& z;CX@b%-R15{m&NtS_9y`*7R>p{p?%l&;H-MxFY>;6sySQ{dTPf{X_d7YwPSy&kO8l zh5qcRJV*3v4S?TT(tmHse{1Sz-$H-vo_TRadU(L>es-+~{X_ddb5mkd7kBU`h>wb2v2mSH)U=7OvJ3cXh@&YkTp#L6{f9Macu9j`=V%f*D z!b|eGhW_BTmh|6O@_&=|ZNqPKwAVjt{Ydw`Y`4D?{n=9h{qZHsi!0KDFT=TA>p}mp zOn4FA%nQVgVf@Fx^ET*)0rJxbVN2PP z*U=gS`!-m6#Sa)B!S@%xVEldYFW*pn7=CNNXNs?GZkGS6ME|VyBi*yj^yeP>R~r8l z8&F%IcUTAZrBo8n7JDZ1fA;R&(MI?Kkhxx z^UyyjpW8h8C#4JDJumwIUi9ZV^v7Q^FRn<>`41uP+rn@BQjz7nVCR1jU*WE1`M+9y zG<)u{g3&)IJ!=D5)%YJi z_kW+2k^aP?^}h@6?`Wp~b)tXxF6sA+qW^oMKWU&p<7Hl4k)BwBZGqll9hgTEnUoZM6r3>E~{do@k znTO=X73qm@7~;My{ANx~-SPr{MEHNUSbY?JiI7D>$3ynr1nr2q9f>Hk`@{D(OA zfB&S)^uMu{^v9-{7gwZb-MB5tdsqkdGhtiJ3&b?R|C{)q`;Qsp=E|q|aoJ>kq1Y~2 z;kCyebN5LvW)Eo`SlpI0`w#p3;_~46RQ20)buP@~(p$6Ek94mR8&!MD$%Fl>#3jg! zE7IdP7UI4w{3aF?bDF%sIhe%OpbgmViRn`b5XUJC9@6NamIrYFDybjeutrAy?000m z%!@11kCBX|)v+G$iD$z8=t_XGqo_K!mj2bKC-%-t@WeO74Xj2Ts+|WiZ0nJEuj^>9 zOttG1mtR|;Kl)By99eohe&pHG?ffh%$LF0vw z#z{28#}Hpr;yuorH_vg7>Q`TV<^J}!zm?A6#JBcOfBI9&4>T#C#=C`wFIZQ`*1~)n z`N!XvGam3cVZRdoH0-ISAF#Dm)-gE?gzo_E8#G^dXl}G(eT}tp{0k;doLHhiwsY3c zh*bq25KH4)o!`!xAe=GGS`>Eql@#Nhc%poZ%@+R@%eQe|ICz1v+~NYW#)SN5r9ZYz zI}3(9@cnPlec__eO% zQz?%%zH7TYhW(cqb!qlr;@UOn*mmhyDQ)QgnbQ+9>ALH#E5*=a&PO~|`T+J-opsh( zrC1M@meKgG?eYz03}D-5evdtv_=Us)Ar1pEKk!2)UI=~x4LY`6IyPuib=nA}jlTv4 z8W?C`pn-t~1{xS>PZ;PyV;2*Ak4qPRb?DG#@uq9b{|&uZ>qtUL&EfkhBWVw6dw<8d zyG78UQAX`~y@BHeag6+LqjOIi5RC)QTW|2qf_&4!$)bT1_?tMC4T#1;L;e>HK5z6_ z(R75rw_9V42E^cCiN^Tf(0>Y;hu5org1sLIXvlx`xKS^Dtyj4}(%Hbo4k{Yh zOHj);!{58e51|3kI9O8WIMfpV(6?xwqC8?y)UsWRTHfr{WS?izVDSoTg-_(4^Y9uF zje}at|0;^nSu{^k9{gM@o>~<1<=iIrb`}k_juEq@yoRT6-y)rzj78 zUKHiDR&63~6Xz%t4a_@g)h6;q{--PEKm($2Kpg*C;vYS{Xr7`x__>ztTGa9$G-yyM zJ_9itihxn0MwMd75g($KxP-qCRh;n#MB|{=@(+E96$rhH;43Qwey$~7Eoyla51p7k zMFD+u5wW1)?^!yhwgJ&NSgOY3KXL+{p?6WdMLF>Eq9&uYY|q%SV@v1ga+Yopz?pr- zk*Q^y$Q%AXUT4iWAQ}fn$Uk(3-bL`0l>tB3nzt6E{L!1(uU{1Gvdb=|v+BViHmGH_ zr}%rCt5+MR@b{@Y3#kFoIN0U5j#l#A=&4b7o<{ zneFfeI9*vWg*R24(B6s_+im&f-CEKYSJF9lONlpI+b1k7`RBaS21Mhawek;rpcC|h zZqN@pLQm)leW5e-E|R|*u?O?{H9;TFk1Yy_A7!>b_+)df6Z_Cl{L@E#)Kh1SbP@mj zP%&q0Owkt0%zZoK|A{(_q5;u3$fN&*chl9N2Xuix&n-;)Gpeyu+&d|F^{(_&YEhCF^e$eOi(@!r9&;>a^%;bMd zjTe;wyvP`|uEwGtX-u*?LmXc($~0_E+rXFU^57ACf>-cc30?Tc4Cc#aomEKU@16*Yx=^XE|Mb@x_G!X9w0w{*7Ommzw=>)n*$*7QJ;*Ps7|C zd>|L#2Rs?hs(JP0A9@$bU+{B7?$hPoa0GqqjIScDC!c(B>1;U4hflWBS+UgybXT)) zGw#Fp)h=UU%nv+(4{#5Dz*8;SVe-!zfY7@LzOpjlXXEY0HN79;EQcFzxS=rM+(_H| z2cPtp{8t+o$5)i?3i_k(Vxz8h84F{6;KB5N@B^M|(GHV;=nTD!&z{f9PE#f5FcUxlfmS!_g&|T;hKD%U>1-S6_Ygck(ZOtQ8Mp*EU-h zer#Lncdg1=81kk4-~qaW7w}W7dav5t&(P09?;`mNem352T+{o3%PzajJ@wR6g#l+q z6B`QJz$djjp99_2)&TGgWW1|YSqnqHv>!Zxcklv!YE^HOf9MRoi{vl(xgq!Ia&I`| z%;smGeYP;T@x~j=@{c}RD;{KQ!}p(d;_K2^w(nY%wJ_vM`^_f`ynvrt)!XJ7$UpQh zlE2_*dQa$E|S0C=Z4&;%e~>~jyvvfbLY-23?6*&LAUzq ztCwg5p9~T&))H*Zi~TN)d$la9t>#U;Z9f$FsC7L}{-HDUE|S0CXXEY0HN79eZ}Ni= zJ}32z=DKj=uau?;`mNes0Kpy4)L%?z`_k_t8fm z6$bc%nEW#*9jx)cmax9J27ukGmSwfoylJ=58+_Edo@Q%+&d|F^{(_&at&MAk(p(!m zOdLG==%enFPd+IOo_z92w}#H7hc-pX|Hk5dTlXezWvzL?E#^ek4-I{BzSswpu z&5PK%?X0`yv<6V?^4enlv>ToW58$KLbu{^h&d|F^{(_&A_?>s{N&ffTb5EB9zy9^F z-B(|IRT$t4X7bOtG*sh%t-;m+;D6S_YF%Di%AfXH{|6q5sGI2<&>4Cc$zSku62J4V zJ<0#U2OsQ`0DKkMKR@@}a}~=!{_4cA$qRNK1##^;Lm=<>3v+tfOS|ED@K8xxzPT_k_O&q@5wyY?ji#~pW^O9Jrq*=L^>22Vfzbb0;{pA6IZp9P3jY5UjO6aCsk zTfsZ{&q62CnEYe^gWg5*7yO*W@4RaZI4!CUKl#Z|ToQnWbh9ivh)GI{6p^|`3rtd;&W2?5Ye=+gkj2SZujVEt$<=g8Oe1muT0O$Zc()s{j{-Jk~ z`~^QJ@q2sQAAmnp61@55o9^9r-z^M?1&JR9`~;tj&=`>f#H}#N!mYR7npytwRkeLYnJx;5&r%-$wHI}i)`;VPHD{aq8?E~H z?_WAoqOFaQi(-8^y90b1?zut_=n_XWp0C~4%7LHLcz#irdB1&Wz8CDzz(=DfAU>-v|D!ct#6hnWS1gY`n{U3kTdH|n`GMw_ z`|Pt%X`Q#N$jhQs57x-RFL;KRz&rRizJe}sG~>B1|IoWA-l81%IgRJ79qr-z#TQ?= zB)~sA&0bo~_sEHz|3xgC?Zhu}U@@y1gAO?005@sUr1DzyisHdpvt~7PfEw5Wz$^Gg zK3Mw)@8I8b0q7D(GoD+_CFl&jtI0oUdBM*~{LZ`fAoteBw7nPjXFv4NLxll)WmfrT z?+Wc$Qhq0g9(rhLydOMxaJdh_zwGqWPjB=ARqO-6r}<|h``{aW0Q^G-=mA}_%0Kij zlE2{RG@duvXb;!4*ej1e{&=dtM4CTEp7)&3mR0^OZq3pqe&PBXtPuXF3!w`Ftev(7rJye0*oZn4D{4SQfK<)3jH zJc3VX!Hk^Zh=)gPZ5=S$hoBj`-p?6WdMLF5Z?$hMo_-G~hoQA$XKmPHL%j<~n?2bF`*zgUmun)k;7yOy*vu+1|P4>Bhf9Q~h zZqONeSCfCz^2*|G*dFBG+L-1Gfqw>Pv=#--FMatRtMMWZ{BvaevB>yx`t<2#zcl8i z_^C2iwfBu{y00+!0&h0A$IlPEhPVU&wr&Gm;%LTm>$jmZ^e&3GCC#7SMoz&fZj#%7UjUtX*}N^)wziZe|I0L=SHJe!Ydh>nAy4ufnvWPUqQq~s86G|L)KeqVMt$F&pMfWn zX>bP~!Dkdsz&~^#9dyYe|IitF7s+4na~jW^Y_x~#{rBJRk^ukibIv)ZFgW6fBg*4V zn*1->?DN;TbLT|8{?bb?bsKNIae4l_!3G;d>I+eP-CmzDo`WZ3fN>xEfyX#}AXm_V z^w1@X{G(Su?;`mNeoo?d-n9q0w>B~#N&;xZI8YQ2f6?s7$p84Y){2Dfq(|D`pYGke z$MU7|>)B_YUFJ{xRJPo5%ktWlrDoR!AlKk84L{HUzJe~$CysWe|3hc! zT@-Io4*Z~Pg^rG}0e1I451OJ1s(AFQ<4?qW#f9MlMH=g`Fg~8ORQ{8gSetqys91jt1+V=hp7%(7{{KL2SsoGw3!$IR3 z9q$4>fv-4u51&H^a0y+YPaN$`{-HDUE|S0C=QN&gPyBHF@yEL)z^^kcUV1g(@4ox) zZrSGZ=-`tbG+so(K#fZ#|HFn2%gm$Lt{LCj6OAivD|m{s^@nnAzoCQ4KlF*B8_!Js zp)>TZCjX@61wSY8JMSvR*TVSSA%`5|k^uc|-+lKj40hgm=koZxR)YNZ*WM9}`8$66 z_{{PTuln-OSyUZ0&NZM32X;0WybPX9wzFKJ1K&Xx=o2UZ(3N!P7tp&%{(_&A_?>qP zqa0US=e_pY%OwHx!6ISYxN+afzx+sd)S6NhY$4xKlmFdz+btKL_UqTLOk-kJZzW!B zKobtYhw&14$|Coc20HL9bb&rmbmQ4t&3@a+KlCn=zbGq--+5>4Zx2^uI3&Tui4zNr zp+9ou$nriC_#}>pHj(exV&XMuG;P|n%zVoFbM(5953A6t~`Q zGVfoZ1K&ay=o3dflYjOLLGL2ZXn>!S_?>sw{`PPkGGvHLg0W-ArkVK>zDZyxgXGgG7i9p^{e0seEBk-bPpX&W}r_L z-FRm551pZR9{y-;TKGAM-+5Aw%&T{a$K1t`M1~~_@-b# zPU1`d-FfGo=hj(gof3_)9}bY6ig>jRXu<*bFuN*v0$)D8qXu^Si9yt5_z*myY`|qHGodW=Upi@XYe%tsDouPM;`~^Q}<^4vw4kf?O zt+v|A6$QkUu)St$C&+&n*^ZzOYe*-Ya6)DtJ?W&A%KpX6FTS|jRy;ni0c9M35AXtR z@y`WczKkc`LkC;Cg+6ie4_(P0Iz#WGc#CrIV{XWGw7*9bUZ4^4w4%Vqe(D0BOpp#5 z!p?eTJQTI}KZ!?=J@(kLec^{1e+G%)8_*I5;063cbMTdfPyd}C1EAD*N6-#h8to_p zdSeGH3Vi;G;`he0?0rM6ag`+h7DE;t^^7yl$jqb6QO&QNHUGi-z5y+90A8Ric*A^FDtpuN z#P^&$d2*SziBmgF^51}#IIy_N&=q|7GM;n~9iRu_L7#^FH)OgseFO5pi^hu(CTLt) zs(F7}w{G2HV}C^PD(lD8i8XH4sFKd9ZLjaZi}?V6uP8i5JtGDP^Z>um2Renc<9B2H zUwHZjY{0~6D+(yj){x`mpK-<3sPp=$neRXR-CI5??N!E;+6`Vz{`2es@O>+x4|GbB zf9OmMAmRWQ1@KpE#-#T4E$b!3f+z}D53)66;z;k>vEu^3x{}c$>)wAGugv!!A9c>D zO**Hpy}ko4wzneh9sr900DYiS6#Xo2J9LKLMe!EpG}iy}=^mSIx@l=27~?<@z&UcZ zMiVFh#FjGo&$IWRKERJr!@7UcId$#z9eAMXlVgNuN=#(V?&>4Cc!B(0;y`QJ_Be+Z1rM!P(F|Itr7DnGtmLTg*dchWgE?e!ga z0YBggeC62#WHA8v7CMErZJ<+{{6p_N{L$L9@UzvgaZQ*1;lqc!U3cBJFc>|0bb0@8M~(lJ zG+u;&oEYt>o6mnq_x>3bOUpi;#Q)WPhdeW{URVCgtKw6s^3BF(ZLurQc~3gh^Bvz; zyG}{@fgkEa{J*HPRpRgrJ**wjDWo00p(|55empY|wnp zBy^cEV@Brj|CnQrDfcbJxr&QV+1lsBRcCx?7{f!E$ETJtmGd+E^y%Za*=8HZm^5b0 zn9`NsJm)>>%vafXko?G({3)lkb&dPp;(#He;4N;v51&I1tLtX!t9I|yX#p_*V(1LL zi{dTHfuF5@jcfY&Pi&U7cxlyqkH4A8KV#6w8h=8dUohGob<|OrdDB0mzO(o`EoLKdwBR${o zz1c-AU&^68%B{4{ao>R-%3=Q(cnjq`?l<(X`Vj*pP5z;GHTfqkFZkK&*SMz3|CA|H z95gKo&>t=SH|NOpRy?{8Y=0W`%d_{F{@=#ao{}5Zr>g1+FPwwHT$n4rdCq&%k)H4Po;aE0XXotFe#)a<%BLRHXb*XS zAMyuZ;4Mzx!{^Y$3uAZ^Pc0{% zx|i(vL)Kf*ZNK4$Zi>#$*s%*#iJQ z%zg`s&d|F^{(_&AaN2m+vM+!>Y3HR>^F8~`ljI+Jvh5#XPXgz;#f?Sb zbBpcBSV^4AsJ*FKpRs3fG_WD$%p(bZ?0i^JfmLJFKb(((t#h-X~0{E%eddr z1G-QT=mfozv zp7@mJ`;TucKCV%|sac*OTekl=#23F;m0f$J&ceJ_@$lbMOuYY;P48Qsr>l+1&Ruw6 ze$aP(Pd?;FzT{6iQRVZD`ccm;?TJd``vB+J0{}hD#|k<@FQ0zg+x!hWL+_$^i*n%S zIGi<}FW46l(~&cviURE5HeZgCe|Xhmf8^c!Z@&Ndw&7zJ<(roF4Bgtw_xWW>*&=#t z?tQA(mtU8i>Hj1L3ZC5r+83)$%1#Fkw*;N1twXh=Axvv|H0MeFltX!xOZk3%xTl`f zH?2)k@4=7x0Or{P;Ku-_x3GU%hSqG|3SHw zPd%uQ(T*$irQS*Hih2irz!Q0Zw-A?czoEwl8*EVe4mv?EpMKoi_z#_-cai)BKl}J; z+{ep4xWS%#%PqGQ2F%}*D^yzJ%vPyL8;|NwQg?4=?M< z7PhesHUGG2@4ekW8JkUJk>#teZh~vBaSoU>rwOjT);S;4uZsDj!B5A%ikRj^)eK z+LDJ0DQ42U7Ms%+2TJxcyrn>JZwulbc4`{KqT|2cZ5txK&cop=xN zVG>Nyd&W%Prw847y8LlIl#TmaWX)vVWE@#Vo^QUn38Xh^aC7d~Tbtmv+nfV#zdbwH zH)*|W?3 zvz$L4>ZJZ})~tzvW%e)D*t*IdcGtlNyMHp?Gamc0ZZdANihSR3hjVw{*#vjpE0lbtX|LlV`y5!mW z@B99^J&q7ri$fV<~I}iW%{~=Beee-IsS{5ScXjL~fDkd+&AbzWbU$`jZAZ z=N@>V2_AgVxvXH{SRR%q`BM(%S=rRX`h=iAp#HRj_JBXyM?0hRbHfFAB5mG10DcSr z=#?b@(7Q zPuy?lYJREgC-U>;9v)?_%->tEissAb%dY+p^nB!rvDTOOP}WVxO|~C;$Z2qM?vY2n zgJ1l@IpEPp)4|gE-;*EtS{d{YluN%5_6b3MKs#s;?J^wFUfNCjL!5vo(t$Vd7l+&M zIdrl7p;wr%jsMUYdKbxG@N*i^Tix5kHO=?(A@SNX&pcBY+@LvZlKlIzKc-Hdnwclr zLu2|czHNJp-+dS<{n)qfchMaAap}DCk^4~QZEW}D-Q?V47WtOm9KlMe-N?oW}E3_x5m2^SydpeD~suFBS$jYyN6yNZ}_Q+NAw` zDS7t(o9{m~h1d7d{(1w>{`Tkk!+Z5|pR(4@92?!**XNNhppm_R&u36KOwqFr07& zPbLF-_5k=X0Eht+_A562Lucq+B!9urX*_RjZV%V%WiL(w`sP<(eYG%PerEEIAA3Lf zi1^^|w?U7K8-v2<=KIgQmpSRa$iK!o^0xKFC8Xz09W==O7j|@C?iuH!WZuShlXv9P zY$cU4Cc$zSku62J4#>fRo% zcZm;@;3e_kn{U2Z7~Cm6b+zU>KI_l$j}LzAk34(-&G(;kDTsTwxA?oS^0sqCmR4Ug zYy5ckKiKtcyf?Ww-QIM1#$06H#&=}UFYhMf$hG><61?@6 zbHDzzb8o->9SFBVZcFgrlb-J^5AvgrApfvGF#W*q3#c#sRYE^NyJQr&Rp$p#t-Q+uzB>&L6NdAJK(|F$M-X5-Lw%51Ci@*Eb?+SwlrDqfW2HZ1F zpobci#*XGSDdw#gYA;0XL*L-{3Dy@- zzUc52<2S4Dcl05*>#q0{KF+w+^Ay*s!p)>R@ zlE2{RG@fq{a&K)+v%Nr@_uqfNFnC0K>C69q;uizvk^b2c7i%wEDCcp%Ev5kTS)0=` z@BO*r>wSZboH5^I-)wr!?@iD5b$pY1)9aBz#${w4`Sj)8Wc>HPckaFSoDkUrAAH~( z@P|Jv2=>m>@*UsPSCC)WA5gC81@r^di+;)P2dKZz3uu?w2k7f)x7rULz=zobd|ZLQ zINXNMp^L>TgkI3iXvo!P9W7xkOHE4KD;G-aHF*S}@1@9X=>e%zREa?d!6oP~1F7|ob%GH>#Z zJpb{J&VBfy6C#`7!QNR~zTkBB4a_M)%e!$lUl5_!EI}{$k z2Y4|(!0-kBvhD$bF1CjYdOR@lE2{RG@iFMw})$*?)9;F@y~z$b7Am= z##@UYf&ZD$H~6GmT#E1%y>H-Ag~|DwjF)$a>T zFYt8&zaKCgfv*e1%?D_|rw4!^@MJOo{<7`?f-ca9Z=n}-^XX`Qh0qy#7s+4na~jWE zo7=lZxA2_;Jft@@Soa<+iea2wMW69%ujnDrh8T?4&?W?jU+#+50*n9kRSPyKjlzfSs#ef1+w%3 zv^%f|fFJM#z6^KZG0T1{=mLHCjx}89W;EpL%RlrklE2{RB!1_ewYNQ7Kl|)6mjqvY z@rC>H%P$Lq=Ok}7cEBeGh+hndC2M=qdrB@YQw$7W)}!u;_h9=8nAaYy^Je}p%Fd4r zM9ueY+((y=827)?*#D($|1Zm@=6uDL*=whr+(5?-+PrrDleZ9XDj@~0fiqg=|T z9@J-n`2h6}=K_+u1?&OdJb-l&@C3fh9snM}XB3|OXV3-u&~E4j-He7@P5z-X^e&RW z;O8WM=Uuhw)t2-7+u#1?+7e)!iIaa~Ntr#GbDY!m{<99%MREfE(O)MkhUR~>caJ%L zXzQ2W9Xa;1uIJD9W!wL^=KWu3t?eQ4`9boF?WK4(i#PkwgtW$nhAo|#gRG@3FL_{J z?V6I|&g$P-AKOTN_I)(=bLBVBc~3gh^Bv!lkJ&E6awwmAP#@|={itVY-H@xT56~WT zny7g|paXy>@CDv%{scbL)?J~CowE(Spj({$L+`f4f7B(!?V|iUP4}wz_$n5%BI(MDxj4pLn0uZWYOd3IU;@#zca{n*GE8?l$Mo{qdQ=a>9^sQK~b z@}1vFXK<|2yf-F_H;~sgWcT6>jjiQV%Q`x9;OXnH?`Bj0e8>0XLw@8-{enEdaVeAJRiF=w>wJTJP~c zjpwbM?cthcd#(5U-{%`*N!YqQXXeGtMX^6~&by6SJv5)5r!lF8KYx_XKV0jRocxd0 z&F@tljU9Au^wJuS{aE|PAH>w?u5p{aZp?M5GctRS;NThn`I0~7P#)z{KJ~CV*_HZI zZ|YAwXwL%jPrK27eEA1I&GHZ4z#n)dU+@ZkTTiep9vp@CZJ^0qcR_IZg-jV*o%mpN`O#JfJi5E|R|*_W$o<|3QPawNTbe)9j_y zeDAOS!zYY$1{V8+@rQF9eVdcrvrmB;vUc34wP9Bh8Jk2hxi|98y?o>%r4H42GB0rM>}aR?JkY~ z5%d32Y!mPX{D# zyw2B{AUoG`fz2LSA)YOJS}oSN?IlLHB~Jd4vb(hvpguN7vOT-hoBGoZzfS{~w3l|% ze(+G*=ZNkPe!vs!q~Hzw36J0tyn7o6VlzjGLSp<(GBz(MOlg>*YOXZqCwKJZ%N25B1_aVe0AE zn|7EUKp)|+CD4BG06xHrKld-;4g7&e;S;=qUz2a}4*vbJppW%6&@D>-p)>SOn}b&K zJ^Y-+@4PcUXb;!4y-@Ys{};+XXHr5F`08+-i)Z|XzsWWl!;D_zbw=)g%LZ7Ai+%m| zP4PNS2WajCK9)Ueru5&Xn&%39i#%Xg$Id=Zb5_>ecpmP3CuTKg5AhEB_7NKYk5L~` zZ=fEwK0^Jdr{RdJ#Xz84w2yYuUcVmzAK(T2l=@2W)jal>;+}#}tp|W#@N75-|GqyK z^fCE|ZgKM8*#B4TcyIKwYuaAudhY*UU;00`Zi7C}Yi`({{CKo`?6F7rEbPwWwLj{N z2QhwAY<|}K;915l&0qf{zCB((Gt6Oa`~nx8lY=}QB^f$adtDFJoZftmn5Txm#v@0L zEb~74E#J(pBT&B0k7y6|^JSm<+rA3gMf>=M_R?D#a8Af6cOAI`csI z1<&A{@;HkeI#`*|$M#%6H=`j}=*l;Z{r~lqeP}?ulO(8T{2$J%z^-kuVYA%{UgI1W zc#ZSi?7R@-+}|f3)%nt4OK0Ms|Ie9I8n6DL`)l^y*L4@Ke_vxZZ3pltX3mT}%+?zB zaUNKC%yGk5L&UhS^F)v*Z2!mW+j;@zTYp8p!q_O(-)tka%Wo&`rv2c-{HwtYcmiMG z4g8h#De%d?*7(3P__p%}pab-PF3<-$kq_k=4Y@*Bo;TwE)L;J7VxiSD{$D8n>oxNY ze8oAl_@LNXbMWfSZMSvb%GOmngAe@`9u+UXuk*Ag_UqRo_BH3@;!AUg_z_u%l3Ui& zz9&9qJmg#m8{4?z<7R8z@G^7U6O_+M@_Q{BDA#Nw)P;J5zLC_QcF-Q$71dtw06xGA z__28bF~h+hcm$uNz7_mx-UYtFyY;Ei1G+#TlYi(IC;yH3fA#GH=%jnj`KA6%=VQxA-*nclc=LZX|GiFj=q}B1Y>^G-$N1XfkBZzR0drRK zsbNgztUA9BI78*xS>^b-vi5eeeB(|j5Gapw%`ckzP%pop)Z26w+C#gN+RZ!g1D?#D z0Pese_yn(|K9;$G@D1LcvQG)FdGA(sA3>CvZYovkRKJparB>f`(5 za8JFhjD7b)%8c;x)$iAR`!45vzkT;}wZHK->?PkE z{Ra5_$KGY)CoL}UoP>9tsjk}L%AU?7spt7W^hNs$UJ?9$YaO?zd>7Q84}H)76wEu$ z-j;gqf8_e$(4p=hI>wlM8xE9lx-7W&!_Y5g4=eGo-euCHNfmV~{5o3rpks-gZOypa zUGfd6wUCaUrA_+e!{1ZFF^y72zzMc2*LpNFYoL6oTjO+Xu_#ZubviD7X`Og~NI|R>p1r7|CI#7M#yn zKBG_cihgyyCC|`5cEBFk1^ehb*bV!sEtUV+8GDDs7kEy>yZSBAytn$5IhrJ4Ecr>< z`w>c}PMz9`TX3TLYDUU9l&v9iyL-oXfw5=$!0MlZ_U{o=Ut&Y% zy~Y>lm%{_bA+)^>_T%I1aPMB(WBZ-&e5Z3>g0va8947oD4tP9Wz5`i>@Vv+SI{q1z zN6Jb%q^F$MEBR7xl3(&o9Nis{KyT=ebkV2wf6z1f);SpLfIYAa_R;SkcEf&ZOXWY` zC+r;xTcm?-lJKr`mXy`x3z5I4r1e2%Kf^v+Z~6S^3=rjBFTwLBnTP5tYg6#p1`8>J#OiUg5{EVZ+>R!h0V>w1YWci?ena z7kEgxQcZYHIKt~3q{cop zU9b;!BG25zeqHe&dzX!&r1ah(T}`J>KyP-K7aVbA4dLX*aM?sxUvrAN@*|OE!^s^Fy^jj5K_PW zi{#JegU?0ov*tdY5Awphl!>`<{Q0m(o-4njwKwwI&pZDU5Ah|XM}D;4C7rG(Y46|32th=Nr&JcF-``2Rmuoj51+I?5TT{uru}!g)Pzn&zeWOrt=>gr>zkz z^ErD-bxjR8q0Tr|=9RUcr!V_=(wG#IR1o;+FKe870RPoI;dzhui6_3Uk2FY^^!@Qi z@<%?qTSoMQo^;N&t30A-@`m2gKXy>RpM=LwI%b0Xup{^+U(c@E8 z>qYjy;$KtS;d#gA@0C6|++zMs^F*KJ`?5~HnonXl%KRMl&snm+?l9pO+`$J9?=qgw zmEYXwIpGM;dtH57;6CY*uJ)P85BVa0I? zruF**@&9RyGWJcrSfevx!i4C`Z|-ZmI{u#i<~iw*p7t-u2l*jidCNli(F6L>zCJod zU+9f|Y1-%&{i0`IpM=LA*aiFe-($58_QbCI#?II~B)-72=Ebhb+($qEA@jOmGn8N- zU8}C+{c$_RaYbE3{l~g<=EACRhx_bHKUnHUKMvZ;|1Lgi@0R{5)5xU+Lioc?@-tx9q{bu#r{wJ28@z(q0`n&m-!s~>?Q5~EOr53oJ-9+)R|ei#2ERA z5hFV5P12(7#D^|^eD0U|xjZsW!owebO%8D~zJ(u5`t8*?lr_)1Pdvn@@t7NdJn(eqV0=6ZN|Rya*4VZUmEfGI{1L^ z4ff%%ZYJxuig1MIJ>HM=igZYibo1tw@=;E|t&bkihpwN9>nqD|?15d>MqIHQ_Ve%Y zKX%66p|C|d;5nWT`(6Dzz&vx>eu*-lQ}4w2&v+K=NBc|P)E|##Y@9ag<#KL)S99T6 z@XC9PS?w?DYZM36h5Jh#I7a%htk-)$=IOHvJY;_zduDXbQsd>ym^tI#J!L%%>v!l| z4;eBfn$PFTZ|?J)a9z!15HInQ4(Vmh8{sGq<)VCkolp7ELlHe<2kha`abPd(hW-5U zQgnfxv3HsHNs9|S`}VN^t8*XSfJuD0h7x?%?$I$m1U?xn#%DC`RMw$hEMw!0aryhw zSr2oh^kZrJbu~Yh44|F`fum(U?Xk6RGH6dJL-5g`$pL_4t9J2PxN>35AY@7hT2ER-*3PD_HOmJ z!SeOjUmw+BexHDRz&pm&tF6~dx=+2!K3n#{Q5RAV(r0H~JoV#lBJhPPzq!wI!V#YL zc%OKZ(y8{0e3O65p}L}c)YX)?JKs#kBha%y|3KW>1G``!<-Kn^?5X*{Uf8=#{G`PN zo>d2SO|JXV&q;D_)KJ;y9ZF6SAJjUh_pee{uxG8B;O~~bf%uouxoYyvxH4-}nWyT` z_&a@A+KK-7I&~KH8FlYN#~kAxE+8}HUFO+YR|`kr1U`AV@|*iSCtQ(q$S3(F-&*IY zekfme#!k>DdPTp!e$YR5z#iD8n$5V6UC9S_#@?Z@MLOV_v`w<F-|^w`0#GwoOUkr^2Z2={BbwV);e3p+?Y3eM4mOOkU#S2p9Mxa zC{NsnNxV&8?Kj^G^ckOjK=0@uJE%>Pu0H>a(`=MDZ!-?-OS28h++jyB7E1T@B~{eb(2F9XmE!mj{1nH*?l@Ps!W&rOqBN z?eazw@&u;@$=Nu(t=ZsnBsS6qJqW)lQ zYqJUY&a?gqy`UfTq-`-Uj~>w{dPTpN%D5!H!t=^kI>sTfb3O3YPW)}=vKHaLelx)7 z`7-v+nsa}RE@RK^Q(^6S7H;_br#|E?P1-87Cyy1Mcl29mBM~S2UDlC;$w{f@skeekuK?z z5As94$RGLSTa}gnlo5Rpr_RBEAM}R)&?EX(-TM6J?2sWc-jGFnKPJtLPs@AuafI&Z z3jVWyy$k`joI}qTwLccl8dUg|wpQQgKWki>M?U}j^CKU7__}5v8$S4$N9X(t=G11- zo-Ie`EsXqIagM^ORjb_EwQJp5Z@uMy^{ZdGKm6ejj`QfZZ{O}d`Q(%6%5U!ToN$Ea zJ>JJp7V!};@skeekuK?z4}AWSFY-q|v+$pO0p&*z{@QEwguc)l`it9vc}dP4LD<_L ze_rjk?*HiyChVQsa;}l|TPFV%i=21IdGtMGe%&vt&K0nKJU;%#?^fkM?#m5L+ zjsKL7a#CK(tu{p;=mq_tr)oOn{urLcv|C{H#!CX9RL_>+r{ewr=ylVS0 z&lOzyc&qk5_-0KizPI9Y1^CtV=L%Yd|2n2m`TTYIlpj5yk2Kz^J}da2QRlqt^Ph2s zP}m|Je_TVqd3LS-J;DzS<4U1~^mOel{AYeCi%@4V_m8l@g>`RP1-!FA<#6T-WWHSS zz}PoqY2(I?i}vg>=0<Jz@PG;^Kr7gQ!Nbj;4m5UW}Zst3Ye?L2VOJQ|Gw`-$`hSO zAmyW+)pU^MK6+N2qyH@L5XR>}_6~(D(gDwmc_c|YeHWNZP7wjCrRHQ0hfBe=oL)E7xu6o z*Rh_a+1mf)oBS*9i|Rz*N6)Hr^so2RuF8MxjJ-o)i*&$q65e^%PW-?4;)`99TqI|? zg%tK^b@E^Or)gNy=aDML<`&6EGxMMP=P7TN zu;^KJj{dW}Lm1^hcE;YJuthrHISupe#Q!wk%hz0UO|-6*wWT41_L=d&-1WbFw;GlI z*gFKSG!5{ahWU2lf7;nAoGXQos8Djj1s8PAQ&CUg_bQ9f7G(_pLcNsbojhTvw~lYp z_CNV1|9Q%rB`kVYoumIO?+`}of94~xcPMO;4tP$(d^_=u9^IlPQp9S+KK;ZXRqVy4S!Lgg#MZO|AqgYU7bbz zx(Hlmc_&X8z7x${|C9eb<;@b-=Rf+-@(y9N{>RSPI~2A^2Rx@?zMc60?6c3hBw>FT zXTOCK&XH!FHa0l0oBYR@W>zd_4QKrS{PzPrYyIDy@qg@$y+dJ(bii{G-g(we{D0+@ zS6q^??}fGFp@cq~&;Lns#$*;@--_-N0GCC z0a@hhGVTw@uru}!g)Pzn&q;XaSv&E6_3G6wNuGG(iOAOk{w6{Q<1^}mg8F~5;5Li+ z{Kp?aOo^OR8mh(v97-xnv7Z(Cong)1I z!aL8}iT{86;~!m;yzs&cZt2pc!GtjyJy+%+Y5(6Lyvri=Mb!`WRq}t9ck+Y*zs<~l z@}H-?wG6BL|9kN_GJX2=VAul3;5iBJJZmTZfArBuE=g9dTIeLP zT_tr_78xae?oXC|oe1IY6#utn%4CVJsrg^BK8onp=l_fuGlF3Y9E0a1yz{J`_`hSv z4wodazy5mUdlvt*Aq1bc%74a*l+$^x^h=B2v#WRSfdAq{qZ#-AkZUJ;HTmgsn7Gu)x!U~1n*@^ zEAYQeeH4kScSrjU{^MIYB)-6N65e^%PW<1pWs6Iab?eqe{^#*QA40$b{X%STu*?rJ z$COvt>skb#UA;>^+06An`R}S+^|+_}=RCn#vt|Xsm0}k>C*hrE?Zp4Iv5*ZLHl)s% zrp>43dCvSSxWESBq#pR}Dox{mdEXD8|5@ha^WY~fEO<`Cd^_8#lU;!uky5|KU>q z-!130HiFzG`S`ac9seWW}=SMR*@PB2-r zWQp;=>Uzc;5iNR?ZkijUrF+dU;H9gP*jp;5iBJJZmTZr};ucUmtw%K`>!0i1EK%|DSxf8kPUpJ0!lqa~kH` ziT`Q75YboKdg(Hsvrgmd;!7f`|79KEkB>aEA>E&|3wANq+guU%GAEwgnT`XDk1Y@c2Jf&aIs$XE%lx(uFtoHaY*vKjo;m z9?1iCRsLh|koW@6NqFa3JMlm5EClqGwqK&m=d91>yh>~UPNsrck>%pI{pUaZX>fT; z{8N%X{5i2n=l{t!`KKI|ryhF5erikQKX%66W#T6-F7TX&`F7&}_rCW%mn7(G=gytM zg!P$S@qdl%3;OHteivL;-g#$B@t^Y4Lyy?6EB<5ekoW@6NqFa3JMn+$(4j6#-g@h; z)csOv`>FCgXN{)M|7lWZA#0WYG8eg3=5V&iJZ`OItMn0-Bk+avX}30W{ZIZWhtGe? zSt}h9FLwH?*b7}^KeeS_|6}hw_$V3{JSX9uXYIuQw6l=cuV3%BZ{HqF*uUZT{}nUJ z|3AxG#Ko6h>V9(CX*H8&S6t!#^6OtmxNTMbQ$EUBOFd#I>{X5b*cp3=#20u@!+bmO zpSiXqVXai!e#tVQzxwK{o%}yi`v3PGbyOtE|1I+Ue&XD7JMZiBGOzRHOsc<#A2@Kk z>aM$@w5Ccvnz{Zb|LBPFP%g?xIm^^rJTB~ny_Em@9J|6X_>aBI#7|mW;5iBJI``a8 z-+-jD;xlRU=FP$6XFvN{=lp*K|HV%fIHFxyZ~ph{)hjx;p0jH?Q=T)U$BY>hon`T( zAN?pgUvl!~$`}e8q-9y{)bb| zB;=d?Qx3oWr<}FWpT>!u_+G<*?5Fp&{)hkAJ0!lqvvItV<4O8>>ZzyP?|=XMVDj8^ z&vmZ<2PcXdvyC+TDU{P~VGlc9t@Zxa9iEbYl4{O=h5SNIGO{J@PHH!eDd8eix5zomb_XwjnR%5Uy-PBq~O&wJR2c!)1=9{li~ z{Fm~D;6L`#_P^%C=Rfuig)Pzn&q;WK>hz5*`tShK-S+P>!ts= zL;4}$X`a-TdcPLeCojCvZ5Mu!-fL1{7D?kqX)lz?f8r~WAId|yC?Dl45?9*0*a>@) z9`@7l*cF~(XY5@je$wIs&&Kgejwk5@|E%~-3ndE{EHM5j)c>ucr%|9q)e^nNX_i(>VEku=7aT>leak^K1e zKjkbESK7PSN$Y>?r{S?HJj2g3_AV1YX>oyP<9H>a z@gIAK!WQX(=Onz_v&wG+=d-a!Bb2btg|Tkz0RJD7x*v(x|9Za`SHJ#$UHZ#K(x^rK zUnD=2NBjSjvq)TN@5bwY4X^dTp8pdHTciV?jpLOZPtwN&4?Ga9(O{iM2$?x^W-9*| zNV`(8REukw{J*K>_CN6zDRW5vV<*4;ule@*kG(_SO49((NqDzsmEVT@?z=Bqi^_V` z5W*T)t^bdf`hSM_{6OB6`_x-oWk1P+5hFV9>+>?Ni${&>9RGiP%9KKB)q?*;%1U{( z{->Np;!1lLJ7F)vyC+P!UN%&|EB@aIMVCVUN)%d^A z_}|GTr>GBlZr3Ez$wcNqDzsmEVTDq`$}<;r}C2_ai@-e&WZ{kK88x$tR`$*ZZ}& zE|Gc>evsa3!Do>);Om!5TK`Kt#8)Igl!tOrKFV1nuC#Zt6ZRrK?5E+i{>RSPI|QyY z4e)FnujF`=KGfArhmc8Fj9FOqsi@7LnGG*KED~4RyV%LE|24eU z|JWIOhr$-=fM?@)CC8KWF?Q@&cc=Kk3?)}zeYM-C<9z62q}`uxX!8XmiXIqZzRLt%?_z;hDb?OElw;ZpJ8c*`xf1QYDD z_uhL)Hmb(|#R2)hM*7Q&+wNR%DY^b9zV75h-=RF(|K~fW_iJ&*PFnwW#eeLKy+h&) zJR8R=Ii94CQGyZnp@)*uqer{F_S&ni{9op^|67^=l(QDR*ErMokDal1C~T1qcuvB* zJ*)gSoOj-NQ5%hRS_r{DKL39rZGXgX|34-5ir%lqHO~JcY1E?rFOna>{->Np;!1lL zJNfm$hS&B#cE;WzaHVO0XXAJ!$CLDdZz_DygcAJM?z!ilk&O-!d|WO5u8`+s-R73x z{KjpT`J`uVxWUc6=%Sj*3h}G^k@&|Vy~VfQ+L;H%0sy*ALXp295==OM zWsg1f_?(Syy6GnOj$kRYlsR5hl>cR5lk$YtA?abic>b|7_6~_J@Ep&F{jTJ^uMhlC zjvP5Mm<%2~xJ&+zA3xr`Exx2e3w4ICk0Sp!0{o5%lymBI4nS?ww{PF*d<)LF2r1-6^HB8K2>ho!A@!$e_3PKK zLXX&&ykPGTxY9Jhb5T3C)BFAV_m95Oe5XT-`T%VuT{i;%8%3Y^cn*mtO$$6XiVm6~ zAIBbhtUKkDQ-X{70B8msWzD1U|Fd=`KHlnqEAX7vUKZ{PQ5)@q6HaiUMfU)XV0F&W%u28Z@KTZ@&7aaW8Zq<%Fg%w%m&psZ})4X zBjbN<^lErDy*2{|jQ@tyX27ZCu{Jn0{?|sYhF8;TGho2@Z#ZoRoLU}hgHz*wZS-n* zHN7?i2H^i?mt7Y5yulA8zNjC0{c`_jyh@!t>sr{`4oeV8MdU zvr)|s`Rri&GJVwp1MG2IyLPSn@WT%a@t^nCtXUK7nX5-REKTE&VIV&S^o%Ro_%FWr zqFcFgrF-LzH{7~)>)ghT8zWzw@4fe)`;GX><%+LN?(>{*gy+3w%a%oc^7U*qvqgSe zn9fXRwZH)DbMR+_&oYGnckS@`U90gw;wK&aGa#h9+ittrIzjO(UJDyroTk?}26owH z7l%J79oJ*54&h8|U9(#&{u4jxXqsGEFMQl_$GIZ3K<^T z507T^ur|k+yw7|6zux>m@x&92|5pDS25O7}&ab)h$}8Q>nKLWC1NG$p<(FS>YlLfT zcdKW^*0YVQZ@vNF`qsA``*#No8Wag?r=Na$XPRf8d8XrxB=Xb9 z`m($kciIU9@SpSTZjiHZCrz5vx$gh5#~yQY=FExwek@+Ij9UC$oBmtK0Qa}DtN_3JCv0PEUc?(5oL!t);QUwiGf*8aD# zJ^TJQ5e8~C{%7C##`(sZEzB0xFkt*QY*fRB-EVzt82?+}#>Qi_aWxDW{|y_}uwnOG z9~;L1*0-_o*lb)41IB;DMm22M{np2Z@xS$LY&jJp)TYUf%j_~;Qm@r{NbPfRVRZGk68x9QvjfDYxbm9B24FA7; z8;H+r+*md?dzd|{VPOCL_jjz@EyMpWYXXU{T3UABaA+84EDX?I=NvEg^wAE`w*IPB ztD^71h7B9srcImNyYIdmUHQ%Tg6FLLB|PuVojccEb=6h2{XZ&vrI~X6#4)wqQe){pvzu$iQMQ8UMaKHiXpo0!_ha7TGHFkl!k3>XGV$AGBR{!9a= z0n>nKz%*bQFb$XnOarC?(|~EfG+-Jq4VVT@1EvAffN8)qU>YzDm{2#ZL2l4;_ diff --git a/代码/robocode/robocode.content/target/classes/robocode.sh b/代码/robocode/robocode.content/target/classes/robocode.sh deleted file mode 100644 index 81ca7de..0000000 --- a/代码/robocode/robocode.content/target/classes/robocode.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -# - -pwd=`pwd` -cd "${0%/*}" -java -Xmx512M -cp libs/robocode.jar robocode.Robocode $* -cd "${pwd}" diff --git a/代码/robocode/robocode.content/target/classes/roborumble.bat b/代码/robocode/robocode.content/target/classes/roborumble.bat deleted file mode 100644 index e056ed9..0000000 --- a/代码/robocode/robocode.content/target/classes/roborumble.bat +++ /dev/null @@ -1,9 +0,0 @@ -@REM -@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -@REM All rights reserved. This program and the accompanying materials -@REM are made available under the terms of the Eclipse Public License v1.0 -@REM which accompanies this distribution, and is available at -@REM http://robocode.sourceforge.net/license/epl-v10.html -@REM - -java -Xmx512M -cp libs/robocode.jar;libs/roborumble.jar;libs/codesize-1.1.jar; roborumble.RoboRumbleAtHome ./roborumble/roborumble.txt \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/roborumble.command b/代码/robocode/robocode.content/target/classes/roborumble.command deleted file mode 100644 index 27f9f4b..0000000 --- a/代码/robocode/robocode.content/target/classes/roborumble.command +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -################################################################################ -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -################################################################################ - -pwd=`pwd` -cd "${0%/*}" -java -Xdock:icon=roborumble.ico -Xdock:name=RoboRumble -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/roborumble.txt -cd "${pwd}" diff --git a/代码/robocode/robocode.content/target/classes/roborumble.ico b/代码/robocode/robocode.content/target/classes/roborumble.ico deleted file mode 100644 index 927ba6e4f14330fee367bc922e4ac6f3941bc752..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32038 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 diff --git a/代码/robocode/robocode.content/target/classes/roborumble.sh b/代码/robocode/robocode.content/target/classes/roborumble.sh deleted file mode 100644 index b0a4050..0000000 --- a/代码/robocode/robocode.content/target/classes/roborumble.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -# - -pwd=`pwd` -cd "${0%/*}" -java -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/roborumble.txt -cd "${pwd}" diff --git a/代码/robocode/robocode.content/target/classes/roborumble/meleerumble.txt b/代码/robocode/robocode.content/target/classes/roborumble/meleerumble.txt deleted file mode 100644 index 969673d..0000000 --- a/代码/robocode/robocode.content/target/classes/roborumble/meleerumble.txt +++ /dev/null @@ -1,244 +0,0 @@ -#=============================================================================== -# meleerumble.txt - Configuration file for MeleeRumble (melee battles) -#=============================================================================== - -#------------------------------------------------------------------------------- -# User property. It's highly recommendable that you change this to use your name -#------------------------------------------------------------------------------- - -# USER The user name used when uploading the results to the RoboRumble -# server. Hence, you should replace 'Put_Your_Name_Here' with your -# name, which could be the initials you use for your robot(s). - -USER=Put_Your_Name_Here - -#------------------------------------------------------------------------------- -# Exclude filter used for excluding participants. Use with care! -#------------------------------------------------------------------------------- - -# EXCLUDE A comma separated list of all the participants you want to exclude -# from the competition. Excluded participants will not be downloaded -# or take part in battles. This way you can exclude participants that -# cannot be downloaded due to web servers that are down or hanging, -# the repository is down, robots/teams that crashes for some reason or -# cause other trouble. -# -# You can use the filename wildcards * and ? in the filter. Example: -# -# EXCLUDE=xyz.*v1.?, *Nano* - -EXCLUDE= - -#------------------------------------------------------------------------------- -# Properties for controlling the rumble. Use YES or NOT -#------------------------------------------------------------------------------- - -# DOWNLOAD Download data like participants, missing robots, rating files etc. -# from Internet if these have not been downloaded for 2 hours. -# -# EXECUTE Execute battles. Battles files are first created and old battles -# files are deleted before the battles are executed. -# -# UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL -# property. -# -# ITERATE If set to NOT, the rumble will only execute battles once. -# If set to YES, the rumble will restart with new battles every time -# the battles have been executed, and it will run infinitely until -# terminated. - -DOWNLOAD=YES -EXECUTE=YES -UPLOAD=YES -ITERATE=YES - -# MELEE Must be set if this rumble is meant for melee battles. -# -# TEAMS Must be set if this rumble is meant for team battles. -# This flag is necessary, as jar files for robot teams are different -# from jar files for ordinary robots. - -# MELEE=YES as this property file is meant for melee battles. -# TEAM=NOT, as this property file is not meant for team battles. - -# Do not modify these properties! - -MELEE=YES -TEAMS=NOT - -#------------------------------------------------------------------------------ -# Properties for the battle engine -#------------------------------------------------------------------------------ - -# FIELDL Battlefield width measured in pixels. -# FIELDH Battlefield height measured in pixels. -# -# NUMBATTLES Number of battles performed per rumble. -# ROUNDS Number of rounds per battle. -# -# MELEEBOTS Number of robots that participate in a melee battle. - -# These are standard values for the MeleeRumble. Do not modify these properties! - -FIELDL=1000 -FIELDH=1000 -NUMBATTLES=3 -ROUNDS=35 -MELEEBOTS=10 - -# INPUT Input battles file that is generated by the rumble automatically. -# The rumble uses this file for selecting which robots that must -# battle against each other. -# -# OUTPUT Battle results file, which is the output of running the rumble. - -INPUT=./roborumble/temp/battlesmelee.txt -OUTPUT=./roborumble/files/resultsmelee.txt - -#------------------------------------------------------------------------------- -# Properties for retrieving robots from Internet -#------------------------------------------------------------------------------- - -# BOTSREP The robot repository where downloaded robots are put. -# -# TEMP Directory containing all temporary files for RoboRumble. - -BOTSREP=./robots/ -TEMP=./roborumble/temp/ - -#------------------------------------------------------------------------------- -# Properties for updating participants from Internet -#------------------------------------------------------------------------------- - -# PARTICIPANTSURL -# URL to the web page containing all participants of the competition, -# which will be used for updating the participants file specified with -# the PARTICIPANTSFILE property. -# -# PARTICIPANTSFILE -# File containing all the participants for the competition. -# -# STARTAG Tag marking the start and end of the participants on the web page -# pointed to with the PARTICIPANTSURL property. -# -# UPDATEBOTSURL -# URL used for removing old participants, which is used for updating -# the participants file specified with the PARTICIPANTSFILE property. - -PARTICIPANTSURL=http://robowiki.net/wiki/RoboRumble/Participants/Melee&action=raw -PARTICIPANTSFILE=./roborumble/files/participmelee.txt - -STARTAG=pre - -UPDATEBOTSURL=http://literumble.appspot.com/RemoveOldParticipant - -#------------------------------------------------------------------------------- -# Properties to control the way battles are run -#------------------------------------------------------------------------------- - -# RUNONLY If left black or set to GENERAL, a new battle file is created where -# robots from the participants file are paired at random. The number -# of robot pairs will match number of battles defined the NUMBATTLES -# property. -# -# If set to MINI, a new battle file is created similar to the one -# for GENERAL, but it will only contains robots that are MiniBots, -# which has a code size < 1500 bytes (calculated by the codesize tool). -# -# If set to MICRO, a new battle file is created similar to the one -# for GENERAL, but it will only contains robots that are MicroBots, -# which has a code size < 750 bytes (calculated by the codesize tool). -# -# If set to NANO, a new battle file is created similar to the one for -# GENERAL, but it will only contains robots that are NanoBots, which -# has a code size < 250 bytes (calculated by the codesize tool). -# -# If set to SERVER (recommended), a new battle file is created which -# will first of all contain priority battles for robots that that has -# priority over other robots until they have fought a specific number -# of battles specified by the BATTLESPERBOT property. The number of -# battles fought by the individual robots are extracted from the -# rating files, which are downloaded from the server if the DOWNLOAD -# property is set to YES. When no more priority battles are left, -# robots from the participants file are paired at random similar to -# GENERAL. -# -# BATTLESPERBOT -# The number of battles a robot has to fight before it will no longer -# have priority over other robots in battles. Prioritizing a robot -# makes its rating more reliable faster as its number of fought -# battles increases faster than when it is not prioritized. -# -# PRIORITYBATTLESFILE -# The priority battles file that is generated automatically by the -# rumble when the RUNONLY property is set to SERVER. - -RUNONLY=SERVER - -BATTLESPERBOT=2000 - -PRIORITYBATTLESFILE=./roborumble/temp/prioritymelee.txt - -#------------------------------------------------------------------------------- -# Properties for uploading the results to the server -#------------------------------------------------------------------------------- - -# RESULTSURL -# URL used for uploading the results to the server. -# -# BATTLESNUMFILE -# File containing the number of battles fought by the robots, which is -# returned by the server when results are uploaded to the server. - -RESULTSURL=http://literumble.appspot.com/UploadedResults - -BATTLESNUMFILE=./roborumble/temp/meleebattlesnumber.txt - -#------------------------------------------------------------------------------- -# Properties for related competitions -#------------------------------------------------------------------------------- - -# Related competitions are competitions where participants are a subset of the -# participants in the general competition. -# -# The MiniBots (code size < 1500) are participants of the MiniRumble. -# The MicroBots (code size < 750) are participants of the MicroRumble. -# The NanoBots (code size < 250) are participants of the NanoRumble. - -# Do not modify these properties! - -MINIBOTS=minimeleerumble -MICROBOTS=micromeleerumble -NANOBOTS=nanomeleerumble - -# CODESIZEFILE: -# The code size file that is generated automatically by the rumble in -# order determine the code size of each individual robot. - -CODESIZEFILE=./roborumble/files/codesizemelee.txt - -#------------------------------------------------------------------------------- -# Properties for URLs and file names for the rating files to download -#------------------------------------------------------------------------------- - -# RATINGS.URL: -# URL to where ratings files are located on Internet. -# -# RATINGS.GENERAL: -# File name for the rating file of the general MeleeRumble. -# -# RATINGS.MINIBOTS: -# File name for the rating file of the Melee MiniRumble. -# -# RATINGS.MICROBOTS: -# File name for the rating file of the Melee MicroRumble. -# -# RATINGS.NANOBOTS: -# File name for the rating file of the Melee NanoRumble. - -RATINGS.URL=http://literumble.appspot.com/RatingsFile - -RATINGS.GENERAL=./roborumble/temp/ratings_m_roborumble.txt -RATINGS.MINIBOTS=./roborumble/temp/ratings_m_minirumble.txt -RATINGS.MICROBOTS=./roborumble/temp/ratings_m_microrumble.txt -RATINGS.NANOBOTS=./roborumble/temp/ratings_m_nanorumble.txt diff --git a/代码/robocode/robocode.content/target/classes/roborumble/roborumble.properties b/代码/robocode/robocode.content/target/classes/roborumble/roborumble.properties deleted file mode 100644 index 1df0dea..0000000 --- a/代码/robocode/robocode.content/target/classes/roborumble/roborumble.properties +++ /dev/null @@ -1,6 +0,0 @@ -# Connection timeout in milliseconds -connection.open.timeout=10000 -# Connection read timeout in milliseconds -connection.read.timeout=10000 -# Download session timeout -download.session.timeout=10000 diff --git a/代码/robocode/robocode.content/target/classes/roborumble/roborumble.txt b/代码/robocode/robocode.content/target/classes/roborumble/roborumble.txt deleted file mode 100644 index ae45516..0000000 --- a/代码/robocode/robocode.content/target/classes/roborumble/roborumble.txt +++ /dev/null @@ -1,241 +0,0 @@ -#=============================================================================== -# roborumble.txt - Configuration file for RoboRumble (1v1 battles) -#=============================================================================== - -#------------------------------------------------------------------------------- -# Username. It's highly recommendable that you change this to use your name -#------------------------------------------------------------------------------- - -# USER The username used when uploading the results to the RoboRumble -# server. Hence, you should replace 'Put_Your_Name_Here' with your -# name, which could be the initials you use for your robot(s). - -USER=Put_Your_Name_Here - -#------------------------------------------------------------------------------- -# Exclude filter used for excluding participants. Use with care! -#------------------------------------------------------------------------------- - -# EXCLUDE A comma separated list of all the participants you want to exclude -# from the competition. Excluded participants will not be downloaded -# or take part in battles. This way you can exclude participants that -# cannot be downloaded due to web servers that are down or hanging, -# the repository is down, robots/teams that crashes for some reason or -# cause other trouble. -# -# You can use the filename wildcards * and ? in the filter. Example: -# -# EXCLUDE=xyz.*v1.?, *Nano* - -EXCLUDE= - -#------------------------------------------------------------------------------- -# Properties for controlling the rumble. Use YES or NOT -#------------------------------------------------------------------------------- - -# DOWNLOAD Download data like participants, missing robots, rating files etc. -# from Internet if these have not been downloaded for 2 hours. -# -# EXECUTE Execute battles. Battles files are first created and old battles -# files are deleted before the battles are executed. -# -# UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL -# property. -# -# ITERATE If set to NOT, the rumble will only execute battles once. -# If set to YES, the rumble will restart with new battles every time -# the battles have been executed, and it will run infinitely until -# terminated. - -DOWNLOAD=YES -EXECUTE=YES -UPLOAD=YES -ITERATE=YES - -# MELEE Must be set if this rumble is meant for melee battles. -# -# TEAMS Must be set if this rumble is meant for team battles. -# This flag is necessary, as jar files for robot teams are different -# from jar files for ordinary robots. - -# MELEE=NOT as this property file is not meant for melee battles. -# TEAM=NOT, as this property file is not meant for team battles. - -# Do not modify these properties! - -MELEE=NOT -TEAMS=NOT - -#------------------------------------------------------------------------------ -# Properties for the battle engine -#------------------------------------------------------------------------------ - -# FIELDL Battlefield width measured in pixels. -# FIELDH Battlefield height measured in pixels. -# -# NUMBATTLES Number of battles performed per rumble. -# ROUNDS Number of rounds per battle. - -# These are standard values for the RoboRumble. Do not modify these properties! - -FIELDL=800 -FIELDH=600 -NUMBATTLES=50 -ROUNDS=35 - -# INPUT Input battles file that is generated by the rumble automatically. -# The rumble uses this file for selecting which robots that must -# battle against each other. -# -# OUTPUT Battle results file, which is the output of running the rumble. - -INPUT=./roborumble/temp/battles1v1.txt -OUTPUT=./roborumble/files/results1v1.txt - -#------------------------------------------------------------------------------- -# Properties for retrieving robots from Internet -#------------------------------------------------------------------------------- - -# BOTSREP The robot repository where downloaded robots are put. -# -# TEMP Directory containing all temporary files for RoboRumble. - -BOTSREP=./robots/ -TEMP=./roborumble/temp/ - -#------------------------------------------------------------------------------- -# Properties for updating participants from Internet -#------------------------------------------------------------------------------- - -# PARTICIPANTSURL -# URL to the web page containing all participants of the competition, -# which will be used for updating the participants file specified with -# the PARTICIPANTSFILE property. -# -# PARTICIPANTSFILE -# File containing all the participants for the competition. -# -# STARTAG Tag marking the start and end of the participants on the web page -# pointed to with the PARTICIPANTSURL property. -# -# UPDATEBOTSURL -# URL used for removing old participants, which is used for updating -# the participants file specified with the PARTICIPANTSFILE property. - -PARTICIPANTSURL=http://robowiki.net/wiki/RoboRumble/Participants?action=raw -PARTICIPANTSFILE=./roborumble/files/particip1v1.txt - -STARTAG=pre - -UPDATEBOTSURL=http://literumble.appspot.com/RemoveOldParticipant - -#------------------------------------------------------------------------------- -# Properties to control the way battles are run -#------------------------------------------------------------------------------- - -# RUNONLY If left black or set to GENERAL, a new battle file is created where -# robots from the participants file are paired at random. The number -# of robot pairs will match number of battles defined the NUMBATTLES -# property. -# -# If set to MINI, a new battle file is created similar to the one -# for GENERAL, but it will only contains robots that are MiniBots, -# which has a code size < 1500 bytes (calculated by the codesize tool). -# -# If set to MICRO, a new battle file is created similar to the one -# for GENERAL, but it will only contains robots that are MicroBots, -# which has a code size < 750 bytes (calculated by the codesize tool). -# -# If set to NANO, a new battle file is created similar to the one for -# GENERAL, but it will only contains robots that are NanoBots, which -# has a code size < 250 bytes (calculated by the codesize tool). -# -# If set to SERVER (recommended), a new battle file is created which -# will first of all contain priority battles for robots that that has -# priority over other robots until they have fought a specific number -# of battles specified by the BATTLESPERBOT property. The number of -# battles fought by the individual robots are extracted from the -# rating files, which are downloaded from the server if the DOWNLOAD -# property is set to YES. When no more priority battles are left, -# robots from the participants file are paired at random similar to -# GENERAL. -# -# BATTLESPERBOT -# The number of battles a robot has to fight before it will no longer -# have priority over other robots in battles. Prioritizing a robot -# makes its rating more reliable faster as its number of fought -# battles increases faster than when it is not prioritized. -# -# PRIORITYBATTLESFILE -# The priority battles file that is generated automatically by the -# rumble when the RUNONLY property is set to SERVER. - -RUNONLY=SERVER - -BATTLESPERBOT=2000 - -PRIORITYBATTLESFILE=./roborumble/temp/priority1v1.txt - -#------------------------------------------------------------------------------- -# Properties for uploading the results to the server -#------------------------------------------------------------------------------- - -# RESULTSURL -# URL used for uploading the results to the server. -# -# BATTLESNUMFILE -# File containing the number of battles fought by the robots, which is -# returned by the server when results are uploaded to the server. - -RESULTSURL=http://literumble.appspot.com/UploadedResults - -BATTLESNUMFILE=./roborumble/temp/battlesnumber.txt - -#------------------------------------------------------------------------------- -# Properties for related competitions -#------------------------------------------------------------------------------- - -# Related competitions are competitions where participants are a subset of the -# participants in the general competition. -# -# The MiniBots (code size < 1500) are participants of the MiniRumble. -# The MicroBots (code size < 750) are participants of the MicroRumble. -# The NanoBots (code size < 250) are participants of the NanoRumble. - -# Do not modify these properties! - -MINIBOTS=minirumble -MICROBOTS=microrumble -NANOBOTS=nanorumble - -# CODESIZEFILE: -# The code size file that is generated automatically by the rumble in -# order determine the code size of each individual robot. - -CODESIZEFILE=./roborumble/files/codesize1v1.txt - -#------------------------------------------------------------------------------- -# Properties for URLs and file names for the rating files to download -#------------------------------------------------------------------------------- - -# RATINGS.URL: -# URL to where ratings files are located on Internet. -# -# RATINGS.GENERAL: -# File name for the rating file of the general RoboRumble. -# -# RATINGS.MINIBOTS: -# File name for the rating file of the MiniRumble. -# -# RATINGS.MICROBOTS: -# File name for the rating file of the MicroRumble. -# -# RATINGS.NANOBOTS: -# File name for the rating file of the NanoRumble. - -RATINGS.URL=http://literumble.appspot.com/RatingsFile - -RATINGS.GENERAL=./roborumble/temp/ratings_roborumble.txt -RATINGS.MINIBOTS=./roborumble/temp/ratings_minirumble.txt -RATINGS.MICROBOTS=./roborumble/temp/ratings_microrumble.txt -RATINGS.NANOBOTS=./roborumble/temp/ratings_nanorumble.txt diff --git a/代码/robocode/robocode.content/target/classes/roborumble/teamrumble.txt b/代码/robocode/robocode.content/target/classes/roborumble/teamrumble.txt deleted file mode 100644 index cf6262f..0000000 --- a/代码/robocode/robocode.content/target/classes/roborumble/teamrumble.txt +++ /dev/null @@ -1,203 +0,0 @@ -#=============================================================================== -# teamrumble.txt - Configuration file for TeamRumble (team battles) -#=============================================================================== - -#------------------------------------------------------------------------------- -# User property. It's highly recommendable that you change this to use your name -#------------------------------------------------------------------------------- - -# USER The user name used when uploading the results to the RoboRumble -# server. Hence, you should replace 'Put_Your_Name_Here' with your -# name, which could be the initials you use for your robot(s). - -USER=Put_Your_Name_Here - -#------------------------------------------------------------------------------- -# Exclude filter used for excluding participants. Use with care! -#------------------------------------------------------------------------------- - -# EXCLUDE A comma separated list of all the participants you want to exclude -# from the competition. Excluded participants will not be downloaded -# or take part in battles. This way you can exclude participants that -# cannot be downloaded due to web servers that are down or hanging, -# the repository is down, robots/teams that crashes for some reason or -# cause other trouble. -# -# You can use the filename wildcards * and ? in the filter. Example: -# -# EXCLUDE=xyz.*v1.?, *Nano* - -EXCLUDE= - -#------------------------------------------------------------------------------- -# Properties for controlling the rumble. Use YES or NOT -#------------------------------------------------------------------------------- - -# DOWNLOAD Download data like participants, missing robots, rating files etc. -# from Internet if these have not been downloaded for 2 hours. -# -# EXECUTE Execute battles. Battles files are first created and old battles -# files are deleted before the battles are executed. -# -# UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL -# property. -# -# ITERATE If set to NOT, the rumble will only execute battles once. -# If set to YES, the rumble will restart with new battles every time -# the battles have been executed, and it will run infinitely until -# terminated. - -DOWNLOAD=YES -EXECUTE=YES -UPLOAD=YES -ITERATE=YES - -# MELEE Must be set if this rumble is meant for melee battles. -# -# TEAMS Must be set if this rumble is meant for team battles. -# This flag is necessary, as jar files for robot teams are different -# from jar files for ordinary robots. - -# MELEE=NOT as this property file is not meant for melee battles. -# TEAM=YES, as this property file is meant for team battles. - -# Do not modify these properties! - -MELEE=NOT -TEAMS=YES - -#------------------------------------------------------------------------------ -# Properties for the battle engine -#------------------------------------------------------------------------------ - -# FIELDL Battlefield width measured in pixels. -# FIELDH Battlefield height measured in pixels. -# -# NUMBATTLES Number of battles performed per rumble. -# ROUNDS Number of rounds per battle. - -# These are standard values for the TeamRumble. Do not modify these properties! - -FIELDL=1200 -FIELDH=1200 -NUMBATTLES=10 -ROUNDS=10 - -# INPUT Input battles file that is generated by the rumble automatically. -# The rumble uses this file for selecting which robots that must -# battle against each other. -# -# OUTPUT Battle results file, which is the output of running the rumble. - -INPUT=./roborumble/temp/battlesTeams.txt -OUTPUT=./roborumble/files/resultsTeams.txt - -#------------------------------------------------------------------------------- -# Properties for retrieving robots from Internet -#------------------------------------------------------------------------------- - -# BOTSREP The robot repository where downloaded robots are put. -# -# TEMP Directory containing all temporary files for RoboRumble. - -BOTSREP=./robots/ -TEMP=./roborumble/temp/ - -#------------------------------------------------------------------------------- -# Properties for updating participants from Internet -#------------------------------------------------------------------------------- - -# PARTICIPANTSURL -# URL to the web page containing all participants of the competition, -# which will be used for updating the participants file specified with -# the PARTICIPANTSFILE property. -# -# PARTICIPANTSFILE -# File containing all the participants for the competition. -# -# STARTAG Tag marking the start and end of the participants on the web page -# pointed to with the PARTICIPANTSURL property. -# -# UPDATEBOTSURL -# URL used for removing old participants, which is used for updating -# the participants file specified with the PARTICIPANTSFILE property. - -PARTICIPANTSURL=http://robowiki.net/wiki/RoboRumble/Participants/Teams&action=raw -PARTICIPANTSFILE=./roborumble/files/participTeams.txt - -STARTAG=pre - -UPDATEBOTSURL=http://literumble.appspot.com/RemoveOldParticipant - -#------------------------------------------------------------------------------- -# Properties to control the way battles are run -#------------------------------------------------------------------------------- - -# RUNONLY If left black or set to GENERAL, a new battle file is created where -# robots from the participants file are paired at random. The number -# of robot pairs will match number of battles defined the NUMBATTLES -# property. -# -# If set to SERVER (recommended), a new battle file is created which -# will first of all contain priority battles for robots that that has -# priority over other robots until they have fought a specific number -# of battles specified by the BATTLESPERBOT property. The number of -# battles fought by the individual robots are extracted from the -# rating files, which are downloaded from the server if the DOWNLOAD -# property is set to YES. When no more priority battles are left, -# robots from the participants file are paired at random similar to -# GENERAL. -# -# BATTLESPERBOT -# The number of battles a robot has to fight before it will no longer -# have priority over other robots in battles. Prioritizing a robot -# makes its rating more reliable faster as its number of fought -# battles increases faster than when it is not prioritized. -# -# PRIORITYBATTLESFILE -# The priority battles file that is generated automatically by the -# rumble when the RUNONLY property is set to SERVER. - -RUNONLY=SERVER - -BATTLESPERBOT=200 - -PRIORITYBATTLESFILE=./roborumble/temp/priorityTeams.txt - -#------------------------------------------------------------------------------- -# Properties for uploading the results to the server -#------------------------------------------------------------------------------- - -# RESULTSURL -# URL used for uploading the results to the server. -# -# BATTLESNUMFILE -# File containing the number of battles fought by the robots, which is -# returned by the server when results are uploaded to the server. - -RESULTSURL=http://literumble.appspot.com/UploadedResults - -BATTLESNUMFILE=./roborumble/temp/teambattlesnumber.txt - -#------------------------------------------------------------------------------- -# Properties for URLs and file names for the rating files to download -#------------------------------------------------------------------------------- - -# RATINGS.URL: -# URL to where ratings files are located on Internet. -# -# RATINGS.GENERAL: -# File name for the rating file of the general RoboRumble. -# -# RATINGS.MINIBOTS: -# File name for the rating file of the MiniRumble. -# -# RATINGS.MICROBOTS: -# File name for the rating file of the MicroRumble. -# -# RATINGS.NANOBOTS: -# File name for the rating file of the NanoRumble. - -RATINGS.URL=http://literumble.appspot.com/RatingsFile - -RATINGS.GENERAL=./roborumble/temp/ratings_teamrumble.txt diff --git a/代码/robocode/robocode.content/target/classes/roborumble/twinduel.txt b/代码/robocode/robocode.content/target/classes/roborumble/twinduel.txt deleted file mode 100644 index 8fc223b..0000000 --- a/代码/robocode/robocode.content/target/classes/roborumble/twinduel.txt +++ /dev/null @@ -1,203 +0,0 @@ -#=============================================================================== -# twinduel.txt - Configuration file for TwinDuel (rumble edition) -#=============================================================================== - -#------------------------------------------------------------------------------- -# User property. It's highly recommendable that you change this to use your name -#------------------------------------------------------------------------------- - -# USER The user name used when uploading the results to the RoboRumble -# server. Hence, you should replace 'Put_Your_Name_Here' with your -# name, which could be the initials you use for your robot(s). - -USER=Put_Your_Name_Here - -#------------------------------------------------------------------------------- -# Exclude filter used for excluding participants. Use with care! -#------------------------------------------------------------------------------- - -# EXCLUDE A comma separated list of all the participants you want to exclude -# from the competition. Excluded participants will not be downloaded -# or take part in battles. This way you can exclude participants that -# cannot be downloaded due to web servers that are down or hanging, -# the repository is down, robots/teams that crashes for some reason or -# cause other trouble. -# -# You can use the filename wildcards * and ? in the filter. Example: -# -# EXCLUDE=xyz.*v1.?, *Nano* - -EXCLUDE= - -#------------------------------------------------------------------------------- -# Properties for controlling the rumble. Use YES or NOT -#------------------------------------------------------------------------------- - -# DOWNLOAD Download data like participants, missing robots, rating files etc. -# from Internet if these have not been downloaded for 2 hours. -# -# EXECUTE Execute battles. Battles files are first created and old battles -# files are deleted before the battles are executed. -# -# UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL -# property. -# -# ITERATE If set to NOT, the rumble will only execute battles once. -# If set to YES, the rumble will restart with new battles every time -# the battles have been executed, and it will run infinitely until -# terminated. - -DOWNLOAD=YES -EXECUTE=YES -UPLOAD=YES -ITERATE=YES - -# MELEE Must be set if this rumble is meant for melee battles. -# -# TEAMS Must be set if this rumble is meant for team battles. -# This flag is necessary, as jar files for robot teams are different -# from jar files for ordinary robots. - -# MELEE=NOT as this property file is not meant for melee battles. -# TEAM=YES, as this property file is meant for team battles. - -# Do not modify these properties! - -MELEE=NOT -TEAMS=YES - -#------------------------------------------------------------------------------ -# Properties for the battle engine -#------------------------------------------------------------------------------ - -# FIELDL Battlefield width measured in pixels. -# FIELDH Battlefield height measured in pixels. -# -# NUMBATTLES Number of battles performed per rumble. -# ROUNDS Number of rounds per battle. - -# These are standard values for the TeamRumble. Do not modify these properties! - -FIELDL=800 -FIELDH=800 -NUMBATTLES=10 -ROUNDS=75 - -# INPUT Input battles file that is generated by the rumble automatically. -# The rumble uses this file for selecting which robots that must -# battle against each other. -# -# OUTPUT Battle results file, which is the output of running the rumble. - -INPUT=./roborumble/temp/battlesTwinduel.txt -OUTPUT=./roborumble/files/resultsTwinduel.txt - -#------------------------------------------------------------------------------- -# Properties for retrieving robots from Internet -#------------------------------------------------------------------------------- - -# BOTSREP The robot repository where downloaded robots are put. -# -# TEMP Directory containing all temporary files for RoboRumble. - -BOTSREP=./robots/ -TEMP=./roborumble/temp/ - -#------------------------------------------------------------------------------- -# Properties for updating participants from Internet -#------------------------------------------------------------------------------- - -# PARTICIPANTSURL -# URL to the web page containing all participants of the competition, -# which will be used for updating the participants file specified with -# the PARTICIPANTSFILE property. -# -# PARTICIPANTSFILE -# File containing all the participants for the competition. -# -# STARTAG Tag marking the start and end of the participants on the web page -# pointed to with the PARTICIPANTSURL property. -# -# UPDATEBOTSURL -# URL used for removing old participants, which is used for updating -# the participants file specified with the PARTICIPANTSFILE property. - -PARTICIPANTSURL=http://robowiki.net/wiki/RoboRumble/Participants/TwinDuel -PARTICIPANTSFILE=./roborumble/files/participTwinduel.txt - -STARTAG=pre - -UPDATEBOTSURL=http://literumble.appspot.com/RemoveOldParticipant - -#------------------------------------------------------------------------------- -# Properties to control the way battles are run -#------------------------------------------------------------------------------- - -# RUNONLY If left black or set to GENERAL, a new battle file is created where -# robots from the participants file are paired at random. The number -# of robot pairs will match number of battles defined the NUMBATTLES -# property. -# -# If set to SERVER (recommended), a new battle file is created which -# will first of all contain priority battles for robots that that has -# priority over other robots until they have fought a specific number -# of battles specified by the BATTLESPERBOT property. The number of -# battles fought by the individual robots are extracted from the -# rating files, which are downloaded from the server if the DOWNLOAD -# property is set to YES. When no more priority battles are left, -# robots from the participants file are paired at random similar to -# GENERAL. -# -# BATTLESPERBOT -# The number of battles a robot has to fight before it will no longer -# have priority over other robots in battles. Prioritizing a robot -# makes its rating more reliable faster as its number of fought -# battles increases faster than when it is not prioritized. -# -# PRIORITYBATTLESFILE -# The priority battles file that is generated automatically by the -# rumble when the RUNONLY property is set to SERVER. - -RUNONLY=SERVER - -BATTLESPERBOT=200 - -PRIORITYBATTLESFILE=./roborumble/temp/priorityTwinduel.txt - -#------------------------------------------------------------------------------- -# Properties for uploading the results to the server -#------------------------------------------------------------------------------- - -# RESULTSURL -# URL used for uploading the results to the server. -# -# BATTLESNUMFILE -# File containing the number of battles fought by the robots, which is -# returned by the server when results are uploaded to the server. - -RESULTSURL=http://literumble.appspot.com/UploadedResults - -BATTLESNUMFILE=./roborumble/temp/twinduelbattlesnumber.txt - -#------------------------------------------------------------------------------- -# Properties for URLs and file names for the rating files to download -#------------------------------------------------------------------------------- - -# RATINGS.URL: -# URL to where ratings files are located on Internet. -# -# RATINGS.GENERAL: -# File name for the rating file of the general RoboRumble. -# -# RATINGS.MINIBOTS: -# File name for the rating file of the MiniRumble. -# -# RATINGS.MICROBOTS: -# File name for the rating file of the MicroRumble. -# -# RATINGS.NANOBOTS: -# File name for the rating file of the NanoRumble. - -RATINGS.URL=http://literumble.appspot.com/RatingsFile - -RATINGS.GENERAL=./roborumble/temp/ratings_twinduel.txt diff --git a/代码/robocode/robocode.content/target/classes/teamrumble.bat b/代码/robocode/robocode.content/target/classes/teamrumble.bat deleted file mode 100644 index 3d97f1f..0000000 --- a/代码/robocode/robocode.content/target/classes/teamrumble.bat +++ /dev/null @@ -1,9 +0,0 @@ -@REM -@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -@REM All rights reserved. This program and the accompanying materials -@REM are made available under the terms of the Eclipse Public License v1.0 -@REM which accompanies this distribution, and is available at -@REM http://robocode.sourceforge.net/license/epl-v10.html -@REM - -java -Xmx512M -cp libs/robocode.jar;libs/roborumble.jar;libs/codesize-1.1.jar; roborumble.RoboRumbleAtHome ./roborumble/teamrumble.txt \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/teamrumble.command b/代码/robocode/robocode.content/target/classes/teamrumble.command deleted file mode 100644 index c103230..0000000 --- a/代码/robocode/robocode.content/target/classes/teamrumble.command +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -################################################################################ -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -################################################################################ - -pwd=`pwd` -cd "${0%/*}" -java -Xdock:icon=roborumble.ico -Xdock:name=TeamRumble -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/teamrumble.txt -cd "${pwd}" diff --git a/代码/robocode/robocode.content/target/classes/teamrumble.sh b/代码/robocode/robocode.content/target/classes/teamrumble.sh deleted file mode 100644 index 96b6e82..0000000 --- a/代码/robocode/robocode.content/target/classes/teamrumble.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -# - -pwd=`pwd` -cd "${0%/*}" -java -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/teamrumble.txt -cd "${pwd}" diff --git a/代码/robocode/robocode.content/target/classes/templates/newjavafile.tpt b/代码/robocode/robocode.content/target/classes/templates/newjavafile.tpt deleted file mode 100644 index b5bbc36..0000000 --- a/代码/robocode/robocode.content/target/classes/templates/newjavafile.tpt +++ /dev/null @@ -1,8 +0,0 @@ -package $PACKAGE; - -/** - * $CLASSNAME - a class by (your name here) - */ -public class $CLASSNAME -{ -} diff --git a/代码/robocode/robocode.content/target/classes/templates/newjuniorrobot.tpt b/代码/robocode/robocode.content/target/classes/templates/newjuniorrobot.tpt deleted file mode 100644 index c7f0ec8..0000000 --- a/代码/robocode/robocode.content/target/classes/templates/newjuniorrobot.tpt +++ /dev/null @@ -1,54 +0,0 @@ -package $PACKAGE; -import robocode.*; - -// API help : http://robocode.sourceforge.net/docs/robocode/robocode/JuniorRobot.html - -/** - * $CLASSNAME - a robot by (your name here) - */ -public class $CLASSNAME extends JuniorRobot -{ - /** - * run: $CLASSNAME's default behavior - */ - public void run() { - // Initialization of the robot should be put here - - // Some color codes: blue, yellow, black, white, red, pink, brown, grey, orange... - // Sets these colors (robot parts): body, gun, radar, bullet, scan_arc - setColors(orange, blue, white, yellow, black); - - // Robot main loop - while(true) { - // Replace the next 4 lines with any behavior you would like - ahead(100); - turnGunRight(360); - back(100); - turnGunRight(360); - } - } - - /** - * onScannedRobot: What to do when you see another robot - */ - public void onScannedRobot() { - // Replace the next line with any behavior you would like - fire(1); - } - - /** - * onHitByBullet: What to do when you're hit by a bullet - */ - public void onHitByBullet() { - // Replace the next line with any behavior you would like - back(10); - } - - /** - * onHitWall: What to do when you hit a wall - */ - public void onHitWall() { - // Replace the next line with any behavior you would like - back(20); - } -} diff --git a/代码/robocode/robocode.content/target/classes/templates/newrobot.tpt b/代码/robocode/robocode.content/target/classes/templates/newrobot.tpt deleted file mode 100644 index 070e471..0000000 --- a/代码/robocode/robocode.content/target/classes/templates/newrobot.tpt +++ /dev/null @@ -1,56 +0,0 @@ -package $PACKAGE; -import robocode.*; -//import java.awt.Color; - -// API help : http://robocode.sourceforge.net/docs/robocode/robocode/Robot.html - -/** - * $CLASSNAME - a robot by (your name here) - */ -public class $CLASSNAME extends Robot -{ - /** - * run: $CLASSNAME's default behavior - */ - public void run() { - // Initialization of the robot should be put here - - // After trying out your robot, try uncommenting the import at the top, - // and the next line: - - // setColors(Color.red,Color.blue,Color.green); // body,gun,radar - - // Robot main loop - while(true) { - // Replace the next 4 lines with any behavior you would like - ahead(100); - turnGunRight(360); - back(100); - turnGunRight(360); - } - } - - /** - * onScannedRobot: What to do when you see another robot - */ - public void onScannedRobot(ScannedRobotEvent e) { - // Replace the next line with any behavior you would like - fire(1); - } - - /** - * onHitByBullet: What to do when you're hit by a bullet - */ - public void onHitByBullet(HitByBulletEvent e) { - // Replace the next line with any behavior you would like - back(10); - } - - /** - * onHitWall: What to do when you hit a wall - */ - public void onHitWall(HitWallEvent e) { - // Replace the next line with any behavior you would like - back(20); - } -} diff --git a/代码/robocode/robocode.content/target/classes/theme/editor/Robocode Black Theme.properties b/代码/robocode/robocode.content/target/classes/theme/editor/Robocode Black Theme.properties deleted file mode 100644 index bd627b6..0000000 --- a/代码/robocode/robocode.content/target/classes/theme/editor/Robocode Black Theme.properties +++ /dev/null @@ -1,23 +0,0 @@ -#Robocode Editor Theme Properties -#Sun Sep 15 22:13:41 CEST 2013 -editor.theme=Robocode Black Theme -editor.font.name=Monospaced -editor.font.size=14 -editor.background.color=000000 -editor.lineNumber.background.color=22222 -editor.lineNumber.text.color=00CC00 -editor.highlighted.line.color=999999 -editor.selected.text.color=993300 -editor.selected.background.color=FFFFFF -editor.text.style.normal=Plain -editor.text.color.normal=00FFFF -editor.text.style.keyword=Bold -editor.text.color.keyword=0000FF -editor.text.style.literal=Plain -editor.text.color.literal=FFFF00 -editor.text.style.comment=Italic -editor.text.color.comment=00FF00 -editor.text.style.quoted=Plain -editor.text.color.quoted=FF0000 -editor.text.style.annotation=Plain -editor.text.color.annotation=FF00FF diff --git a/代码/robocode/robocode.content/target/classes/theme/editor/Robocode White Theme.properties b/代码/robocode/robocode.content/target/classes/theme/editor/Robocode White Theme.properties deleted file mode 100644 index 0eecd3e..0000000 --- a/代码/robocode/robocode.content/target/classes/theme/editor/Robocode White Theme.properties +++ /dev/null @@ -1,23 +0,0 @@ -#Robocode Editor Theme Properties -#Wed Jul 31 14:51:10 CEST 2013 -editor.theme=Robocode White Theme -editor.font.name=Monospaced -editor.font.size=14 -editor.background.color=FFFFFF -editor.lineNumber.background.color=EEEEEE -editor.lineNumber.text.color=000000 -editor.highlighted.line.color=FFFFCC -editor.selected.text.color=FFFFFF -editor.selected.background.color=3399FF -editor.text.style.normal=Plain -editor.text.color.normal=000000 -editor.text.style.keyword=Bold -editor.text.color.keyword=0000AF -editor.text.style.literal=Bold -editor.text.color.literal=0000AF -editor.text.style.comment=Plain -editor.text.color.comment=00AF00 -editor.text.style.quoted=Plain -editor.text.color.quoted=7F0000 -editor.text.style.annotation=Plain -editor.text.color.annotation=7F7F7F diff --git a/代码/robocode/robocode.content/target/classes/twinduel.bat b/代码/robocode/robocode.content/target/classes/twinduel.bat deleted file mode 100644 index c5573f2..0000000 --- a/代码/robocode/robocode.content/target/classes/twinduel.bat +++ /dev/null @@ -1,9 +0,0 @@ -@REM -@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -@REM All rights reserved. This program and the accompanying materials -@REM are made available under the terms of the Eclipse Public License v1.0 -@REM which accompanies this distribution, and is available at -@REM http://robocode.sourceforge.net/license/epl-v10.html -@REM - -java -Xmx512M -cp libs/robocode.jar;libs/roborumble.jar;libs/codesize-1.1.jar; roborumble.RoboRumbleAtHome ./roborumble/twinduel.txt \ No newline at end of file diff --git a/代码/robocode/robocode.content/target/classes/twinduel.command b/代码/robocode/robocode.content/target/classes/twinduel.command deleted file mode 100644 index a61c9e8..0000000 --- a/代码/robocode/robocode.content/target/classes/twinduel.command +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -################################################################################ -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -################################################################################ - -pwd=`pwd` -cd "${0%/*}" -java -Xdock:icon=roborumble.ico -Xdock:name=TwinDuel -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/twinduel.txt -cd "${pwd}" diff --git a/代码/robocode/robocode.content/target/classes/twinduel.sh b/代码/robocode/robocode.content/target/classes/twinduel.sh deleted file mode 100644 index 1669b1b..0000000 --- a/代码/robocode/robocode.content/target/classes/twinduel.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors -# All rights reserved. This program and the accompanying materials -# are made available under the terms of the Eclipse Public License v1.0 -# which accompanies this distribution, and is available at -# http://robocode.sourceforge.net/license/epl-v10.html -# - -pwd=`pwd` -cd "${0%/*}" -java -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/twinduel.txt -cd "${pwd}" diff --git a/代码/robocode/robocode.installer/target/classes/net/sf/robocode/installer/AutoExtract$1.class b/代码/robocode/robocode.installer/target/classes/net/sf/robocode/installer/AutoExtract$1.class deleted file mode 100644 index 2e47a107adc0a14c1e01368f1b23079fc2363766..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 877 zcma)4O>fgc5Pcgvbx7T>&=yMgZcCHU)B=t{NT@0jlG`3q6^Yx%UK)q3UD=z$Z{dK1 zxc0)ONF4Y9{3e8Wc7kZ&(!=iT?CiXG^Jahi`t}{bV|Wfq0voY1UiQXIlU@=eq4J_Q zGg51nde4U@*?DhL8JM+44s3z>fjpI-mhq9d-y5jFIG7SxE^ed5dl6|B%VR}rR4Op_ zG>RkhOu%Y14+ZRP;#Xl|+J%FPz?>h&YHxVlQ|W>1X(dqelR)Z2nMS!kzO+q0$^@GJ zC8>5;Sq6bRF#@X%|0282$SXSNnly@!I?dNrT*Z=u#fkn#Q5Va&CNOOhKY6FpZJCke zVx###Oa&|KaBCpb9Io!-CT{! zU-8G(88a$lmor@>gSWf#WUN@Vn+($+p92%;FU*nrP9=rki36QvY=2joeiAxp39MgA zUKg8avtp>UGHPFke$?Y|7XHyWpSSxmj;WcJS*9}F1v}&_^YfLs_yg!&;pqvjpe?t) zqWYx>yWFe!Gw~5NgEREq(Id=ajvo8M0{0wX$d@*4ee)c(y>{*TIc|KwY`b>5IFzk3 z`;1|W5Px7lp)5WZu&q(*7?vPpdao!|$9=34y39|o#*>A0=9BeLtT-I9g$MLY*g%8U OMiURQRa6-D!{cvbc*hz5 diff --git a/代码/robocode/robocode.installer/target/classes/net/sf/robocode/installer/AutoExtract.class b/代码/robocode/robocode.installer/target/classes/net/sf/robocode/installer/AutoExtract.class deleted file mode 100644 index b25dbc80c06fd32f7a7c692ef0856cbb90d0f725..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21469 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 JGdA<*zX4s@r-uLl diff --git a/代码/robocode/robocode.samples/target/classes/sample/Corners.class b/代码/robocode/robocode.samples/target/classes/sample/Corners.class deleted file mode 100644 index 5b8935854a8ac104a1b9a3b12db728de5d34b697..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2603 zcmaJ?YjYG;5IvJDvzyIL2oOL?3@fN4izI^b&;$t(9;*>B!SEFe}I1RXZQpBNQtLsmQBFYRPEe*yZd&ZKHazT+uuL`3SbSU z#Ct~&_JRu>)5UxJZYf5vungaY%5(gfPNL?Fb&Kdv|YWcJT|KRz1FCs4a^_(vX(Pq z`L>*^LbES)lSDlhD9l5n_*kfrKm(ly1)G3c2Jgh*%b&Gwe#Os zXnPq~;`oxyA0~BYx(ZhXSiC3Ko4YQlD$REclKNtH|b zc8)@1t@&ng&xbhdmHn*VZp*|~)q&qFC^+$01r|nroC^FVWK@Tx;<)7+rzD9++9{qM zaU~e8aH*A%dZ)VJJ1qJz!Rr-^-3RYzb3gtCsQb!*v(m$Z}B9;(`m0npvt^%8Thd*x`jkiS- zI-)NMy`S_QWL}4`fG!tvM7AM^4vxo%kPkyIiriO23*kOW3@!x4P}dRXp7XE@=PYGX z^0g~k5uCq-X2u_H#pH!Ah+%F8uS}zzsuSlgqlu)P3?)hKPH{H_u7j`ukD!X|r@JR(1E4ajrYPzrP(#>R) z=A)FxiQ@!oehN$RI;(t|9r^~VJcZpjgCV>{D&Luvom0!sAp_scWS3agb`MYA(q|pM F`v+en99IAU diff --git a/代码/robocode/robocode.samples/target/classes/sample/Corners.properties b/代码/robocode/robocode.samples/target/classes/sample/Corners.properties deleted file mode 100644 index 86a295d..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/Corners.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Sun Aug 20 21:14:27 EST 2006 -robot.description=\ A sample robot\n Moves to a corner, then swings the gun back and forth.\n If it dies, it tries a new corner in the next round. -robot.webpage= -robocode.version=1.1.2 -robot.java.source.included=true -robot.author.name=Mathew Nelson and Flemming N. Larsen -robot.classname=sample.Corners -robot.name=Corners diff --git a/代码/robocode/robocode.samples/target/classes/sample/Crazy.class b/代码/robocode/robocode.samples/target/classes/sample/Crazy.class deleted file mode 100644 index fda7610db2e0c1e7cbfda176c0017df3033b5c92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1729 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 YL3|#-H&n$pge&+ZaT)j(@6_SyS2+oTRsaA1 diff --git a/代码/robocode/robocode.samples/target/classes/sample/Interactive.properties b/代码/robocode/robocode.samples/target/classes/sample/Interactive.properties deleted file mode 100644 index 66603d1..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/Interactive.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Wed Jun 27 23:08:48 EST 2007 -robot.description=\ A sample robot\n\n This is a robot that is controlled using the arrow keys and mouse only -robot.webpage= -robocode.version=1.3.4 -robot.java.source.included=true -robot.author.name=Flemming N. Larsen -robot.classname=sample.Interactive -robot.name=Interactive \ No newline at end of file diff --git a/代码/robocode/robocode.samples/target/classes/sample/Interactive_v2$Direction.class b/代码/robocode/robocode.samples/target/classes/sample/Interactive_v2$Direction.class deleted file mode 100644 index 6f5b802a50faf5488aed715b765cb48c601f0bc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1205 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 NULM(TwqGv5|V? zZ8#&LAaURUcn}_gGV5ANCBTQ>nVp^A%zxHDe}Df0U<*$(NH8o-#L1~ETL)+Rjz0(85j(UKAE;Rl&wns4%3&Sc)MvR*wTq9LqYugV0y6LUrhj#(~bb$#F{ujDfH}Fywmy?FZsC z?$Gp9&lXC_VKkF0WmGxVuuiDSMPOHrv_RI;xJ{0`8kddh9C`Y*&e4EHMUEYxt{U~1 zdTM!3y>^23Svz!H8EEtaj;2PJ$Mf^Hq?xIa#ysSBge^+c@LjF2D~|(GO9RlrT+a)A zTkbo$pUU4a+I%lQ3RH zgE>o95e%qVSv|Qrw%w6; z>U110g@nMO%VpQ;$!f4CV7#`K?Hvfji>0g*Qm^NDsK~0K$i2!VJjk&4`uELHH7odSukz( zfS4EqMwx2cH{GU#-7?{o0JS#F3Q_trJ9tQjz#}{kSx3y)tPI@21 diff --git a/代码/robocode/robocode.samples/target/classes/sample/MyFirstRobot.properties b/代码/robocode/robocode.samples/target/classes/sample/MyFirstRobot.properties deleted file mode 100644 index 1d298da..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/MyFirstRobot.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Fri Nov 02 17:17:44 EST 2001 -robot.description=\ A sample robot\n Moves in a seesaw motion, and spins the gun around at each end\n Turns perpendicular to the direction of a bullet that hits it -robot.webpage=http\://robocode.sourceforge.net/myfirstrobot/MyFirstRobot.html -robocode.version=1.0 -robot.java.source.included=true -robot.author.name=Mathew Nelson -robot.classname=sample.MyFirstRobot -robot.name=MyFirstRobot diff --git a/代码/robocode/robocode.samples/target/classes/sample/PaintingRobot.class b/代码/robocode/robocode.samples/target/classes/sample/PaintingRobot.class deleted file mode 100644 index cd1ef4da5918d83d11e25fec4757d844e7927078..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2379 zcmaJ@Yjaao6kVrjlMpTtO3Sm-fIQL^h&)va7~4WAq-kwSq==83- zupw=jGE-g1Nqbh$m8C#;+RE$YtZo}>-Pr7OO2(qV=Jb<14-wt2n!(f@Ir0+$Q8a8q zk3g4Rl6rxT%>+K+tdlosoLgP)tokpB}ZM|p`lM1I&*sdy1=>_hvS4^ zX;4{jnKOCaG-aU?Vt+i{in`r$wkAzyXdoNLE`exSUv%27Av`Ov<(gj8lV#m3CTAR* zN)A_zazWY=?8W{N_6cl%I<$s31_VMy>16Z;D%TSqNUsDOieL~2LpVSRD{UGMAxVIm zUarc?d4YZLw)>O0Ycfy%ZCf5kLhi<4mA@kbz3o>Tb`|n5>KD_Um^ynx!}EB7wV+oj z(qu9YKIzgbKMgJDZZA%17{V!m2!kD#tPQj1mei=iKcnzp66j-&pNbO3%K{r?1zEJE zTvXH?V?mOiz=(!Xob{BP<)({#K_QPRT1PtfJ1^Q82G)n0D)N-mu9{@VD>(Dvl*_||Z>T$YZ& z&bA6|Gx!C1SzwJSP}dm26;*t%32bW>-^yEIyw2AcTQZzdtYR%mJ7&$ta;`f{dIfK4 zcuVCg%zRBLdl)(Tcue+!1_@T(TAmrR^-9Ue^NDY17O}qMB%9kuMu*m*gli!f>@jW~ zEAxm|wrma8QD$*jHlGo-iF!J=?5rOXl@Kg}O|6?gu!bA3Nt8Kq;drW%8y~^TgQKCU zV(KK{%fZw|zm?q5@OINOr`+Av@GkBUwP5Q@lYCz+uJ|}Vst2Xr7KC7G!b1qAGR>WA z6Y~mAs?>j?;Zv3RutQkY&0JTVQKjgl$I#vP$Hy zG<>ZD4cM{}OpSZgA~bxbp8OpZ-VYjnbie$Gk zw~j5|YI|e#>!W{oB;dksrf0C9u(uLsKYH0i`>?0YO@G79GwvON^ZB5k--_%FUhm*| zJkcF{h~0C8b?o^AWd2KLx$TpijibWmyi31N% ztYhH-7mGcp74LC!)15@ks9DE54a?o8g_CF{TJbIKH!Yk*Ytfo-`JidxBziM?lNRRS zL(1|IeSYiFazV*+p nj^ulvy;nrj^fJS;o@Ej*VS-8W)0k;7&A9wj8h;|A4*dKd`iLhH diff --git a/代码/robocode/robocode.samples/target/classes/sample/PaintingRobot.properties b/代码/robocode/robocode.samples/target/classes/sample/PaintingRobot.properties deleted file mode 100644 index df0c29e..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/PaintingRobot.properties +++ /dev/null @@ -1,10 +0,0 @@ -#Robot Properties -#Sat Apr 12 14:47:44 EST 2008 -robot.description=\ A sample robot\n Demonstrates how to do custom painting and debugging properties. -robot.webpage= -robocode.version=1.6 -robot.java.source.included=true -robot.author.name=Stefan Westen -robot.classname=sample.PaintingRobot -robot.name=PaintingRobot - diff --git a/代码/robocode/robocode.samples/target/classes/sample/RamFire.class b/代码/robocode/robocode.samples/target/classes/sample/RamFire.class deleted file mode 100644 index 5af3693995fad46013a4b707fa813d195669dbcd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1544 zcmaJ>+in|G6kW%e`Z7LtlGZVWgx-=;dkS@E3#BAY+{AVo>a@iPR)r8^GM+d?otbJp zE{b^L1(6@90EyQ;gTM$L_yGQZH-3UwV4a!C4FMzhT-M(E?6vmU$G`sh^Dh9d!%86` zknfv2PkVNyW$rW_-%ddz=6jo-<#mX15eVdhf$!F6wgSg<1;naAa^7*BU_oG{RBj7s z%k7#eg$c6z*nDPI%uj;Kve)x`i5GBIAk%ZY+rf%&?y4hBy3FZh^OD3QrUYc) z4wk&mZWt_Zru0wea$Ds(Cvje#t95y#ioYmvNyTRwzcO&caOF57aalR0JEs3clFLneiAqFhJfB>8EoEw+YPUkqn(gei(7#Sjvj;r=ov*uxiaP{oW>oW=1>ClVm@|f0P!gm3mq;J% z!VLeM^0+}!H&MhboMTfOxXn~=hg^zLnwSd{;x3j*Lb1}27*|DIMlGTxatfnmk9q6= zPODB@wB9S={_}5;GYVK6;^9785!i~sjS##Ofo+0WV>E=6BnEH9evdr}joGW&WK_pyK`ku|L20UqNaw(tl$?B!3mA%8N?D5Qx;;Lkj8rP-@rwii*Oco=7&A$PFi!Ipz diff --git a/代码/robocode/robocode.samples/target/classes/sample/RamFire.properties b/代码/robocode/robocode.samples/target/classes/sample/RamFire.properties deleted file mode 100644 index e48d0d4..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/RamFire.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Sun Aug 20 21:17:21 EST 2007 -robot.description=\ A sample robot\n Drives at robots trying to ram them.\n Fires when it hits them. -robot.webpage= -robocode.version=1.1.2 -robot.java.source.included=true -robot.author.name=Mathew Nelson and Flemming N. Larsen -robot.classname=sample.RamFire -robot.name=RamFire diff --git a/代码/robocode/robocode.samples/target/classes/sample/SittingDuck.class b/代码/robocode/robocode.samples/target/classes/sample/SittingDuck.class deleted file mode 100644 index 6705c168f6fb3c7c2a71a7ef9e547ef27397491e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2440 zcmaJ@-B%Q482`QO!oV^LZhk<14Vne$vT9idxG9LV$%hD{V2Z=;3ycgi+w3ezpH|#- zPRF}0>Y`JpbMmGeEtkr3%F~4xp3_Aa{S*BOW!dkYSzt9zaF}`C=kxb`ywC99pC5k$ za2QJ(Dg@$rb1rAg(Qca8K%iDfC8`AK`YcBd6y_$SH)2lOlFs_v zjA@UWo~6zuW>sh4CWZ*=b!!))&RFWL@<^9oK4wqTovtpXdbn)7DTT=0|K zuI+j{8qg?EwJ2@dT@a}6dtBZTBf{-Ec3`J~o|k@?n_Ubn1)getQn_VRsqfZdDD_&Z z_ZFN$Tf-h!E%0r*$*#iGl=N6MX=bIT;Th(-B0FW-GUQj|S%I32TX6igtm!M)%{p4p zO4rlUKWX}=QWn@#0%DuabaL4D*r|?|5F3Lj9j37t2UNKd0-H+eD>8+;2}vbAxRw>A zA&ibteptuzc!7=d2wJs@1#d1zDGwaOi#V#`CB_L-3S?={!?a|zUq(A!}ac7^=BcNe>qMT%n{E!*Lvl zA%&AF%^rcqwIY=31<9t+tK(Iq1+<)sWILR(=CrCq3a54Spnd0_=eQaf4u9I1G3TW*DWzkWMm}5|MwXkym~uVBx&oLN~||Z|Klsi z%VkW4JE~2A;dthQ3HRMFFAW7Iw3cnSoKCskoawJto|6y&>Q=4euH)3yhF(jYDs^Eb zhooV393H>_+);v+Uz?V)K2g?GmczOTls#A1hMWy()-v=)VD_y_o0!|(HQ-iD z*k_0>Rfs4PQ|?oAe|*(_*D|^X65ES7mDr&kMZESYI$FQOK>TbGBR7$3j|QjnJT(Sn z5o3(Eo2nBx(a>I5!ZFcUscD`T^k53Tu(*}xaGKHjv4lZbg9zE)QtK0_#XJ@`0zIqL zF!K+27x6`jI>Jn^QLiG<3#oIfyh}tA^6HtvBHpBA2vNL+w@Hl!)H|eHe2jM~i4b`_ zkVf$y(G*bkh^2^XYAiK%Cp27th#Ed0F{I)PvYNmwG{xb8Gp=F0SA+jI|3?ya4{=aK fs*Akse9*22RVBL=eO?F3U8PhUfe#qG0w4YhzU)2^ diff --git a/代码/robocode/robocode.samples/target/classes/sample/SittingDuck.html b/代码/robocode/robocode.samples/target/classes/sample/SittingDuck.html deleted file mode 100644 index 9f4d522..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/SittingDuck.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - SittingDuck's Webpage - - - - - -
Hi! I'm a sitting duck.
- - - - \ No newline at end of file diff --git a/代码/robocode/robocode.samples/target/classes/sample/SittingDuck.properties b/代码/robocode/robocode.samples/target/classes/sample/SittingDuck.properties deleted file mode 100644 index c3aab1e..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/SittingDuck.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Sun Aug 20 21:18:07 EST 2007 -robot.description=\ A sample robot\nThis robot sits still, and waits to be fired upon. Exciting stuff\!\nAlso counts how many times he has been a sitting duck. -robot.webpage= -robocode.version=1.1.2 -robot.java.source.included=true -robot.author.name=Mathew Nelson and Flemming N. Larsen -robot.classname=sample.SittingDuck -robot.name=SittingDuck diff --git a/代码/robocode/robocode.samples/target/classes/sample/SpinBot.class b/代码/robocode/robocode.samples/target/classes/sample/SpinBot.class deleted file mode 100644 index 7602f847b3c0126b0ee6b8dc39b1197a7ed1f12a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1264 zcmaJ=$x;(h6g>?gf$$h)h{zx^s3Almih>1dm?Bs`j{ggu$SHWgz<`3c624xxJhYM@ z61b?On)0SBJXgp|0wW69M&ynxN~ek)6Bt+6@QH4k_OSwA5x9DqMYbS)-f;TIYxW&b zh)IDYuK9WHmK|%y*xP4+L-Cb~TsYn1;XL59;G_s_r|y<~k<(4PV7MoWV@BYXdTNsU zx-2ratjlD#RcUb&)c|_@b_^)!Eico6xEi% zHXdkbF-lt}YqD&zk=)NGsz;9mc2pHDZmr3EwKC4Aa{Z!NyX+M7HAAhg2>udNYR@=* zvU=(vdfaw?BRr>QHQJ`c7c_sO)4;jGdj|T^N?-T@+BTjz%WCi|QmWvY#AkF=(CeEE zG=mik(~MSdInjf71qqs|3a${t8-y<4m@Fw%lJ8f3*P$~Ll#n@$#Ge*WCEU~C%Ok%Z8Jy}&x TQawvmRTMRc+UW1nZ@}ZfK4kOt diff --git a/代码/robocode/robocode.samples/target/classes/sample/SpinBot.properties b/代码/robocode/robocode.samples/target/classes/sample/SpinBot.properties deleted file mode 100644 index c80fa0b..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/SpinBot.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Sun Aug 20 21:18:07 EST 2006 -robot.description=\ A sample robot\n\n Moves in a circle, firing hard when an enemy is detected -robot.webpage= -robocode.version=1.1.2 -robot.java.source.included=true -robot.author.name=Mathew Nelson and Flemming N. Larsen -robot.classname=sample.SpinBot -robot.name=SpinBot diff --git a/代码/robocode/robocode.samples/target/classes/sample/Target$1.class b/代码/robocode/robocode.samples/target/classes/sample/Target$1.class deleted file mode 100644 index b6846749e64718b8411f6b24b823f9a374dea924..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 684 zcmZuu%Wl&^6g?BWF|l2e2Fm+UsDUH}LfICv2}LSO*`(@%-NYHWF3wD4PmuZr`~n;P zpc|wD5(_?nk3t+f*#xjOo_pt>bLZSMzkdJt3E(-p9%=&3LQYRI)jyDVqHMJ7!4+ud zW^7_JQT>6@lhme03)JmVT13xC87^^lSbCA_)V>smI)BxM$MS>hXHqBqk~s$W z+yQ$xAP|IDLEVRg)es&o3aoejPiYQQt=`V2W0fDsai%D8XkwWi$~-Oe#i3h@6j)o9 z5p7ds5J_$H>D0^$4$=Pi8tSsDumVn}`_9KT-0*N+V0CHQ5I1p4ph2^CwaSyz3jV4= z_?-}Uu_54b&?Hg0fY>8_WM%w*U!E)!`Xe*TWA!>MX9(uDKP_FNvAa6XOhK3Sl|3?( z5D)Q){qq^^rzkoX?rGjS$YfEd0voi@;bV$ctMrjkjmyIYo;Mf`n3wgSxAhf%@9}qp zUn)?Of4>3?61UJ|ex=F-tf9?}BwWH}p7Bjsn>Ty|ml1HacMkvCd^^YOkDoqc#XWP* qSaMJ{uUD`qRpW3@Sv0;^VZ=It_Zil(iHN&P10SHn$S1tKgWn(dLx`LJ diff --git a/代码/robocode/robocode.samples/target/classes/sample/Target.class b/代码/robocode/robocode.samples/target/classes/sample/Target.class deleted file mode 100644 index f559d6c55403416800b013b49dfb329419cc650b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1626 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 diff --git a/代码/robocode/robocode.samples/target/classes/sample/VelociRobot.properties b/代码/robocode/robocode.samples/target/classes/sample/VelociRobot.properties deleted file mode 100644 index a48dbb8..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/VelociRobot.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Tue May 27 14:21:08 EST 2009 -robot.description=\ A sample robot\n\n Demonstrates the RateControlRobot -robot.webpage= -robocode.version=1.7.1.3 -robot.java.source.included=true -robot.author.name=Joshua Galecki -robot.classname=sample.VelociRobot -robot.name=VelociRobot diff --git a/代码/robocode/robocode.samples/target/classes/sample/Walls.class b/代码/robocode/robocode.samples/target/classes/sample/Walls.class deleted file mode 100644 index bb6f236596a89cbeb437a91943a87a72b89a3b98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1596 zcmZ`&U3U{z6y3K;6B=#{HYHXlQskp)5TZp;Y$+`Z4a=luHTPd@{gLo10P1>H8y zmSg3&jN`PEh%1cwUd5|=H7mctO`s5OS=Nq%+Ez$4y2+M%RZ$_aV7qp(s1VD} zmI*B|E`=CIHAaw9I8d@(>t?4}vHUxx;#dmfC9i6nvhi&>_l)tNVYf+L8dNjSTm6nZ zf(c}jI7IhDvupC^QIIcqj^}H&YY8(q5bPtygy~H<%ah zGCoXVOCj^$7>&FAoK`G0B6Iqsms4WtZkSt`+$S2JimG@eY%s;{o%}yq7TI&<1zoGw z(|Bw^hxa<+&=sQK@k+EDwRy)LEm&uaIO}A3moWXCOEmNo=z+AMyP@9-vC^ TQKd=M>`}#_#<_JFI0Wx+JcK)s diff --git a/代码/robocode/robocode.samples/target/classes/sample/Walls.properties b/代码/robocode/robocode.samples/target/classes/sample/Walls.properties deleted file mode 100644 index 7549037..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/Walls.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Sun Aug 20 21:21:53 EST 2006 -robot.description=\ A sample robot\n\n Moves around the outer edge with the gun facing in -robot.webpage= -robocode.version=1.1.2 -robot.java.source.included=true -robot.author.name=Mathew Nelson and Flemming N. Larsen -robot.classname=sample.Walls -robot.name=Walls diff --git a/代码/robocode/robocode.samples/target/classes/sample/pandafighter.class b/代码/robocode/robocode.samples/target/classes/sample/pandafighter.class deleted file mode 100644 index 1dc44306ec52ec32a8ac498a093659852979822d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4510 zcmaJ_33OY<6}?}UB}*E~OB5r(2_(?i7K@7si*QIC+evKW08N|(vzc${TUIRpALMUi zrvy@(!l5mNuF#fJpi5f1uoQ#~ZJ`HB3td>c@B4NNEj@)&%97qUU$T_sv^wYinR)Z( z&71q~dw=XFUVq@L08Ta{LHGljC}&$|&rFS3g<*3nZ*gYGNt^j? zW+5lzlF;u?*Sq+LJOAhq+@wA zJ!zm}=)mc&FdaKe;b^Qdpr$Ri$H~m=g$9@4yiEf9&8_P~?Nt>P#QSDSXSyTff z>xYKU*)F=LD4Z&~F>!b%pSRq_El*cS;S2)_POZ!An3)!bHaG>%g5jA0BkylJzkQpS zS)*{~fx6mBYIBX~2D%Sl@yc-D2?^0&r_h65&$3Kv-Oa*7_Hw4pSoz!fJj?49HXux& zGtLH5PL}s842UR}apZV*iI_5Vmco!sg)`13l61vj2@6wG{`)n zUo91dLwA*JE;JC&T5ex%+LgrIY)zTWD?6+6sxOR-aY+!PWd`R>JKM3zbSD%{ zj8VrNDQ=E<{J37>2AQvuq?w?b zgnMfKJpCSF@vyBqmm}SB9CAtj(qWZXR=to4>^CWV2p^`h$tZWSB^vFlwZ6HN_?nm3 z9L2u*PTBcZh1+mDF(W?1xhbN@8ao&wO+TUVNdy>Rm*PP8%AZ_*<;g3ak(tjZ+#xd! z1uJj5xmjy;tc;q0&nbLf0B@#2ouP-Key74+a@xbnXh>xmvc@ZU+(fQ9V%xFHw&lxG z-mV}EDiekoc({bR99u{rZZ0T%N!$!u_NZXWu!{IWg)fUZva?{7<$<+#J@(SA_dR!= zC_F5|4FtMZdGQm`qY7V_HFdLA-bv@&c@cg?;hWmfT(9F4Xr9R|0eC{;TRLIV&a~)# zN8!6#k9ECT?MxF6-3i%lv)0KO)d?uEX0vD9jILh%EAW&nYZo#D1s7pyBVaw#wZW+2! zt_hW8b5(ujWYn?yb8gSP_lYpDysF4mO_YmcpnL3LeF8!4S%v2`w*_25x6;?1Ic zo_32fQ%JLrO6hB?zM7mUr3))~yc%NU<5P=(MvK=VwsLUZpZJb&)I%+UZA0>YsN{o) zjogoh`_OndWj-w7JErZ_!q3(9v=ygJd26r~%^WeO7wz3qvbQmL4-!QzXS1@1H+W4O zo8yW&kxv#C%r5u*C8Y!SOtp|X5WDpH?{CPK6x$J=kb z1&2{Bj%(6dD-n(3+R0RuvLfD@Ohglr$s*n@r}6+@OYlIRC_>oCt7S7*5y)1Y!S{N! z6PY9~!g06+$0Lsu`MvGH9-M@$(TVGMHxytuYewBrLZT5@;63CTlLGU2FMBn#mBstm ztEJtoct3kVS|7v**bC8qCqBqtgu8TTo<E$lxAyp_je&RX+EW06u}TyR~<#nF05(S3~UpzR0Im z1LudYsi~ zI(qO(tCI@GQlXktBl~a#$?v38X=!UhO{P;ZZ}eCqn20Ul@yTo=SelnnI@REfzU|FF zIhn4Se{wRLYDzRPD(P&ZiOskWg_%Wxj1morrUmRt#rH;xrIFxm`>*nH?irnPkz^uL z#19zm9~be{N*FgVb3owZtRyYWh85VtY#An(x8f95g)Y{G0gNDr^KmWj;y2?$-jlWx zwu|uyM)5d#{}fCO?k>`hV3oinNce>Yw*~jf&4l4u!3)$cb*PW$CGA)21-aAh_%(YW zX3}2#2ES!4b)kUYQ6_)-Wbk|TV)UR7e_*eHejJNGve!fpVwyS;O`WBZbEhC!&N(K| zE7-+Y{t16Bap^^FD7mv+P>bU)B#hwDxMlV;TnuHeX_)Uf|%~$-yeBg ziYd(U&yLHnQ={u8|L#TV?q+me<*~ZC`ZXTP$JOl`4ZlW%HUBkC*3`UA#0f?PU z<`@S_r)4!~?n68oH&8TuUQ@f*XS6hQ-nReQii=)0O*5xv7>-$fkEThKIqlNXo}opT fmSMY5$8CH#LI={P9pQgqUPY}zFAO=Y&j|k)DQDg9 diff --git a/代码/robocode/robocode.samples/target/classes/sample/pandafighter.java b/代码/robocode/robocode.samples/target/classes/sample/pandafighter.java deleted file mode 100644 index 09420f9..0000000 --- a/代码/robocode/robocode.samples/target/classes/sample/pandafighter.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.pandafighter; -import robocode.*; -import java.awt.geom.Point2D; -import java.awt.Color; -public class pandafighter extends AdvancedRobot -{ -double moveDirection; -enemyStat enemy = new enemyStat(); -public void run() - { - setBodyColor(Color.black); - setGunColor(Color.WHITE); - setRadarColor(Color.WHITE); - setScanColor(Color.BLACK); - setBulletColor(Color.YELLOW); - setAdjustGunForRobotTurn(true); - setAdjustRadarForGunTurn(true); - setTurnRadarRightRadians(2*Math.PI); //״һֱת - while(true) - { - doFire(); - doScannedRobot(); - doMovement() ; - execute(); - } - } -public void onScannedRobot(ScannedRobotEvent e) - { - enemy.updateStat(e, this); - } - public void doMovement()//ƶ - { //ж˶Ƿɣɣѡһ㣬ƶõ - if( Math.abs( getDistanceRemaining() ) < 1 ) - { - double myX = getX(); - double myY = getY(); - double nextX, nextY; // the next point move to - nextX = Math.random() * ( getBattleFieldWidth() - 100 ) + 50; - nextY = Math.random() * ( getBattleFieldHeight() - 100 ) + 50; - double turnAngle =getAngle(myX,myY,nextX,nextY ); - turnAngle = normalizeBearing( turnAngle - getHeadingRadians() ); - double moveDistance = Point2D.distance( myX, myY, nextX, nextY ); - double moveDirection = 1; - if ( Math.abs( turnAngle ) >Math.PI/2) - { - turnAngle = normalizeBearing( turnAngle + Math.PI); - moveDirection *= -1; - } - setTurnRightRadians( turnAngle ); - setAhead( moveDirection * moveDistance ); } - } - public static double getAngle(double x1, double y1, double x2, double y2) - { - return Math.atan2( x2 - x1, y2 - y1 ); - } - public void doScannedRobot() - { - if (getTime()-enemy.time>1) - { - setTurnRadarRightRadians(3*Math.PI); - } - else - { - double absolation_bearing=(getHeadingRadians()+enemy.relative_bearing)%(2*Math.PI); - double relative_radar_bearing=getRadarHeadingRadians()-absolation_bearing; - double a=normalizeBearing(relative_radar_bearing); - setTurnRadarLeftRadians(a); - } - } -public double normalizeBearing( double angle ) - { - if ( angle < -Math.PI ) - angle += 2*Math.PI; - if ( angle > Math.PI ) - angle -= 2*Math.PI; - return angle; - } - public void doFire() - { - double heading_offset=enemy.en_heading-enemy.pre_heading+0.000001; - double distance=enemy.distance; - double bullet_velocity=20-3*3; - double r=enemy.velocity/heading_offset; - double heading=0.0; - for(int i=0;i<4;i++)// ʹԤ׼ȷ - { - double b_travel_ti=distance/bullet_velocity; - double predict_heading_r=enemy.en_heading+heading_offset*b_travel_ti; - double predict_x=enemy.xCoordinate-r*Math.cos(predict_heading_r)+r*Math.cos(enemy.en_heading); - double predict_y=enemy.yCoordinate+r*Math.sin(predict_heading_r)-r*Math.sin(enemy.en_heading); - heading=Math.atan2(predict_x-getX(),predict_y-getY()); - double diatance=Point2D.distance( getX(), getY(), predict_x, predict_y ); - } - double a=normalizeBearing(heading-getGunHeadingRadians()); - setTurnGunRightRadians(a); - setFire(3); - } - public void onHitByBullet(HitByBulletEvent e) - { - if(getX()>150&&getY()>150&&enemy.battle_w-getX()>150&&enemy.battle_h-getY()>150) - { - double dist=150; - double a=normalizeBearing(90 - (getHeading() - e.getHeading())); - if(Math.abs(a)>Math.PI/2) - { - a=normalizeBearing(a+Math.PI); - } - setTurnRight( a); - setAhead(dist); - dist *= -1; - } - } -public void onWin(WinEvent e) - { - for (int i = 0; i < 50; i++) - { - turnGunRightRadians(Math.PI*3/4); - turnGunLeftRadians(Math.PI*3/4); - } - } -} -class enemyStat // - - { public double pre_heading; - public double en_heading; - double xCoordinate; - double yCoordinate; - double direction; - double battle_h; - double battle_w; - double relative_bearing; - double velocity; - double time; - double distance; - public void updateStat(ScannedRobotEvent e,AdvancedRobot ar) - { - pre_heading=en_heading; - en_heading=e.getHeadingRadians(); - battle_h=ar.getBattleFieldHeight(); - battle_w=ar.getBattleFieldWidth(); - relative_bearing=e.getBearingRadians(); - direction = relative_bearing + ar.getHeadingRadians(); - xCoordinate= ar.getX() + Math.sin( direction ) * distance; - yCoordinate = ar.getY() + Math.cos( direction ) *distance; - velocity=e.getVelocity(); - time=e.getTime(); - distance=e.getDistance(); - } - } \ No newline at end of file diff --git a/代码/robocode/robocode.samples/target/classes/sampleex/Alien.class b/代码/robocode/robocode.samples/target/classes/sampleex/Alien.class deleted file mode 100644 index 4ff8a4c73d8ff0fbdad7bcab82dbef0d267aa019..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3054 zcmb7`TTdHT5Xb)qgAHcG#R0-4fsjILn}8__o-i}s?>JQ*|pDNSXl*WFK5pDX68S$yZ+;!-+l)$hu1N*FmzSS)3Y+? z-)C0K78fzJGW497=VqpCilfZV;R!FgF+>?A9sAHO+9jTm7p^5-?z}RKypq{kGb>hc z{hSN85<@$~M3b$15)eb2A)!OqJIyQV0aPDusZr6ux>KC*=6E>VbNsz9j6R8AZb+%(XQ9)|9mCHV8|=^=Oa zy<8GGyJ(gRren!_f3ej)wko7k?y`6kpy!CYDxj`rAer(iQG(XiX>UL6)yn0pipzzp zEJY5XwFR{%My$eJSsUq*40rMbQL(fdsX`2646~u3LS*a!!?=MP=wgUlbsj_JeKuLqOYHak_2!9Fn134@{YOwR#z(5Z^(%1at$`s>6frVY#>Lrp!k&uNHSli5@u zx-vBW_kMPIP;Qtv@IY>exm8DOlJ`5`o8blxOY!x#dFD5`%NF^fDFpYXhhZ$BZqTBJ zelb;${6zzg@Tu364a=b%`X~o2%38Ht<}Njjk?FQxzsjS8Z1Kc$*WP$O45NYg0Yfc( zbono@&N$Yw8N&v{P`$5>`wcw77DKNbKTd-!j`qxwWeS>TdMvWClxGHVQmS?-)tX&; z!!V)~ZUjaHf1yc3aYFRQ2Xh_gRy|sl`DzQnN0HVIEDMOmlV5O=8pqhC1 zuETjo4IR4%8r(y#${Kpxs#JLC@=$nNJ&T40x_os5O^PkD+;orC15odmTGEVuomjv^ z&z>3)_54wH0wt1!YE>f!HR7_7p+iv)%yOAw_%cK;YR0Wg3~ggDY@y=$rQ8Wn^tuKO zYfz(^q0JTtmY_iiKxjdG-_+jqbuD)b5^6PwJ?)aXo6h{`-k)C>o(YLs(la4Dx3hhWM$bh%e z4^J+*hxb&<6PWaIOFk}|o_dS-8(Gt&;!J=Qt+S#?Dq-l`RoC*IRF`thr+>!XKBO;j zKLYQ1_5yRY>xC=pKm7YAxkZ$I0~AvJRxvP7N(#m;9&#@ja5CQkH=!5Dx+SNfh8;xiD3n+KJh6fB#8;HlC`N{kS$)|X#|bj zB^rw505?(RCWyPOxX-cUa~FsyxlCicsap*o=&?{!CyQLdu0p)PUNgkwP()rK_VHOW z#Cj;Apb!W6ycuFM6!B6azQC8w5L=;$uN2~IeA5i^EEMsrLVO3a8DcvWai|bQl$s%S XLJ?dcUg4-2;zcOpSRpJmP$&NZVnB1J diff --git a/代码/robocode/robocode.samples/target/classes/sampleex/Alien.properties b/代码/robocode/robocode.samples/target/classes/sampleex/Alien.properties deleted file mode 100644 index 292c411..0000000 --- a/代码/robocode/robocode.samples/target/classes/sampleex/Alien.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Sun Feb 20 21:16:33 EST 2008 -robot.description=\ A sample robot\n\n Is not inherited from classic base robots,\n uses new experimental access to RobotPeer. -robot.webpage=zamboch.blogspot.com -robocode.version=1.6 -robot.java.source.included=true -robot.author.name=Pavel Savara -robot.classname=sampleex.Alien -robot.name=Alien diff --git a/代码/robocode/robocode.samples/target/classes/sampleex/AlienComposition$AlienEventHandler.class b/代码/robocode/robocode.samples/target/classes/sampleex/AlienComposition$AlienEventHandler.class deleted file mode 100644 index d11f0fcfb1d6df8829b05f1a5465b2de05247a5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2403 zcma)-YfsZq7{~vIA#TkhjCSIa1 z`~ZF>^Zf^aIc&ty!7%Oey?slF_u0pmDP-Q>+qYfQ zGi^Dp1dH#4^j5g6TEdB=lcDb|f5)>Hm%G_#J8wnBi=&I-qGRva6}u|3{*7l!PdKl6 zMY!2wj=N?>VO)kT?~Un>&oT^`A`hM?v-_qry@w3vCjMbJxy8_#r$ZB9IAI`;<4MHO zYaoF>hS-E}&|5O4SgY;r2xpV;Sc2hX$*yo~i#w+OTo-owficWPAJB%xPeAZGD4mal@nba3_dh zoka89IEV9bj4;eLg85Hh1EUyYh`YjDG99Ycz(iqEN06&omhdQXMyfMf-kK_P#Fi_j zm-`U-s9rXr2`LUL)3xwx^!H|ACY{6-uEa4-C5p5+FoUZM{ky`;3F@TWE%U0$CAE;+ zUhoSrYv3B@7>;{2N9OG62dXILLL)J(<8FzA?5U+5_iBX7gqx{k2f;E7YDi!ns2I9! z8Dvass!<5h5Nk?CQ<}7tTnKbf!?B}qfl@<9j(~=3)Yt}sRnv7v_3+q+H5wXfcB=sm zj4ca-dv6%hp%9fwGg3ORkcJ_tCZ!y_LBk<`Dxs2UL|P*bD;W}svdt}vVdyZ#7iz}o zLkz8BFl?#LtEX}{MA32$8q%Oy#aX14CZ5x zzM|(NJ$0a;zPrc<$m1k^8|prZQy8EpiV1^t!ZMxU6MCmU!T5yJz29&)hHZ^WD)l0I zu%u9ffq5N8j<|qvg34 zftz*oO~U$UrZGXHr4WKO5R4GF6yi4Sv_q^#BJL{0J>BG$;Y T1JBezt>ZcU`mYr&Ka_#LF`f=5dJn7@4WOhXRNic5?dQJNo_9_K{VC2q*w~6N?QUxZZ4~Cz3heiQGE8F z@mZ)yeGngf@?R3v*)z1I7{P;`otgb^=9?eie}4V~U>QvdIfnU|4~BsdZ@u+E3e^q= z!!VYK3{^FAY;&nBIHS{z)%46z&v5iu-xqOceG#MskHB2^-y zm)sYzrvcv9Zo*ZcNBtfB`kY)XbL|C128VmoZ5eae+IE@Gi>$tTqne9Aat`*N;#!aBNnOaQl>5|J&>PU*9OK0iAY= q=mHN>L<<$HU=fc!E>!K+gASUfnyCmJ&k84W<9yuFJsMeQpO%{Xl62hP*b< zOj&a{p0)4OvJ(2zZf*+1TT=Q0>*axD%D~#KgtmKV`-hrzpDKlI+Kwx*R2~?8PN(yl zW;8dBNzqW=RxU%lIF)YrDl#WB@yv0ZaErO*3sw5vVbUoK;kt=Yj2XxXEdE0bDNJBW zL8b-f^Mhm9EL4*axM5-hrh!?3(k1L?<4qxpDTTjj;wr8QjFuf&zG*jW(tm5$8d4x# z_Ud+{YWt3Qca`z**a-x(e~F7V3}mRP&yM9UYgvB?biWE!19t`1{ApN>|maK)}HCqovV^fE=lc*Y@l3rK1{_Ilq>xYMTViU6;f=4Lb-VdpEAl z&JKe>vbO@b%}NgOH;g!UpE>e`DlE@2HEa6j%8IA0Ya1n;@x7o>~dF!7GU zWCt^pvr3-pVEz*gVz|XKtsN}zTqH#fvsj{Y(19kw0`;Jrqds!5O=OI^WU=%EcRI-T z$x`}{JfkgWlF7)hOQPa0qC^^jWvq1Rwz_nQVyT1G^IXf!ZsiPDqQ{lM8vQ7)d;B&= zp;`LPiWEO%<|AW_a!gPSn)mY>?&WnK8yA4*&x1EE0LSn^yLgC4ywh}+CDmif6TF`Q FzX4Y~TfYDR diff --git a/代码/robocode/robocode.samples/target/classes/sampleex/GreyEminence.class b/代码/robocode/robocode.samples/target/classes/sampleex/GreyEminence.class deleted file mode 100644 index d91efcc5b0e8c214408f130d3906cfabf20766c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1111 zcmaKqT~iWK7{~ty5QJ8tBGhy+dj%;??N!V%-{1nP(T15W7d*lioMqO<(YwA)*Uc2o zbkPUs6ZC1S|5*`s7>8wcIp=x#{h#MK=l9>AzW^*_ErNi+jbpRfYDjsySa9UoPSa9S zRb>PrziVIC+KqrC#nkZFzg-N8|;3*eyq&z7HcH61ST}z+ux=@$GyxYW-K#y1qs?x z=h3)Io_=B;m7~RV7+t1fo}e!`{|#eFBs)l*uVy+(_iS^0+n0ZT7#{RQQv?Eeg4dA5 zE2OcG3|2jHEkJBn{H~Wni@-hH?`pp$M)wod^mqpk`t8I##}-@P_O%l2wGzcV*}9d7 pc+|xeS&hae&Wl~hb?~^>!LvbXfwdQX)I^V(AoZn3T_q=g{C}N_<2(QW diff --git a/代码/robocode/robocode.samples/target/classes/sampleex/MasterAndSlave.class b/代码/robocode/robocode.samples/target/classes/sampleex/MasterAndSlave.class deleted file mode 100644 index 45dbfea4a325ff94942d9512a938aa6b23a25159..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2086 zcmaJ?ZC4vb6n=(4Qsbte(6j|wv=o{EvKqC%P+Lf$EgD)(YR>WFBpJeL*l;$R9Q)0G z<5&F>&hdjkz~ABTP@kFIB+H7MbF#BDbD!rv_s+eufByaZ9{@`DE`uq7n>~4U-cjl& z`$+bDQ0zyAo40lDk6(Uf)gce$UwW%R*qm!VTmFX5^`oE&49(7whTW!OvrhMGH&X!t(o` z`@HW~o%X4(p?56Y)f>|d+5Ax;SMxa@$@5Un^{!iMO4l7nxl*W%GZNi77%11@Db_XT zs)hT8^ThEOrr>`$2}QSE_l4t^-<12Ej$$tFM!ZBeMo!YZ^-*YB*v{Ys=4-4fZg0WH zhXUEQ^2>_3cH8EN_O;TIg^#t;YdS3zbwbxm6Qyw`rhbVmhq?x2({~2S2&yy|EFH!xZaK~k5&Cx5V)cB$)3}UaTXIfCy0RUk%cetrNAw+jp{Q-xRpqF2^4Vd zTKEdA>pVGYZy4*@B}T3Psf9f}WDoR||EkX{-YQgnkOOHuUHh0R_iMhVvG7*zYN8+2Ko@fs~1 z>9+0By2<^w7GC0&hL%_$wQk>Qs%MUF&H2lB#I`2D`>dE0|1)f>IgV^=KHuWZ<|sJM zY+NAw8(*ei@tHP@i^%ca3Jh=^vz$@s7~C+Vz{DY zNgPdNDH7pSz%jR{ubL3K&cIS8um>0TY@#AK2HrA;55(}cybAMq5{7*hV%9>1`m}fA zBBO5DHdjENBth6lS3t^15cX0CS!cR}lij?)v!r17F&JYaNqdomVV8|D5kKD~Vfbws hVzys_0PD~~K2 z`mJCF$_&i#0r*f1XIDyOl&A^+$g913etYlTJ@ViG{P7onTX;~$h`?M=9&`hxesaH% zy;w!-vZu-@3Cui}1L+1*x80rQW97vH=Q=9rs%STChJ3qFk2vtcmU7ox1F1dLvXNzh z@fBbD@v6XRwYDcv+TfxJMsdzT853ok7nnNQw-LwzqYkD`bcWz+{V13vwOreqgun|9 z#xO20UH7&6vVYK2(IeRm6eIP}lfj;heDj`8mg0`z6PQ1d$gSEcK1}}ZK}&RCUwW$NZvRKrW6297HJ(y@kmI<|JI}Q|GT+PXT6^xUnZoQ>?y2~pGBw|-7MI-R3U}KoZE{AzGpXPj-YDaB zcEB|0_;qk_1y=6=SeP5R)6?!$-&(ugA^57Imq9b8A1_q3aZ z%-P${i8DU+?U>N4&KI1wxy-oky5-pVpCwktgfs5*c5!*!Fy)O znCvLoGBY1J_`u9ew0MDx7YJ-h?}>@6IQYcGO8b7qi+&BCI=Exy-S9`#_Nh=eJgIeR zAb~4G=P(?xhsnOWe7pTh_xjO`l6wY0^=CU}#9=RF0-OrtSHhH909Y7zoWAFC!B9M znEDN~zi@H{b9_!&zzP@M!3``KlN&?g zu_N)zc;zhOtrNu;ap^4L2PcYO#pSbzcTN=3NU3;@MUJr4NmKLEGrX2HuVMoY_WO~A zEF=rl+9|=Cc#9Zeyi$Ox<#AsT_jLho2{$Z`ra8im+7q$+aCBz@?!!FJBd%3|`#8;xhAzM@=W%V~I;Y_HIVixb=5bGm3kq?(*or8Wnn>b>Hy9HjfESG#Ax*s8ZpXN~oiWR{p+AcR zG10^y;EyuCvo`Gp3pX=!zMeVfo%#Le$1ecSv6V+guy*G4zJ^Mj@4So5`S9(><46q; zdx2KkS9#oVEU4-DSiy6!c=3DIiO~2Ps(W%!76(cR< zdtuv)0&9<)x%g9XCaB$x7R(v_I*9j&`~5If9J$tLjnzm64hKrd?8NrH;$jI^!Hlv_ z!Rjp)f|AiEzNhtA)OzZMbR>PnLl+NFj|XtFL4B63E^wRh!x}p sT>UzZVqoJ&oE=}RU?bd%#0CnsyDMy5r)^T2t<;2t@q|w}QwE!V0kp!hbN~PV diff --git a/代码/robocode/robocode.samples/target/classes/sampleex/ProxyOfGreyEminence.properties b/代码/robocode/robocode.samples/target/classes/sampleex/ProxyOfGreyEminence.properties deleted file mode 100644 index e47c5a0..0000000 --- a/代码/robocode/robocode.samples/target/classes/sampleex/ProxyOfGreyEminence.properties +++ /dev/null @@ -1,9 +0,0 @@ -#Robot Properties -#Sun Feb 20 21:16:33 EST 2008 -robot.description=\ A sample robot\n\n Is not inherited from classic base robots,\n uses new experimental access to RobotPeer. -robot.webpage=zamboch.blogspot.com -robocode.version=1.6 -robot.java.source.included=true -robot.author.name=Pavel Savara -robot.classname=sampleex.ProxyOfGreyEminence -robot.name=ProxyOfGreyEminence diff --git a/代码/robocode/robocode.samples/target/classes/sampleex/RegullarMonk.class b/代码/robocode/robocode.samples/target/classes/sampleex/RegullarMonk.class deleted file mode 100644 index e5044ff813d7412fc22c9c424040f73101791e67..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 279 zcmZusO;5s55S%TQN=3dB!j&U>u!&cV7ZXke5-{9f%ci{gXiaI2f6EgI2Y!G*im*>T zaNshtGrQTH{WTojV7*8C$vMI@wD1RT)e5sFrgRbu`)|lXsiECw_NKjVGv$C z{zUK>c~!(b)^MHo)-3`3WR^1`yH;o#c<#Y+BVR|jbQU{K=@V^ Jp(W^`eFEEqJB|PV diff --git a/代码/robocode/robocode.samples/target/classes/sampleex/Slave.class b/代码/robocode/robocode.samples/target/classes/sampleex/Slave.class deleted file mode 100644 index 0af7ecbbbb4af0d4eef1910bc0375251869cfe60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 817 zcmaKq%}(1u6otv;sL$7IFf`DC~q@ z*i{E7-GS7e>VD@!EHHU3Bc(Z6XpYh@WG_}xL-y1$1)qKG$6o}NYHup)ZGqfZk{x6* z?ZSd9kge6*HfY7g1SSP$n!Z-w`d1wlUCK_N1m>EdCxf<(d=n2BbMX(qC-7l>P*MS1 zWTU=zuz*DiMS=M@th$&tCl^B9@}$E>40S)*V~3#cCmz#fS|FJ|H%dN zp+5KH#%-e?1d45|r0}VYH2sr{3aSF-G5M8Jz-fj3$Wv#&>5h}sz5i1VB-Yr+EU%Y+ zG0o&G$GL?mjy9t+WcUEi?jOE;zmdOVl)((gLXufx#xk{K5`f~f8nc*V#Jq&c;!OjG z%p-mU_ojA#A%BmLW1^E}S9pFkp_vTohBW>qC=D4WR2pBlVeH*w`6XnXX&Wg^_Q;Zr c6|5!}*tmCaYcFxz#O=I`TTgHs^pnBn6V_sw#sB~S diff --git a/代码/robocode/robocode.samples/target/classes/samplesentry/BorderGuard$RobotData.class b/代码/robocode/robocode.samples/target/classes/samplesentry/BorderGuard$RobotData.class deleted file mode 100644 index f771285ef0fa4678f2f0ea7dfcb85cb1b288c660..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1762 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 e4-+Y(?+)YFaX`E0#OX%IzgSq6O;|L)p z(2j_LRuY5Ze?8*YJj0St#gE+?{W7TB@f79+K)ER6pEIPx5yN?3DaY@+TKF zl#*QnkG2BjTNz2g9)Z15uuMk2GpUTgK0L;z6&+hE>6+{14A<4loaNePVy2zW8yslG zyeNm7Nlr%&{CSzk0;KbU0>cSjxW%E^;b{TYF0@f_9Zd7Pc08-MLaWm-i6y(Jtr zxLj6Q+86?-B|A);8L2lbU`j>@8Kb7_X_n4?ox{9}N^58Q&^gVct_7P5;n|#+saf1m zIW7jA!&w1G3PY}G$w;0+wH2u#70wG>@D+61RdJE{39Rig+qAqmYIs536EAYuiBaMp zMn^9TT*51KY*z`7)s5D1(#Ken$L_IHnJ8Z4HE`ULVC(nne%G){{kFrKYN$VsH}IB< zHv=FEm|TzfDnQdum3+3 zak&l4n6EX5M2k^g7(R=rX&ed)+Kdaq;sY?3K(?)M(;Kce7FEH90B!?<7HlI2rZ4&H z700(Is`!qJyNKVr_2n#o5cpB8j4q{9?-rI9 zZeV40@Hcc_M{k4lHOK~%P1mudK?YKT*U(!>O47bMwoAI9j)x`PQpY2b4%D$bHCV^c z6@+uCRoGw00g}-=#v0_vmD_(alRRd)z**)Xa~{J=zBeO^E%M&y?`A9i90UAHV35yF zUhNrd!w9zXHcQib2km#_6mMi5yKx44a2C7#ntRv>*43;ziV7xhlo5}S+l{u{4BMtc zQ5lG@tZd7ZnB<#1Rib>ysHn>t@^uuxM)+!~j;Hyl=|^}f@l;OS#F?8|nA7)$$#R!i z=g5krZlPA_4fjTF;Ca6jYlfn!Yj~;a)jD2Z>mTcQ=PE<)V>J_tT}b)8ILIo7nf)Pl z;V^%77BpVMTj%}V9z1AIuYJ=FaOAF~fh4B-==!t^nKPkD;a zOBX)F=j^rY$Qp#iZ5%|q-;$|NDCBpgn{K|qmyND4m3F_WogCp;EcTmn9p5h@F769Y ZFprtQ1UeV<>SSI&(UpRq8LmSE9O7h4sdZX{PAL{7JKWg8Y4x>4R zDHpY|e`0!8hxSRgLn9-c8<<|-#?je+Q$Zal6nEpOpXewFbT}|sa>}QeeBhCyM}^$B zjcl@`kX>&!>w!XMH@-9lq%rBCgeisedOaA0!n6kuML{zj#!yr!wQOV#2i>;mo&G8* zx8jZt15I^QHVkHxYui^SxBhOrMYb!GoI4Kc5$8goa1sxC9kXX;w}N|<4Otv3ij^NAJ6s|F diff --git a/代码/robocode/robocode.samples/target/classes/sampleteam/RobotColors.class b/代码/robocode/robocode.samples/target/classes/sampleteam/RobotColors.class deleted file mode 100644 index 7a05bd6b9a4f51042de598df03bc6b2a0b2b9775..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 493 zcmZut%TB{E5FGcFHng;qQp)SV4LA^qD~L-G5-0+RLhep#6(cuBi35Va;)KM358$H^ z8`nr2uw>7Acf32}ukVjf07uyIP+=J6eEz6}5quup=vbSvRyxZ))EIgX{D}vOr?cQX zeh`WA&|nzYtkl6oWRffS%3~#noZD+8vRvx)?&6GrT{3jWI?WAFO~h3p>NL4rjG-0l z>5CmkZ$sOYKbyd2jv1P>B6U?i<5QlwODj+KZ(%7e6iIiL#)(X&Ic2Es?MDo?v7QPa zRSetcW0j#B%2Zqx^H^lJ3(5UZCtO9GY>)+)teJb6GmOIjKZd0F6J2D9IG5J;pHDk1 zU0@d^fp#4YY{Em6;ud+Xz^ABX#h;U+m5;A9HNeLUX3cAVl{f8>hHNo{^7MU$F2@z#!3>(Lf4Igsq!HC68w3q( Fegm*kgueg) diff --git a/代码/robocode/robocode.tests.robots/target/classes/NoPackageShortName.class b/代码/robocode/robocode.tests.robots/target/classes/NoPackageShortName.class deleted file mode 100644 index 3efee5a096eb61e86e9a60fac4279e2a04df23f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 483 zcmZWl!A`|zspopCAI&Tk+(>JxDBbgIIUUKsjqCK$2p#uP zpxRsZJ)(9Hd3gw|o7g~EAR`?m$8>9*w@2C2`4cw>;*Oe$dfZ`#QQ%!h-oTwWVN7h9 z*p3Oq;#mTPVaR+XA5#DP(2oLJUAXav_2nfF?&MrzpF(=#r4jKy#vJP|vtZ72Ua|5* zpm7-_G*HAEvH9D;TwukI{2RWdWIWvLlolv;s;Dfm8RJHZpT9pz>xpEIu0WZwLa8dh WV-pR=e~V^n(M)D2EU-hUVfP1yCsjQF diff --git a/代码/robocode/robocode.tests.robots/target/classes/robocode/BadNamespace.class b/代码/robocode/robocode.tests.robots/target/classes/robocode/BadNamespace.class deleted file mode 100644 index 24af7c0b7e75bab3e0c3c7235a4726a2f487ad4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 483 zcmYjNO;5r=5PjPgP%Ko+r=lj_fP*AnHO8pX3vvL%(PZ0hWEEOcTF(9(&t5R`;1BSZ z_$$=e+8~#iH~VJZo1M?^_YVNaILJX`sD^EqM6K)FvA`}4g0_HMpXj< diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/Ahead.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/Ahead.class deleted file mode 100644 index 2b569908dd819c3172983c5759fb330f98652eda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 382 zcmZuryGp}Q82(N!O^ne}+r-(eb}-=JqKHLt3Jxj-$CKnhkJJQm>3g{-IQRfQl=z(} z)xk5I|MuNJKHuH}9An>uB`|JP)2bq=tE_69WWH3g@Zboxz@&TuC=z0fiGV9jMEXvzjD2udb#<<;wJ{3%_(zX&Epb4O-LoxrOvc~i zoUjU3clHYZnTO)Bz$|#D6sWjYh<) Gh4>2#s6hAt diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/AwtAttack$1.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/AwtAttack$1.class deleted file mode 100644 index ddc8eff12af4f1510479ffef0bb75a8b54adcba8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 790 zcmZ`%VQLND`^2Q3tCNB|b*#I3z@snKr0CGQ!!-6z|4+-~m+c=r?wpDN5b+fv(B6kW#{%Qhke!YvePXdy9>;?P3dKoW4d1QKy61~;_nMV6JK#*r9VhP?E9 zc+O16=_E7xfIjsP`qJ-cyS8j>la_kMXCFyx@4eRE`<&nYdi@r_$0%xuC=3L4Ik1Zv z-z#`QIg>pNvO!>4&oo38`sJNI>CK~w)A9PA-Y0L5^YH6 zXh%$;%WzzKyYjqX`}=00WGnO-o@JKurtipe{be*ba>@$VjY~)@GJ#)lW6OtR%wG}= zq~jWT72-j~cMba~*+kQ;llj>4coQ_JZDs42xw|-eWvE5*CGA}X5bbKIc6Xto1R|WgRofD0DdPiTBJl%)s{9 z_Ou}$nUYETUd45#E0mR>tXZAY@d-=sRVbvd26Vj4uJ5=(F7R#h`C=0D_)Np63fG!( z_K$q;R08Sv9CtVc$2AXDdfzuKPQhS3?K{zAhGIo;BWz9Ye=$=~bgy#>NjH*lNIFh^ zC$P^4cbR!YQp~dMl=P0%PyD4Z_6S0LC1ZOp3Hd_-?AlD3r|C5fB#8HTNt*VnSl{zexG4d=))-Qh~btrsd}1`(1*blp((CH_8x77R>+Pv z$tJ^>HxR|mFj9XFRF6bBKE!zF%DbZ;>Sr>NP(yDpama8tjp<)8bq3v-p85s1tC)L9 zBq;eR&s{6~X(V{oI&lZxSmd2|FU&bg45QU^Cdg%hUllQN+zp9~BHsVI8s_6n%?{S6 zs03ZbIsXPrhdtR>STUx%@w$q2nm@#})%L%Osp6p!?AfYf=M3Xpw`z3v&oFqt|B5os z_mm;AXEDbq7rV?U7Hc$QEwB~93LCUax@#E3I$QLBCEGw6o5VgO_7Ob|WU<9{o9iy) z?S<0k!lvfy(vz6N*Z79o=0oXEs5KkzzU6MKUXBPe09}X%8V(+5c+CHN{AwKEVX{^h hUdYYK{Jz<2sTz3xWiq9K5t!jxfJH0EV}h2ye*pNWg~b2> diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/BadFirePower.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/BadFirePower.class deleted file mode 100644 index 50d6cdf82ffde0a4d4b85dd44059488d5c64e5f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1100 zcmZ`&TT|0O6#lk_rqlq^Vi7DDytYM%R|JY&3Zix@GQxC5XMET;YmJ7alP2hI@Q28= zGfwa_vsS*QBe?M81qEi6Nc_Ob;oP#Wo~Sk zuGn(k3Rgi7LsmK(jv@3_V~^VnVLX+Q42eb4HoYZ=c)n0$=vkwf6yoSp(TfDbVAZt6 zroUSk?hdb8f+1aX8r-UJ*OcduvB!I5wi$BO|MMtO4cE6*U^uN}2x$hTDZCwXmq4j{ zC9#sH8__32vMNS!mZ85bJb9I}Z&`x)4(Hbk)x*m~)>0oOjHx(>93eSAg`KIs=6hT> z9ev9+ZExFi1>Y?xm|z$QJr=i{I+;zoS@uoK5N-+@E-08JddDMFT*M`!yT>hGJb6j* z`AQ+Ga0I86!Z@zTzFn0O-Tp!?i2}7$i)d>tIi3YgrcJ51hG`lHZ?%MNFifA6-v!yB zPL*}sP;i~VkM%|+iQHmHQl~>TgsoneCGW_Rvotf=(c?G%2Rx2B74uji49|%gCa2Jy zLL?Tkq~IPy=7i>}SeAWJT5=wioy00bO51d_dN^4*^EDOgQge!UCmOy-vPeWuhM}&R zlQgzH-gxtvw>lb3Z9Bf(5F4gc>Cn+9FeCY3l1juwfyHP?>ZZR!XPs6?Yj5!Y$&a*& zkpdCAfecR3UX221?WYsNz+v(i0*aCCMX?xQ@cl3{&4AQ5^#jG?Cyai>_%rGFjPnP$ zoX!U*P6e0=a67==0Hu9sCxop~SmdXry#MC|6^MtVCPKy|L|_zYjA52UKaU)0n80&n iL$cY3P>1XQs<@90BK?3+TT1szdm8vb!+Vy@(jWNCG3mVfJd@~tf0;_bkSq7f{Ha?pe zOnmSI_(}W}>VFn2`v5O{&Ya8doH=v$*PkCh0o=pWG!gneOF>m4Pq zPz@TgQ#ewo2*$nEZ1gU^gr_!fQ?vk zv1}t;(+l;ho<8Rg1y|0;Hs-EAIhNHgHX0KeE zBjK8h>nO6BpvT+is~=@wdVb)&4Sj7+OsM4P-Yjmg1QUxH+`?8Gn*zBBfi6lY3#89% zZijXAr6I2)b;~2n*DaP65FA@>LQBjI^r4cb&3B9S9GU)iJqwS|6q(p}evFAlaTI|b zKJ}4qDh_o$hKo7I&<7lE%t5rH?3@G&;}WreVWvRlBbf29iC^MCBSYOx} z;O4m7OyntI4jU0}X&5=e+10IJn;d~1+@8qWoxs~9Z)+;=PQ<&*-+NMj_b2eS$=jL2 Odx%F7?=f$fz>|NMAIu*B diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/BattleWin.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/BattleWin.class deleted file mode 100644 index a4591128b15ab680f3ca009c82402c097eabac7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1693 zcmaKr-A)rh7>3^g`oprt$p4RsRZ%GFqJlr5SStu>QKY2C!)-g3)iP_!mc%pf#$yvx z6A!!qufyw5-`Q@v8&Yi2ot^oaZU&NN_P2!K&s$z+_66fZU$XdDBDWOO0dh> z`Fv;N(a7epRNmS`Q8UvfF8a)OPMzBn{Ga<@6=hwu?RdFQxkjxf*~{}0l}Mm163-Uf zTg%{D0*mZd$JNPv6W4J=z^Fb z2#iGxa-nUkpUgWZ?&2Ob+y-%@`SxEnT|#i8qt9oD&OL)zYfz(mBaztnb|#3qlfzm(Q) zJ8g_)@z}U(&uys6rm9GuubBufTn~}Y1qQ-(a$`~-4}qzWAI4jC{vl{xu|Oqy2qJ+{ zW|zhy0qR6PUL?>KFbZy?UY1WCefb7k3GCJl-FT$=>3aS9lH?n2ET0L^Esla?Eb|@7 zuYBp@m4hD!hA_Z)vz5Rx#Tn6^;u4X%cs4VFGfkZ3Fxtd;Yc>_kzWn{olwKb@MrB}} z$`iy)ViZ%npJNf3*+6E-uOXbb1+#o=v+Kn4aExcDb|G|Y_^THPPy48`R#t%0ySaqR zWC+aRO2FD=wq~Vh^Xg&~3)Lp9lgK$Du0)Wj4l+gLEgyLs%K)TYd#UARz%uiX83jRne}4TPz`HOb2nbAhs_Cg} z%5@GLubIj^)n}!aYZnbqMbIZOp&b>cs#2M1+psIDTGWvO;Z@T%y)}VgJW&?td%&0| zf*6npAuKRdFm3g)RXQm~Z|J~i({ma-PTRC=+I&OeO`TWv@)ph7k)QaM#9P`Cp(ATl zzSY5V5^(Z_?q&zct*nea_6-39mzYSbCAxm zvYd+PJ=6Ak67OleNDnWH_pubg2LhufSK0DREA^N|Q(_s^cgl9$x?vTSWq4+rg48UP zQ#Ds9-i;PEH^9^%O03}{QgB+HzlJ(gkDQZ$ox zwq;sXE>d_&Ad3gOzoPPgzBj=aqr| z*eB+^kNLU87xp5Lj1jgbQw=((HFd}%$8@ohdi35GaNJEQm*(?CdXr7jb$gwW9 z<+vs^Uaz59NqbJqt*8xC_v6UfX1}AMaDx{V^!q2o8T*)HgzFUlg8xwR1^R#HB)~3& z?*^`7kaO7$;QtC&g4W~Be=w!qyq_GyPzNLYjdw7~R8#zB&sndZx8Cf=UT!_fa7t(c zBLo^H=P?o(M+}pgz%*vr@V7X|+0XO1iAAoK*{f@qLl(EOP3tZeP~u6S;O?0N?e`88 z&`$=Bq1AZG;|DZOaP=od$@uLbgqR*4c>eESno7{uCWb!F7b)UB4DcVreLw9)ck4;o zVI+`b;@gboi~Ki2BFqrJ89lV;OrcTNlO4=&ak!i3u&7sawU@ZR6iWVr)!&fbrz!gq z8!u3ZJ?h|-L4s@0!Epd6~lJWa`q$G08epZ(;~ryuVGV Xoj)VjY>$S-1-XVOmq3k(0UZ4Y%4%I# diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorAwtAttack$1.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorAwtAttack$1.class deleted file mode 100644 index 59ec141efdb065cd7c1e29400b8ce377c27be001..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 856 zcma)4VQbVt5Pf@>Hg_?ac-GT;wbpCA=I*p<{UlU`a#&Q-3RVvEi|plAo0=w&-B|yY zpsgtQ1N>3qY>XU&&<2*>nasR5^Jaej`t}3BeQcPhF?dQyC8j~1O)@2eQI<-T7m>>H z?PImA6p!9}nss$7|GOy+ z_R};K`6%I13W*h(Po2&jnCt2>(c;zUG+~kV0=*uPtv%LY_yzXh6qi1gF_*Qk{G+p% z&?4KW9PPb=1-eNLxE0Eq3Z*mn4ErnE-_dz>iksoEwS0n=p>YCl2HPe;V42G4!oe!R pcr>D3NzpDTI~9dPls@`IQpbRDY8c`!-3HD79s+vlHgr++{RYU%!H@s| diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorAwtAttack.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorAwtAttack.class deleted file mode 100644 index b6aa527e261c8e2dd1f33e8948be97f0f69aa229..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1613 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 pf%lru6SS7jvE(m!pL(g{!zz{nVN@Cbsa zNf3w+{s4cJ@lIPTB%0KRo!NV5?mg$;d*_)6W8FrAp{zxu#ZEGW+~Jue7+_t-NaP3t!tvF=YGRH?fqw*%AyXy%$9J zC5DCiKtNRrSqo&K*BQLxfH9>8L$Vg`h#@eHxUi9SU}4n75Hbu_(Oej<2U5I@51K-4 zce!Qjq0d_lt^#BCoJm8NVQDbvKYbzImWri=tGI6C+Jzo<8|h*aH;A4eD_|Q_IE>=5X7_Er$7ldg>yNc?u0<%`nkL3&IK| zm3m9lkPoV9EKrBeU}kw|=nhI)wBa#~br@cZad8KC8SJ)6(~^|Ac&-r28_3;iso@aW zii;&U3~BEBA|g4M=`6drZ>E#{zylJ{Lx!1tA2y^GO2utb=JSufXzL&(gpn9`$$>h=)a|DR1!vkN;kUsWd^k&0578?WPZm I@SY;^8%&}f@c;k- diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorThreadAttack.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ConstructorThreadAttack.class deleted file mode 100644 index 3eb54a78df22ed757320897d444ff07c6ac9baab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1577 zcmb7E?M@Rx6g|@xTGp)~6v{V(1xhItEBIAJu?mv3!~h|If6I0Qt7Vt$Zc!e@XYe

=r0QlbX%!%-p#j=bn3Ke*OOO6F?sCq6i6$dxq;7m7HVm*`Av#+Lr4% zHQlqFtpmr_@~I9u9Y)ez_`*}7KU)*Msr z>%xe4V7da6rKa!~qUaWwZAv#405lv02_$6-y#l-GCIdC6b`_&AwH-yjK*tB|Sj$y4 zYd;t8uAmQtGWd`{GF`ep-l$oYxF4K#Ik%YphLoU~1aA z_l{|Kn;wgLSWqy5bQF^UUDuu&*#0D4tC&KDl{gA4SpO|Y(^-k$I*?o5WYL8tF!#U7 z(~J;18?pew$?3Bd6zzA1aMtR4Bi5XB>^-bjOeyXx4rqZk$hV&#*|mdoRb zr1UBE8!06zrnT=An#Xe$1uU{TUBfGDpUIl-nBEE7I=vQ9z9fCTWIHwb2!Q)h3k~@+ zR7)V_?X#E-r;SDgs_DAnx~VyVOtbAKsaH1bnxh*lro1eJ|G2@kk{|(f&9V%qSk+wD z;Pr`J_Buw{IbpsFK!ht^TmGZm6*&ve@yt15912JLl!6dC`0u1TxQgH&V%(|d;tHI7 zBTBk_UEcn>!!Oj8fl?Pp>}13_dP*1Q+nGMcKskGc;jd6j)0uA=J;V5^?nL`3z=>dVn}{n4|0=J@F0Pjbb9k z13pD{h~KF!(^_bRnBVD~KgZ*8wnI6?GYL6M%rDkw{)#!xxR;p67!gFMAjKDDf~Y6C znnD^GV#{KlxFl!uq@6*pun*UM!XA!2=tt|LNPsBQ6c?VUvvDuC&P-3QrFOR6 z4G|C;J~cKI8TX8yD5s1jRNSSq?IW%q%qKWu+;^pw`$0JFyayayCD%!uCi)^ibD7c? zC;i=XLeS&3iy%}5KA;kzjE@2#J`vVBb82b>rR6Z6j%4;b8KsgJ7?^RAo+p{|{wx^y z1qhq(Ox5o40@Ze+jlP+h-14@K|C_#nbP3ewxxFTYa%cAsAv!a8HkLn?pJnN_z=wWo zLhV$KQ)7ASU(#KgNr(+XbH1zsTWB$Rmh(q&4;D)FwU${gO{|p`Emo||e@ykdmyN9w zpAZWiUu0{@*??cMxBnN>-oeH{h`Rz+<2x$Q#FbxAXTMc&2`r((9#>%*D+NYi6>FR& ud}izm_W{4es8Vq2Z+ON^5os1|;w3v{E8}Z{YT_He0oJjJZMLEr3!BdXXO~<6 diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/CustomEvents$2.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/CustomEvents$2.class deleted file mode 100644 index 676a395b031e505a7758282d25e879aedcb3b12a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 688 zcmaJ;O-~y!5Pg$uv#_`%1PYYT6y=ZrVj)+mULq<*O1V&R;I>Ju;A&$_Yi}g}6BiCu zB@X-meiUN7&7l+wW(LODxSLyNCKpqwoo#kP z1cbUz4b4c#U86_JDWeG$cdKmklOwhkK-$sDLp># zwXX?5m)kCauq5ySl?Y{g6bP|QSZ~d#srHqYm-%EMv!BTzmApXT43qRa$&~kJ!N4y- z*n4NHW``G8Y9`v~yNSsyZ(D!c^gqZMfqFc**Mv}RwQmT~mC3WA{I2{gEB^|7;1^51jXRH*FM!_cjW@l_=d@fL1*ycCD4)^@RRy1Q_^A!l$mudh2 diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/CustomEvents$3.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/CustomEvents$3.class deleted file mode 100644 index d30ba1ccc48d2a86e6185ad993d8d5c3c9f4fb5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 766 zcmaJ;O>fgc5PciFF>$vf4W&S6OKD9>0>aR8D?&&iNRiTBf_mV#aaO6p*+t%UrT!BR z{DfYR_>eg81Nc#hS(5_@r7PJxv-9T7%$uLTzW)HQk4}IJ!-kc{%1NB-v9>1e6~^jW z|4b@tqJscFL(_#4J&|!wt4V58tr)8IG&Rv<${#K!I3(P&RHgPg!+!fR;P9a zr_P^0`fdP*txLL!4rqYoNGPq&XSy&nZS()4|3IEFumSb$G-2@Coi`y`*a&c&p|w~j zj!kSa)TYw*mCUE-W$w%Bi>I_HIt(i#E0T9d;{Ck+aHNYok*`uW;OgI7d*q~KsP|Qp zX+u&TNqed%9DBG=w0S|>qsB;GK2TJwmkDE}!8TR#T&+gKX-!szz5rL~y++nCMSZ$? z_rVv0-G`gsz(19!I{m{E%_uWMgZ%B1i(?f{@+b?}uvTI?u4A2|3^#Cd&fOU3VH)6y2AQ3>~Kpp)|JGlC)-7piLn}Ymr*h(zGVhq=tyb&t7JxWEwJ)H4M0X z^OyMQvunA))vo0a@OSt-)O`Vge9i;s9_~43pR@12_pg6m{|O+EhK7(pBCwl*ZDoD0 z<^|1csnra;{nfVZ22BlNfmyX-dX}AiXtkwl+SZne6qvg2xK8juU?P>S3WQ6H(J_H@ z1|~5jFkNr-v;p zMGzB+c<#1i?iC6;rV&@oToTBq&Z=L2CEGIFkZwI&34F(`7uV8N9RhC~xQr_T7o=s4 zF~f~idB{u2b1f%uJhzyxYIx`D9`g}g8}_)I(~&@2!~EGv%MsiVIPbY-@5fcw_Uk_t z?&+9Ad}?KfN6Ak$d(%J)X@N<(YfFnKl6su3POY?m9!4x0xT7MBpyj(yTke)q-wjl1 z&cKq|2-l>!N2E$X`%E4T&WOl|roS>i{YWsJ{~U|mHSi(s@yxsyWpb%cuH$8&li7g$ z+H$|B;UkiGl=eq0r(xN?>gc|Kk3n&1bvxL0_NgAqY+c6+9%*)q&U5#K(K+LPa&kU6Dj8c~e2ewN}7f;GKR%9?nQO71e z*YI2*J`&4_E(2Sr@Gv;xP(r+Ksq{(G((whp)WC}t8`b(>cm}@0PM@m{skn->$WemW zP66K-_*R8R0^ARR>>p@ZE?Dy_c8AO;%HU%=YUHz*rGAm_!k>z|!*rQF5rfFLBCHjUhV(Plt!q-wm&EWB>pF diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/DecelerationCaveat2.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/DecelerationCaveat2.class deleted file mode 100644 index 490485c0ae8c69806b8a7ad098cfaf77f7c53cab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 586 zcmah_yGjF55IwV5HxJi$e8#sZNeTlIY!oplf)FiK0+u(s1Fpth+1vz63qQm{u(naK z@B{oHD^X|HkVe4^_nw(K^Eh+gK3`q|lrfitL0Hh-)a;hRpdRREX_p;taHzBw_&ci2 zN|%!`31boO1TL2^dyGKz0!P@kEPj3+t`9h6g?nq7s38ZcGz#HVb>)neD?;+S zg<8ao*%*(6B>9@1mS$^v{U$CXkSBMa(08nrb8(=qI$|=%K`V54&x_VR^FueB|#GGDLy0hD25>-5!1jZdd0SX5(N9iBlLHR@1&(6v9)3r15X$- zHy@BGK4J8hC^wk8|9Tf<;um2F5sga3qgId>ds5U)$%q^V1t&3!dCXy1-hyBmi?NjX hc!#x)lysb%6G@9*Yg&4xVSd0SYbaWBMgj(AzX289Z7=`; diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/DecelerationCaveat3.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/DecelerationCaveat3.class deleted file mode 100644 index 77e46e5598b7a94c1e6896a2ef0f6cc5db8ece8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 599 zcmah{O-my|6s(@aNz9Jln)Pe_hSewr^r(oU2twS$x&%CSW**pXc4nD$g5JIOKLpQS zB6wK#><{uJuGLA{)4~o+zxTRcSJi9!`R(Z!fGw=#;3+IxX;_KMX;MpUqkJTx)Fsu{ zB=MnciMHE0WEF}I50gmB2T@DMp+sNZ0R?~8#K!I^WLDRz3fV*U6p%rGfIj#NLlqOt zm*$U}q~CO{E()WSB-Hh)PK~R3n^}8d8Vbvm|JvE1RN9RF{c}#iuK-d87{jXybLxicLZj~Q=-YmRl9Q8D(F9+7`w;&Bjk zU|<3tm@DJN;r;qo?1`zImd2F~skE(Fe z5*S$Qdwzb;_I<71J^+j`@Zb;*tSqgZB}Ql3mdRMji72fHm#|aUay^sDO-&Md=c-Wl zg3viSo)X+k<^puk579-B5T&Y+*VR)d&7H{Rk`Sjl7xSqws>Yk5YadieI86T?ea7~t zDm?5GhV2IOHJ8s;>0-Uh)ej61p-%{Ib!BonQT5PpbHwSRco7(a4f$Ze;TP}8(PNZw zCeGcHCHzH02OMh}h_S^nTsLsuX2c)TibstZ;J+ifUt;f*c?ZAx!5_Wf>f@$s{~Jx5 BO0EC^ diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/EnvAttack.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/EnvAttack.class deleted file mode 100644 index 8cc691f56f5869502702bd35cd46d136b24306f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 644 zcmZ`$%TC)s6g@X_5;qtEDGd#;iW10UQA=GRQ6UheQY9A;c?{F`A4c@kL#; z0n|l5px?oFK<}gxr9$;$?!)KYbLY&jyB|LRyhW>k3}ME|zLAlylWt=A{*D@K86(1P z1vrF??S@Gt{jF#qR4AhZ3nS#;#VR%%glwbPAvoKNDI$w!9&*SNNLaFy6L4e-h^-Gm7mb z)uH?lTe~J69^#E%7)#904u@wrV~_bPaP4y>j=9z~+)GX}ydj3afhmk}?)?F99OsHh zKadrVwB&lZRGzxQ^DnJwRIf0{;nfwE{;6u;?{68J9gd&n5kLhlW>LZ%XY=gH0&1u} SlB|y;>q8#7tkvK&gXV7sz<)#l diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/EventPriorityFilter.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/EventPriorityFilter.class deleted file mode 100644 index 88d8192b2165d0571ac209a67472e3ae378aea5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 931 zcmaiyO>Yx15QbmpJIl6Jztd7kmzFjS&;_nRDCJ8W0zwH&&(5xu7`EQZaUyZ!-*84k zLE^v<;2&`T#+xM#sDeG%p7qQ#?~Lc$k1t;V+{e8lG7O#(LnA_8$GzAL{ikE0%quNp zEzP@UGBQFJkz?4f_dy&A|0Eo96^O8H0~iVqq>|<#L$-F*Wyn1y9|u{KUF1<TigJO5J2P>$7eX-;_*F>KFOl>Yo(Orbe`KkL{n7q@N47R^YjHV?UO%l?3JF?ylR zi+q1DY>n|q2Z9EJ+$xt0%dxE&9`!AoB=782B**@)z_I&*_N+0Qvq31(#4SK;V zbatl>v@eiF0%yS|gtWmiKVOg&Saow7 R(u`KZ9ULb#pW-vP`wNziy~zLo diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/FairPlay.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/FairPlay.class deleted file mode 100644 index b329dc70994c74f11517a3274eb24a9c48bd0e61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 941 zcmaJ<+iuf95IviuaT;7oXqtw!r4(97T&SUfatT5dO5hI>+ zF9z|z2kr{Kj>%%kKbA`BCk)woqsx$cPB}$nF>hlId4|QdRN{3!=!xi< z_X5Fiu^oCm=<-OK{rE7aPvnrH+WxzSCgDf1%76Spdg&{IaBM80Of^HHkK;&nc%Mfd z>7QuwBv%BNs~;Ls=R9rZe(1TmC+XObP*fav~Y!?_HQy9R}D#tNS+D066KG@8|WkIJjwHhhb?#9%~u6Z)q9YxP@H`sW2Mwpd$jVxMySEC3#%z%Nn^={TLnXvu`dxu%pc6cJF<6pWS_S_xSV8t3LqDz>XrM5ci#9-zlXk z-k#?lr&h`b&Z6(z#b2TbD-6kT(JMKr#nOrG7M;?T*eP`0DZ6F=YlRMTVp}1cp-l`O z=r#~Rr$Vn)cAfR=;hs||*n0<#Lciq|?SpN*QkM7NFzoM_j}_12$ibaxv;~W z`44eRtiS5pX@s?5Cz(p~N*!zxM61R^HjL1oNkJTxh&r6j# z`zT1I$8+;V+jW~ICQPeYef!PwiR1d|iEY6gGw_L&8>=u#oi{liH}IJppLHJPU1{2qW^J#@a z)6#wiw)-?ihqC*WX?Eia%tUcr;iIGw>yD zkvJ(*cRU-zJnlrn?p$c3+U8~8D{wR-M*<|x$qHL077Q#3Es^4ZckFbNsF@g+uoA_x z!e|3XMsVHpSG=lQTK=`@9QkF>HSi7YbF4I^?p&c_7dck(py+qoLHSk#TuBT2;7G$;FhsQKxd9PY2I#M0EZSDTF z_+X3;>d+e%p~ki5Gs^cArJ{^XzC_mxDj}{V^ffSybJUHx0p)qVDfBd*_XsJ@iOB)< z*3d^WSi|s{w@asQ|Dj2Th8<#LV3d(B6DEN{T;U#%w1r6oVMetN!4*vtd`hy*lp)G) zCVPdyPg@E1=<2Q_jL*@<@sz}e>c#;g-Eft+0>M46Ln`^s3FPi;m^=N%Oj^GoHC4mS z8g74BqtV?{j9XKazvEsFnN!3YdiE4XL$_Y&)aG!T>jBKMid8K)Ikt6L<}|ZOQZ$VL zw&XI`+{AT$*Jo&dgZnv4ubWum+a~vSi&&44)0N_T@IV@P5H4_MqhY1pKtqL*lS zYFk<>P!oE45q=)U(pnU&{N=jH13z@U6srGaYBDdm*Lb+o|LsfcSW|s?Rl_5SzeRM^ z^}j^a@I9HxC0k51bYY^Q2TYil(oC4FM3^vwca9 diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/FileOutputStreamAttack.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/FileOutputStreamAttack.class deleted file mode 100644 index 11c9c1d91c821c74eabaa7e74813586ade8cf8d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1214 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 M@kGW@B{72Ce+~%N1poj5 diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/GunTurnRate.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/GunTurnRate.class deleted file mode 100644 index 88a48cfa1fe1a579f8c4f561cab2d754600994ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1609 zcma)6TT>fl7=FG45(r-lLJAaGrP@Q19#SpXmb4XUN-2gO0!>ezmh4Bm%x0I_>@vM@ zMrZU!ue|fZ3-7%1qBFYf=!`$WU*j)ue7?6>o<>68 zu&-LaGK-$O?)t6b&A?d;Jf~{-Dvch2Q7x~#rYg>x+lEtDW>o_PQdca;@~;UbbNQM; z&vjxlNTOe&7b$_kish)=L33SsYsR{*1coba-LPwhXX$$^?D3ykErH3(YuzZ(gcmre zxh%crUk0R-7(rIxU`zQc#J*HT~n)rF2r9PU6hjsaHGhOb#BC5~uUN7XY` z4}3N6nB}0k)nU_+HznTE+JiI{Ygett(@6c8#M}C9Ab#u69+x3aPp2u1|T1 z0!|Bz6ESaY1}&dnExKNmT5U!L@;G199-NgphoZoNhSI1dWtf)Jh|*rx@9#>Ml0l^7 zATpT7`)SMwjO>&y@GZM|pG!;PA}$F`IIh<;?5eU2-`Zy24O^8}!&8d2&^avklX_O7 zgex@V2EM?d%BHbx6fL)S*Rvdd)%TRqETzE~7>izP!)X*Lrh5y4Wt+;={>@3uV}btB z|23=0K48NvXHdps8aD)nUe%Sji6!E<4LeYGHfT7voNwFSWucV8RV?dX`%okHzUOOw zSP@9fPHE&FiMzPRt~Iu{lw&fj`>E_~gKpbhOB;&YlB z$5@DD)PG5yIGpY z*UNpT5aP@dm-G5?s__yRmJ7e&^6$9%h>{Op;`$5R8m@%6oexnBaX-YPZos1v$u+KX n=w~P+9L8zfh>TA~eKHdp@1@(HFfg_#1O1FAU2=miB(VMujNVmA diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/HttpAttack.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/HttpAttack.class deleted file mode 100644 index f4f7477f10daf17d829bc404dcaa59b621f7d00e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1118 zcmZ`&+fEZv6kVq+OsNA%rQ8I$h@~ykk&8D#w1Nhbf~3?MpUf~lmeDfPOsB-p@y%xv z1BoWaN8?8s*O^vZBtG<%E4Ez>qRqZdn?+@`>qKvRqJc0zKQs;{Kc5)>c6vo_}Yam`2rfD#n5D*-m9mpm)=C z>b~jtC9~R)QS=B*9kKYT5kRS$*}B{CEcw>;Dl+Rx-w^0tw;kKx5D2HzC4tB$!(s@d zPe%+_1p4!~BljA|hteyWhgGS-UCXSNOwU&DmNDWV*>!=j{QrhygJG}XXh;a?LH7#( zWg#EKAchs#h(IEBd9ZXzMU3gVj&XrLwPXACU5ALNbTg+_uI*dXaD)E8Sc+)k zwF6?9z?6<@%y7(#^b4|HBZX2?5b&|1B4%~mLXyag*l}tNpM*>ESYY@Mvh5ljjJeya;QQdmyl&BMa^!>^8XML~|CV>~pIvC{|p=vWBJ3iZ7mhuw+ef zpkoDhIYF(NK_L}A)8YgpEjItDrqcvX&cfjMp{Vv$*a@wWXEX^aY~O}9JkoLxW= zxWm_OQz`U7$$ZzWwL}v;2;}(OR)Lr<*7FVFn~B;r15X^IUypnEq}$}>v;4WL;3kLjDE+&?(H*7 z4&cW}jPl>jy@fN(z4`<_KcD#wTJD?%MUzN#J7Flu8TJP1RLLfeNsMDksS8QWB107| zVJ>KAh4T=y)lQ6Y_i&%p;uQJ=Jmh@Sj9A4Q>trN9v6#k}N+OjNnipZ^kT-t&x;yqOZipH8s3~g%k-*k77)iO(VXE8nzzex-l zfA|1ChtHv&*=~R)#MmZ#_RM_eJKwovfBydd1Hc9zWRYT6P$E>qwFAH9tI)1WryaRs zhaZUWkUL^aDeipC!eAKJ5XX0gz2zQp=?HgM$1r3bdeT#m8Pdg4lfigO7!zsqTIfNB zVX)>&u@fD%M9|=^wqO{k`3`S4dEjY3IW*M17cwl>{zp-TvIUXMY`&#h=x2ghEsSD} zA*Z51*2Er3Gm6`#W@dBY95i9!ss{D&eZgHFHf3R2pBOEwl%c<_D}Kcf6IlbktUFxF zvvLc?+F2(q-aI=JQdLS#%{gabJ}zB$HE9;a)tRxc8xO zqQFz1?H8Ww3c2MtA`C5*P-f_J0>PEojoN}5StwSk)$Nz>s-^Q(Pq#5y*zxXCaYU$?n@Z#VV>|C1h`gv=L>Nttyw}9qBlm(4w?E-!p-!M`wfe4j$zeS%3rW@3j2i6z%a&Ws+|f(C=0Mm mXGKz9#tc?3{e_x}Q1RN+o)+`u#-T9VL^$u5)C)-_kGoND^iJ| zbELfemU!G1QY8>$u=Q!(ZwPm%(dDu(8oN52VQkZrp4wuF7E3jT*h7j*BZ`!TIK~*p ztDY3kJBRxsc*P0HkgNK2-m3Ay)9Y|ErVhL|L!tT~F=e_a=*T1{7_6tBdd*ucqcVvc z!{lC_OBrf2+i5UNS(t{+FwqpsY`zFQKk(FhhUsGUE$?!-#bwjoQ-LR&T3kz6ei1P!%8{|vzk+vtZr+EF{Gkz47o%Q9YWO|HZ zb>Q^qiP2py)l$U1Y+)HIWQ53 ziHVwYO3f4ygqb%k)(jaf!ZK+XE64p)u`z#!{}> zgEJJEHYdwSVa4F=eq@N#U3vvqiNolR;CjfbkPOYsII$jXkj^_j+#MqODp$#zHNvcq SU^4@32KTUKu=fcR!S-)~#PYQO diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/JuniorEvents.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/JuniorEvents.class deleted file mode 100644 index 35170da373b938d7c34e1d2e10e4f24e07f34de5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5577 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 JjCL_R{||rbCb<9r diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/MaxVelocity.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/MaxVelocity.class deleted file mode 100644 index 88149cf5669ab6a679f6a51e934da5f1a5c744ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1356 zcmZ`(OH30{6g{sk9jGHB@-HeswN#;sf(i%)fe02+F-=$w?Gs1K3@KBB8`myONZgsY zFuEYoxG*urXky%$5F;@$Zrqu;GjZdNNQmc6D>kBSPTzg++_~r8`|kAJ=F8UrI&fKo zN1)b`^NvhL()P6N%tywJ#kfq_3Ddc$!6#6q&J%W0Mh21#hLw=X%gRx}-)mZ?(_)kOHY1%Y<}71Ue5`~_g^o&8ac^gsTV?FJv0y|@J905?TF#`Cmd0$4 zh8lrtmq{7cOoYd#H8YqoQ%RW)pbqsKf)x4NL&sk1qv(Q>%E*bU3?CY8%_$Vb=?S13 z4XXG?<*}V_jTfU?z|-BJJP+tNh(m0nF*hfzq(Ixh9@!QppDo1%T6KhRSYQXc@%zr) zjtnV*HYLz5P#+rFp6s76)i|o-7&-)s9Xr<%b~Cj75lWswmxfM(J^$#gj+3fzZB8{j zW%;8^Q4SfP67A8^i!)T1m(IX7X|P%!vx+OOUq@7N8o5Cual;=id#^rgiX750tjJQ5 z1%v62PPwt+f0J8XmGe4cYVb684;rbJ0~3mA2;UmV;7jTGwFmJG1Xv} z6~t~=wV{#XUN^Rf7U!A28ut;df@@KD1;x*3cqk2*21>Dmww`m~x|2KR{`+CE3LpI; z0^uxn-R=$U#_B_~gr8&2D^yPfU!Zmc`^%fMJj)`K#gQx`SsV{OVVqBdQc~io_zEIH zgos(9m$*e-ByJN);vTU`JRKYP>{SK(R*81hu#P$`A&9%! z$6EH|KAKodGajP_PjQGfgs_6ctmg>cq7AD!iVvLSj~vv`=)@Ov;VVw#8@llwXYd1k zSVuoLFetnj78?Id)Qwf;ZY6(XejzZ93+(g+IhD-@+Qd&xm6VjZ-%>RUs?Q!=`UM3K BB2oYV diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/PrivateConstructor.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/PrivateConstructor.class deleted file mode 100644 index f79a141db22808148aaa6d1d06856996ab8bf6fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 zcmaivF^j@L5QX2wXf%4KXkn{XYGL3kPizFMAfjTwi3{$bS=em+UsoMmaX;XGlsJoa z7B=sjH!}=x{;$7(06x$P;1POO=2jjeqZ4iOXl>L*Sh>(yZcUL|Z36g&cQ;P;K}H+5 zN2ttHrtF+h8jkh^f5Ed5CDa-yqe5uLDwC_?oJg}1$w?C0u};NlFN|{j(e&+6<%B`} zD#a%u-0H%la;e<4?sL$|m$(S@!I}6!Fg=%r8L*o&iCG^1p!&^)hmbX70&V!{pw3m} OzQlZE$B(mmXx;!*SVunq diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/RadarTurnRateAndSetAdjust.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/RadarTurnRateAndSetAdjust.class deleted file mode 100644 index e314c5cd612d194a881250f2fd7b1b1fe61ea57b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2151 zcma)7Pf#0G9R41E5(q04N&yS4P-#ih(pW5FON*hTfS3a1Pb#zuOY#Vdn+DZe#haskZ#My2TBn!ye*1pk`+k4lZ-4yf z-gf}{@J0|70zHl_I5HEn^DB9$5S!66x;^LG){O4RVJkB$o#D*7TX2G?5@=DVbUq_v z!3LEJ()>gb~dc*)_UZ6;4D_ z3e=*ZRr%E-w`AJ&B2BotjdI`$@}!2til?E(Gv-b% z&yw(ONl@eo4VN*>Y-Xk7g)lDljA3QHj!7uQxP}*1NrI)4gzyrs1d$XtxYKp6W0OF(V(F zwhhafb!@5U27{OvX!SIvZe?RUrhAuM!^}uq`FBmj%UGa)j9|{lv4z>|6Cqs3D?!{~ z$sfF{;Z-aVzp0z9oLZ&f@I=J7y~n~}2y@WYGg(oH{rX6%1{r~h^PLL0sv(OtJ~(}2 zLs~rVeb|+KETuR+W9y3IH8wHR^S{8H1`BzC8Yk~(L!ddl{|ZT8MY|mj5zwpX>?i{LKn+Y=`~v=B@P;{L4L=$ z3+~m?JE-}JLIo!SJT*{{I?9?4;Qj=^_$JGjD?TSBFN^JHGa8C$B*!6NY}*yvcg3T- zV%M(N?TM8|^ziPSp6|P!|`wi^Zd)*pmv#BiRZD7bI9X7 zHZh2|Z~?b*5g%X}AM)16wDk!R_>^<%GmPR3vV6%A^bL}@hb#D=j6YxsKVcd_<0^h3 z`>#mhH(bN-oD6?p0e@i;f8#p4XGv6JS%jdA1~z{S(&7joaW|w0!w|h#7kzw!12Dx9 za^f;9k>pF8MnTNO5sPre5;nyuZi*bXgoACdg*SH_S8SIWw?h5K*siMU-{T9Y=H4GI zVq~1lm=b!jcQG*${TkEXVs3#ask>ObgXN}l5i(MQQG{8<#!k|iU`6sa*ITH?yZo8n j##y}Y8SnI-TYt%THPh@enSA#+hMSbs%h}@X3T*!eNVL^G diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/Random.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/Random.class deleted file mode 100644 index 12daa16c53fe68cac61b3670be899752d9c770be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 576 zcmZut%TB^T6g|VEyov-wK#UJGDxk56Ta6*nxB?eoNL)_oKr7IiGO+ezwQ{Qbn16!)TijG|sjhMVQ)Ecv8{eg}{m5HnRrs&fp z(j7@vE&i}rDcSL+eotIGYU$Mch9^odDl|GAP=^T7ndpy^Z;)kVqxDzBp9zF$RRn1u zixgpfUO+ZY9v$GX*{4CO*{J7{c|&&if+E39kr!RW~gCLRoD|0bip*`vBeOs5luk|^C}{c8IpCU zXYUT4v~6$CYfv3SR-*@^9M*Y7^uF@6WpeJvqNH~28sFjKn&>3QV zo9_+0o)AtN3fGG*d9ohx+fvg|6kUh5BrQRpzcW%Ifl50#<+KAxC~>(|6?goAE#zX=w#?T(#|y1)T{%w{E-Np z$Vijhu6ZeRqgO%?b#KJ1nVRb==tDn)e89a8gPT=`>1?qPQ}!IgIw<5KCMQrs^}`D( z3}RTq5JO)ht0_dmb&N2yyWCsVb?&-`Pdc7`m)jNDV+wBICgCIq3=`4ruPaBSdsFw& zl)^YBB;0Ny9rzU7K{jCIGi1nQqxgMeLB=FQ;*{8V5~iBU1e}FrGYVAPWk?dV688>m zl4m6fFqG$gM4q60wBdysK?PE5Rw#C#q5p5if*2VO7}_?uY1(6ZwqsUB&LahnF;DYl zSZDSzjm>-%NvKN{$-mW0f}x-wjYWo@0J~wUZ-f}ch-)VVav3WUo{)GAkn10Gek#^L z!7858Ecx=4#Y*frnof}VLr7Pui9JZ{2jevm(dt5(V3fqDR*u9vG+Krni1kUR|6s&> zksm6{zz9P~$X|m?#Iz>uKG2eO8ZKC>Y}Xu}Zx~_)d$zCa_>90ngGr$1#{jg@8?7&$ z65UjKGI}N^zd}Cu-6=YS8|XqCok|cu&vv>oT)RyEMQ?GkJx_O}yXwdk^YJ0 z(o`L{(z*C|bia+I^W{3Gx2DN^Z+ePs<7As7+rz!jP>T7D+I$fF=55F$fqF zNYdE@nRdG!{m5W|Y(vOn7z-GoxKV5nHvw~wSP_&Erc86ThG$eULtC^?Q7x3&P5w=) by-XEf;3auqQ4aknKS@}Y=~|>~3rc?gm|;rP diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ReverseDirection.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ReverseDirection.class deleted file mode 100644 index f739e851974ddbd29dca848719eb28a0d6706328..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 675 zcmaJ;T~8B16g^YQE-foqXb}VvL9yKkoA@NbXo!tZ)fg~+-|pVPn6hhTXB&L-!Cz!z zYT|=Gz+d4{@E53ODndex^Dy`0+;i`lJKuhO`3m46c70S7)~ys)(#Yh4+!oQHjKmbu z)kYGl^UOz8Vab6>o=S9(j^Zql^w3o+c#n0a?GuHmcBijUea4zPrceto4Nqadr!#q3 zo({ykjt4_gSm@tipJAH>O1-Rj`Ibtv3v%U=TMB8@`S_yE|3H0SmlF~|zxwQbdu+ABI$)~k?Z{krL z={$O6bY_pNk@$4qaW?|o!KT9OvDm*oCmZP2aTnV@?kOz(gB;+#Q{%sN{f3$M^!wx$ z@P3`YN1=X{mnMX6QMX2qvO)$~80$vW>MvaZGQ&WS3 g7U;FG%8%H@GCEkn4%YC9o4ypZcOmEjnHB8(1~wsu*Z=?k diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/RobotDeathEvents.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/RobotDeathEvents.class deleted file mode 100644 index 11a743a35c0aa8072bbc1880e7133496e5f141fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 974 zcmaJ<-A)rh7(LUL7M4X6Y@tO;YZcm6*~D9v#2_Y`DhU`8yxZBVUR8BaQ%fOsWf$Uyeq?u3It(eX?m`@j!; zwJngYHx8M)!+Ha0%$b;hAu!+c1NmamYsu)P)9Olrg=XkF-9snxwLNlXRLAcNRGRolUhJhl=TE&_`zTQl54pig^?XAY4Zlh}Arq-F0r_voLsp)T- zm_k-y?m#*2o9E8)NTeAC$>0T6>&@}R6MwuAf^)naR_Wg<;J$tMUC z5pMDz97L{s;_IE{FY)&`wOmvwCe6Pn#gB^O7YEBb!wC1wbC#CPTkxK;E?|C&)2{H$ z#?D2|^KA|ja23~R@h=z`zl*^LVp(6X`2HMAA5peGV<|R2oMG-8ibo487g+s4SB0V4 z*`HsUCJjwf=CXlh_ERKHiRTJxSj7fkn^>Emw@381nLmZJSxB>!btVpF?9iEFXx2I+ zy&>63BF2bA+%>Vapu#Y9gvcV)(IAk3g*zj_ZRTjetd%)O?K0Ln={6>?vSX|)vF^rL J_gJ06=3jW~z(oK6 diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/SkipTurns.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/SkipTurns.class deleted file mode 100644 index 436b949dd2f248eb6ddceff6bbb0c756649a376e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1733 zcmZ`&Yfl?T6g`6ATPQfTur8?Cv8`YxWm}>0@gWjI$ z3Jm8yqMO75PTkUQfsm(%t~ieEM3591aShLOADOZ;os?E3Su#AYDwDOUG+go@#U;i6 zQ-Q(BHr090F|EhhR55&eoWAfECHKoZCXo_|c(gnxAJN(1rPp&nySfrPG0Pc zVu>-DuU=jNi|X<4YX}-=HW|M=(1`){Uickij1P@t4_Du?LU0~TAE7rLc!~b>Ys7Yr zF!&OQ7tPWkjspmCjB$(;>K4Zsh8fXY#rOp0x#BB10sg}W-cA3C{>XE5zsBg!z{Mks z9jD_MZ(zdT=u#U;NFS$r8<_fE@Z-5NhyVVE| z8TT)u{6|XGO6Fa##%HZ&G^r>YW>kZ@%G2B{gH5dBEG?%jt zY)`#CM0o1$@e2ZIn4o)k&a;>!+#Ieq=a%~uqy-AoD5@8$BzKp0agR0Y^gBlrmoSgb qHqu$2becD|i0?>Q`96s7-x$#l>s-{3k1T80`HNcu-*dAAKl}$P#a$r) diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/SocketAttack.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/SocketAttack.class deleted file mode 100644 index 50cbb72976d3dac249af1baf71457a023358b049..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1613 zcmZ`(OHUhD7(Le>dx$%!LwG~dJV=TSIMe1yZAuFvDWv9+m{Os3GmJ-MiZf%4#{{Wr zltmVisw}dI(#H>A9jP)>BelCM`lCwEox%7PDGT3k?mge*d@uj=@1K7GxQaC$34!6z zX@pMI4E#+$Y?u|_-gd&-FtqG#9hyMD1Z=SWxL%a=RmQKBUs zLjnWQtLvNdR%k7H^=4QJ1IK!l!3fUkIKyO)*%|l<=LA07azaI)p4uVkOaV$64B~<$ zcu`<57qd8~l3&+xi6q-xRs+{lczkSN3^_7k$dzVz#8LV?Op6Xxgh59!E`v@840VG3 zPe+!j08_^mf!=m#Rl~q1vZ|@afg7^FS8-j(HHD^l9|`zif}U50?Xz=DV0>c#qFOna9hq{ z%C7khG9SSlXQ2^I4I8CQf-*=PwX|Jx9gkGI6_t2c1QK#qJ2@!H(=y=`>_19Sts+rD z!ir@lJz^&-a^IG$dbAWe?zan3v%D>H?P1_Qj#nsC@tc9|+;!zXb*syIMK%u?Snwpb z8%Xerd&pDg&7>5RsquYuy@}uqPYDA(_<*MoD^Q-~jkDc0PMo4k>Ew4&7E5oD-RK_6 z?z21-E%fp}xG~wn@IKBjzs0EhzPyioQ5({<7A6ZVeERJk7M2U+f8bUNrHOYiXgIrv zR53mI4huAx-@|M%y@%;y>Nsq~Fm;Dgf4?7mgDz;8LWzU4fHGDnzrhB+r_?YHi}bg! z4UhK_yZDjv8J^>3%9nVBUnrB1C3%8#Jo{O{0a_08e`Ex`IE(Y#_yW&stnm~sQh$_w zFEiR0wn~Gg zRX%{v;G!Z1?u{b$>lye|-7^;0&Hvh%pRm-qyU~D1XVB?p2_R=%%X$wh)+?w`YAf>z1re zMuimm8pGk@R)(cThQx&5;5}g2Zo@(PztPy}#{q_v>v_B#Vy|wEsTMXa(4y&h zzVrg6xYUlT{T1OkW8qPinlE!zN#hU>TNq#{{kM~iJdRLTg!B|&q0nQpag*z?Th$&y zG-zW8!zB9wX?I8E2;aG*gw*qzSg=yDaExK^+Js3hQEkquy#iio~$1 zxY>nlFW{1eiwrx%k~e~}aoH4RwG6%{4Yh)+7DhMlIwHS~Yq(BC>&_%n{+Tnb;;XO_99?)ggS*C|X=^M6TsH{2&fq-h&BkzOOpX~X2IjTyt_#7kG`6l&yZX0KGx zqSZ9LwJ^spur`Txzo%Y#yrqRN8DfI^$*T0w66V)6^>60H?(Oqt&FgNfyBw2SQue=A z#tfNZ(a?ZUrsw@Yd3;)!TcL0L-Ez`kVX&)Gay8L(+igy3nfi6(5PON5^lSsmX3fUa zl@&+Kge7f;q;n+2=uDSKKEN)oV#hm@V(6oHl5BuUd1yMVz5)=PudC$QBeS{v8!ow@~lTg2FF!krv3nAWfD>R&oFDeKNg_;X(L*h(~mq KPSgHVve-|iHivcq diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadAttack.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadAttack.class deleted file mode 100644 index 380d973875e48f1def89d473386489f4f438360c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2124 zcma)7YgZdp6x}xoOh|`EfzlSR*b+1ej}Z#BHAo4M*60K)Ae#D|Ohy=m8P;Ti_J{Zz z`qi$b!6j??1NFMqOXFpr z;z}0;`c!nFQ=nJ39c!a`P_w*kqqc7e^y{u^?C%(!E$7i<%HOja0;Br*(UWS@YdW3F zRjS2bhF)%}7{-V|+HZP}Zhc1?Qn|JKPUmv=-$P?6-js(rj6F&z&F-iemn*3nRTb#o zlIm8B!-!0e>ui~Z^<2&m|)U}x3k(fCZd87rp$T3WpT%A-gC08@;)j1Ne zq@9fR0#pU>2#lXEM>cd~c^PP!lexMpu$H?>zzg=;XpBa|0`nK7eBW?(qY}(u9`8yw z_XV!!!U_wvH=B+lGa2YGkM~p*WyBo~-|&1{3h%2}!b4`yZ8GRgp3%Hn$Lxy{2gK4wK$o}E^Kj!&d+n>-)ajgi~VZlIcuZ55w_ zta}=kUon27G_Gg+&ty55Wqr-#bBR$En2BSAL<6tI82?yG1QPx(GZx#88C@WBZPr(kSDj(Xe#19~@9bNAc5$}CUBR)haEwgh1ZwpdJ-?y%1=kX|%4bhtKZq31 z_F@qITvJ0E3~(;7ueI@N5#Cr~5JN58;4s?4tuwRR&tLsbvt$52L|R~zQZPbSql9{c z&zmtfW04!#u>!KJTf7zVU+0+MMi=?N&41x_;^QQqCB2CNaVR_-A<_)fm#4%>|6U*QaG;u#J^&a?X#=w*s~ z(~L}GKb;L26o^jjh(QM3c!bA98Q}T{D3jj^nS6+kxF#d!H}9!}QkolVlo7?>d04_M z#3}04{*7ZisZ8}{TG*15r^xxUjp_g8oWo?B^Bn>cjGXT=q4ych1Ntr^hebMF;^kTn zxX%Z6>%S=)l+;yirFZNWI*;z6#P1u(tT-siLat4COAs@Iw)rEFMJ6Lt}|F% l2|O~jH2E6e{Kw=>szZ~zrzQmYHh?ow<0!u~8viB|{{U^|$FKkZ diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadGroupAttack$1.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadGroupAttack$1.class deleted file mode 100644 index 7f72191e4a25d17477461b37d4a2ea6b307b4233..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1125 zcma)5(M}UV6g@)=OP2vEVhf@`p=w)@QdC4i5<}2niW(u9=+ksNfyFZ0%+4BL{TiN4 z6p0UhfWP8{KVZZ=+a^RHsheze=ght5p1JqTk3ZkO16aVSgD!@gk)e_GvJPs23Cr7i zT8jEp9YoE?#t83SzTzOsklq*XMY$o=Zuv!RUwXzt55v$Y`YKXN)EbhZ$L#rGex9hS z9k`b%c*R$~S!Kuc3U zY|?lO&x$(^?lO#@o^wMPsddyOo34NGWYhS8V(4qe2W_`5drnWQaWs}KYvWDPY){_Z z3L@>vC%*M+=A7T>Y+bU^y7C%9=&RjLY4(CT$BOk>ik#587YuwuDXG^QA`E4SN%CZZ z-fpmT+FFzDSQou1xP1&x){MdEE2Y>B`wJitTxCdp~bctn5p JpjI|Le*ymj5kCL` diff --git a/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadGroupAttack.class b/代码/robocode/robocode.tests.robots/target/classes/tested/robots/ThreadGroupAttack.class deleted file mode 100644 index a4397c81a80288d265e4342efaf07d47a87c57d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1967 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 Date: Thu, 25 Aug 2016 10:01:29 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.projects/robocode.api/.markers | Bin 0 -> 597 bytes .../.projects/robocode.battle/.markers | Bin 0 -> 933 bytes .../.projects/robocode.core/.markers | Bin 0 -> 677 bytes .../.projects/robocode.host/.markers | Bin 0 -> 2415 bytes .../.projects/robocode.roborumble/.markers | Bin 0 -> 293 bytes .../.projects/robocode.ui.editor/.markers | Bin 0 -> 1642 bytes .../.projects/robocode.ui/.markers | Bin 0 -> 1066 bytes .../.safetable/org.eclipse.core.resources | Bin 0 -> 1328 bytes .../.settings/org.eclipse.jdt.launching.prefs | 2 + .../.settings/org.eclipse.rse.core.prefs | 4 + .../org.eclipse.e4.workbench/workbench.xmi | 2502 +++++++++++++++++ .../org.eclipse.jdt.core/externalLibsTimeStamps | Bin 0 -> 972 bytes .../org.eclipse.jdt.core/savedIndexNames.txt | 29 + .../variablesAndContainers.dat | Bin 0 -> 19199 bytes .../segments.gen | Bin 0 -> 20 bytes .../segments.gen | Bin 0 -> 20 bytes .../segments.gen | Bin 0 -> 20 bytes .../net/sf/robocode/dotnet/host/Module.java | 77 + .../net/sf/robocode/installer/AutoExtract.java | 382 +++ .../robocode/test/robotscs/TestMaxTurnRate.java | 72 + .../net/sf/robocode/installer/AutoExtract.java | 389 +++ .../net/sf/robocode/security/HiddenAccess.java | 290 ++ .../battle/events/BattleEventDispatcher.java | 154 + .../java/net/sf/robocode/core/RobocodeMain.java | 414 +++ .../java/net/sf/robocode/host/JavaHost.java | 192 ++ .../sf/robocode/host/events/EventManager.java | 572 ++++ .../host/proxies/HostingRobotProxy.java | 306 ++ .../host/security/RobotClassLoader.java | 424 +++ .../net/sf/robocode/installer/AutoExtract.java | 705 +++++ .../roborumble/netengine/FileTransfer.java | 657 +++++ .../src/main/java/tested/robots/AwtAttack.java | 84 + .../tested/robots/ConstructorAwtAttack.java | 68 + .../tested/robots/ConstructorThreadAttack.java | 61 + .../src/main/java/tested/robots/FileAttack.java | 81 + .../tested/robots/IncludeNamespaceAttack.java | 45 + .../main/java/tested/robots/ThreadAttack.java | 87 + .../java/tested/robots/ThreadGroupAttack.java | 71 + .../main/java/tested/robots/UndeadThread.java | 44 + .../net/sf/robocode/test/helpers/Assert.java | 38 + .../net/sf/robocode/ui/editor/EditWindow.java | 485 ++++ .../sf/robocode/ui/editor/WindowMenuItem.java | 291 ++ .../java/net/sf/robocode/ui/WindowManager.java | 632 +++++ .../sf/robocode/ui/battle/AwtBattleAdaptor.java | 335 +++ 43 files changed, 9493 insertions(+) create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.api/.markers create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.battle/.markers create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.core/.markers create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.host/.markers create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.roborumble/.markers create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.ui.editor/.markers create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.ui/.markers create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.launching.prefs create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.core.prefs create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/1a42e2ddbdd28c4e903ebde7bafa5867/segments.gen create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/26522e0d83a422eed93329ece7565cfc/segments.gen create mode 100644 代码/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/Module.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/HiddenAccess.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/events/BattleEventDispatcher.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMain.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/JavaHost.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventManager.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/HostingRobotProxy.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotClassLoader.java create mode 100644 代码/workspace_robo4/robocode.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/FileTransfer.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/AwtAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorAwtAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorThreadAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/IncludeNamespaceAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadGroupAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/UndeadThread.java create mode 100644 代码/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/Assert.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditWindow.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/WindowMenuItem.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/WindowManager.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battle/AwtBattleAdaptor.java diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.api/.markers b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.api/.markers new file mode 100644 index 0000000000000000000000000000000000000000..cf728b1c9fd1074507ba4551cd70d4804fffd6a0 GIT binary patch literal 597 zcma)&!Ac`R5QZz0L$c!0i?`Yrn0W*djG~}fvSA70rKY<~I?i;5s+vfi#N+xb!oJaZ zw?{$5gV@l}#s63H{~rJh;i!^SCzm{zv77TIC&QO^>QlklPljKK}1vQF}6>IKSoiJH8)jRB)m_iYJfiQT2@kT@^|sRoB)mz2OE%y@$vok2s2l@8Nj<_X6>qv2_3d literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.battle/.markers b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.battle/.markers new file mode 100644 index 0000000000000000000000000000000000000000..b8400f51d9432364cd49f6e5760f2348385de1b0 GIT binary patch literal 933 zcmbW#v5wO~5C-5$f^-2P?wTv;rUL}BJCG34HFrn>K}as5qgZ<<@m}m*Yj>Qx(7_w< z1n>$x0TK-_K@BBu0L(gYib7*y$@Y%?@5uf<05E{3sdt&nou(vH%q6A4=V_&kP0!Ry zrIt7i^UF}`DR*8QyGW<)>Y1`?K|YCL0O-jXj~jis>HH$0yfk&7tt9haPDJ#!X?|*}9rLpw9sWS30@DBE3;KXXF z4j#buCXheThE-OQeAqC!#^*HB0~kCxo=L}-AKw3*z~oY=8{uDPtLjiVPN(t%`1DV; z3%S1$-4?qa#UA2gbAeo#fWgUKF)oPPRwJwF;`SYsNAd+)TmqBQ-B=Dk?y`K@W;y)c zk>wMN{*R?5@*9#DvfAZ1_?N?OIL5YIqtY5_C1Vrf2*t^ctB9jKp(@Raj_@u{sd6$p wc|rLypqWdAu(gY5Z45J-%e=;pGVE=jZG6;?@y(AN#w%a98Q;F@#`x>eZ&+g;5C8xG literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.core/.markers b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.core/.markers new file mode 100644 index 0000000000000000000000000000000000000000..5a5ffb364aadf7e284c9289c6dbcdd895a5ff043 GIT binary patch literal 677 zcmb`Du};G<5QeV_QVL>aU?K}!6+Z*e3R}zpx;&Q%J>c~s5!oW+g@>sAC zx2Tj(8L(v8mVckW?*Jf%fgqPV5eiRA6w;JpCKpna$ih!H5#f>9lv6Kmel|l{ z$|+J7(g4t^XBbfg$Bw2MDr@E*vzg{q`HZE1fHourdS5?`;dDIej?%lc;i!`mPNZT- zoz%~*;WS^Sh0~Qq50TMP3at-l&&fD4yo~B^TClI~CEc(juFvr!99UE0byeg@A#ego z2=q!FuAkws@<=^xSmqXM*tT~SDeUVQ;z4&@SG;|F`7Gdaquit`xn#B|`sb^4rzHU+ wjCkFfZTF*<`>!=&;TG7;HL<&{7u&AMQ#04Et2G_${WIR%E?(~s-g{HLZ{Y2{K>z>% literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.host/.markers b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.host/.markers new file mode 100644 index 0000000000000000000000000000000000000000..9af950237546736e4e997007c92f4f515903c7dc GIT binary patch literal 2415 zcmd6oKW`H;7{;B1khGLCF|eQ)3223?JBg76sWb=zwCP_WHs|~%aeHS+w$qXsHWtLl z0DKn2zz1MrV&*G=5U=y6N-wJ9c7f9+C;RN^eSUtQCycQY+l!5E=|l^Ry4t$fnk3G+ zRPjDP!n88<1))V0Y`Og|^WdC_Dm#J#D4aW&lQOXIDUIwd9~p zzl#odOZVwJP3dh*JD>^-v}KBx6{RQwD|}|vo{`#D?aL~#xuna@w&TXpcuww$ac~#(jD9K6 z#*e6Lr0V!ya1EL}KK~H}#wxQk8qH=CwlG7_8=QuIPjH9ex(LyFZ3hm~Sg92pbx|P= zfD<^bItbE2#sw|aw3-G<%B{T-#;bfi$BW&Z=2cc*wdS%B@UJr&axbXjSsG zPPn4{JdjqMZJwPLIhgLa&JEoZ1`o7SWEbj*NxV$jYi<_UvNzj3*c~^O9%jg-rG}xh z(L+^VdlJ?*#r-^ptJ7^$d>06!$|In;-t z<4xtm&|7C@CW_OPCn!b%OPqm%X_QAkVtLz<<0ztzIQh#UIa7p@T6~))^=g{b;`cyO z=|~d0bebk#obIOrS_mDjg^z==s$t<28~)klhX^g%AzVN?;ULpOwk0X|aTBQNM_$wG zX-!w|1Z%3F-3F9>%GtQ)AGvd%^#8&vqkj~y#rJtqCw=lWkklKtdUjI&Z|D?4muCrG W@XiQ3|LT{#s>byBSHA|T`tTRm(Z%@y literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.roborumble/.markers b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.roborumble/.markers new file mode 100644 index 0000000000000000000000000000000000000000..bd2015536ca5f69e68e22c2cc2c2046a0800b654 GIT binary patch literal 293 zcmXYs!A`?442IqIu!1Hbj@rt#>;W`_qn68}P*nD)qA%T4g4GXMZZ>Rjg~ zTm;@~GK1U4BwNuYFloW~0yWG$#fV#~;BvEGuCG)}J{(BB_B5&-K$P@MXw~B3Ns05M z434TJ3pg=7@}nS2+Rwh=bZ{fxr>w*o5SV3PHQFry hzKkCe{b= z#upH8?6dU3Yahi6AHbO=mSjU9abN>s4%y%Lz*&Xc?IS87@<)Ixt8i;bYt50xh(S&VZ*WxGS`qtSsX)u+lke z^o-O-(rMYfvBa*3gq!!o4Y}{N9d^~vzs<7V9Bb#s0d_mU4?`+ezk8iY3Mx zR_8|GUR+_7{jHY!#Sdp^^Kt zUltUyJT2tuFcAlyR1yfS+Om@y|2Kid#ZQDP21*co0-=ki18rg(%n(orM)hk^z`Y3p z=L-s0nHKP9C}3B1lGHr}8B(I-QId~F8wW4m?adkH>dzwc{R!sZ3o_rFW?n8btBb{% zcipOgii8iw32RFW60S}YJ{iU0!b?!xH3)DQgrT`E%6%<3Nv*8Uex%cQPIqh9itNn^ z_Lpd#+>sz%c$fU5_oUtf{%4)0@ZFxR!OXGMxTN>B@0tdIdt^fc4 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.ui/.markers b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.projects/robocode.ui/.markers new file mode 100644 index 0000000000000000000000000000000000000000..f4be5ab1765d8630bddc8ebfd4f2c9c95573b324 GIT binary patch literal 1066 zcmb7@!D`z;5QfK6O`OuE(4>LV%l4LBBzkQRh2k`%hseYx_!JoLj-_p-U9r2e$i01y zkoV}J&{rzt5NPSjae}Zf%3OqYM#J|lzW^YFxF zn)VxbR#`GfLOPt~)B_k;T^UX%B82eEaN;+fUtjlsu4s4tgs(Q%c!|ZavQnk2^cR#< zVOgD#VjT0F1e+UOu#qPxLyD6?rqlO)h-WmK%*8DYv&N z_o9(|&(2nt{;?a_#bO=odmHTHM`y5;hdezdaHmv%Lg#WCE(3TUxh5Y?z1s8)r_*US zxBj0sH+a`}>)&*AyS-z9{Y{u;nJA%IO+M~ELYJ&Y<(Shf!v!&yNz2~)q?KfxBpapV i?&CyQj5A$N{ImJ(oIN=F&`oUj*SgqMTWoKqtJr@^At?O- literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources new file mode 100644 index 0000000000000000000000000000000000000000..4683b6c30c08e4b3d5abdcb528870a568ae6ba9b GIT binary patch literal 1328 zcmZ?R*xjhShe1S2b=vdAllRFf=Oz}Hq!uZZBqrsg@^UHr=I1FmmZmEh87UZ8SQ#2v znHnoN2Ztya85o-JawX@aCKkD*=9DDH=NF~xr6%WO78IxIrKBd6rt2l=7p2;!CFT?Z z&C%B@DN0SXHNvSSw=$4gIJ;P{G!v!`hxu74B`BujP*#$fn5&muR!ofA^5PP` zvc#Osl*E$E{5%5o7o?=>B^G4rmE`B=6cbPja%)avXZ3-yJTq_DPi@?^Q z1RlsGS;a6P8k(3JnwlG%8(CNw0YeX;MtG=z^jH{~n3)=z85!dY@giVEAx9C8Km;jE u%gjk7B3eMfLWGH^9)u>40};PJgVSN)=bq}_<;NUG(\r\n\r\n\r\n\r\n\r\n\r\n diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.core.prefs b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.core.prefs new file mode 100644 index 0000000..0a60e67 --- /dev/null +++ b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.rse.core.prefs @@ -0,0 +1,4 @@ +activeuserprofiles=DESKTOP-SHKMAML;Team +eclipse.preferences.version=1 +org.eclipse.rse.systemtype.local.systemType.defaultUserId=Terrans Force +useridperkey=DESKTOP-SHKMAML.Local\=Terrans Force; diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi new file mode 100644 index 0000000..8c2319f --- /dev/null +++ b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi @@ -0,0 +1,2502 @@ + + + + activeSchemeId:org.eclipse.ui.defaultAcceleratorConfiguration + + + + + + topLevel + shellMaximized + + + Minimized + MinimizedByZoom + + + persp.actionSet:org.eclipse.mylyn.context.ui.actionSet + persp.actionSet:org.eclipse.mylyn.doc.actionSet + persp.actionSet:org.eclipse.mylyn.tasks.ui.navigation + persp.actionSet:org.eclipse.ui.cheatsheets.actionSet + persp.actionSet:org.eclipse.rse.core.search.searchActionSet + persp.actionSet:org.eclipse.search.searchActionSet + persp.actionSet:org.eclipse.ui.edit.text.actionSet.annotationNavigation + persp.actionSet:org.eclipse.ui.edit.text.actionSet.navigation + persp.actionSet:org.eclipse.ui.edit.text.actionSet.convertLineDelimitersTo + persp.actionSet:org.eclipse.ui.externaltools.ExternalToolsSet + persp.actionSet:org.eclipse.ui.actionSet.keyBindings + persp.actionSet:org.eclipse.ui.actionSet.openFiles + persp.actionSet:org.eclipse.jst.j2ee.J2eeMainActionSet + persp.actionSet:org.eclipse.jdt.ui.JavaActionSet + persp.actionSet:org.eclipse.debug.ui.launchActionSet + persp.actionSet:org.eclipse.debug.ui.debugActionSet + persp.actionSet:org.eclipse.ui.NavigateActionSet + persp.viewSC:org.eclipse.ui.navigator.ProjectExplorer + persp.viewSC:org.eclipse.wst.server.ui.ServersView + persp.viewSC:org.eclipse.datatools.connectivity.DataSourceExplorerNavigator + persp.viewSC:org.eclipse.ui.views.BookmarkView + persp.viewSC:org.eclipse.ui.views.ContentOutline + persp.viewSC:org.eclipse.ui.views.PropertySheet + persp.viewSC:org.eclipse.ui.views.ResourceNavigator + persp.viewSC:org.eclipse.wst.common.snippets.internal.ui.SnippetsView + persp.viewSC:org.eclipse.ui.views.AllMarkersView + persp.viewSC:org.eclipse.mylyn.tasks.ui.views.tasks + persp.viewSC:org.eclipse.search.ui.views.SearchView + persp.viewSC:org.eclipse.ui.console.ConsoleView + persp.showIn:org.eclipse.ui.navigator.ProjectExplorer + persp.newWizSC:org.eclipse.jpt.jpa.ui.wizard.newJpaProject + persp.perspSC:org.eclipse.jpt.ui.jpaPerspective + persp.perspSC:org.eclipse.debug.ui.DebugPerspective + persp.perspSC:org.eclipse.jdt.ui.JavaPerspective + persp.perspSC:org.eclipse.ui.resourcePerspective + persp.perspSC:org.eclipse.wst.web.ui.webDevPerspective + persp.newWizSC:org.eclipse.jst.j2ee.ui.project.facet.EarProjectWizard + persp.newWizSC:org.eclipse.jst.servlet.ui.project.facet.WebProjectWizard + persp.newWizSC:org.eclipse.jst.ejb.ui.project.facet.EjbProjectWizard + persp.newWizSC:org.eclipse.jst.j2ee.jca.ui.internal.wizard.ConnectorProjectWizard + persp.newWizSC:org.eclipse.jst.j2ee.ui.project.facet.appclient.AppClientProjectWizard + persp.newWizSC:org.eclipse.wst.web.ui.internal.wizards.SimpleWebProjectWizard + persp.newWizSC:org.eclipse.jpt.ui.wizard.newJpaProject + persp.newWizSC:org.eclipse.jst.servlet.ui.internal.wizard.AddServletWizard + persp.newWizSC:org.eclipse.jst.ejb.ui.internal.wizard.AddSessionBeanWizard + persp.newWizSC:org.eclipse.jst.ejb.ui.internal.wizard.AddMessageDrivenBeanWizard + persp.newWizSC:org.eclipse.jpt.ui.wizard.newEntity + persp.newWizSC:org.eclipse.jst.ws.creation.ui.wizard.serverwizard + persp.newWizSC:org.eclipse.ui.wizards.new.folder + persp.newWizSC:org.eclipse.ui.wizards.new.file + persp.actionSet:org.eclipse.wst.server.ui.internal.webbrowser.actionSet + persp.actionSet:org.eclipse.debug.ui.breakpointActionSet + persp.newWizSC:org.eclipse.m2e.core.wizards.Maven2ProjectWizard + persp.actionSet:org.eclipse.wst.ws.explorer.explorer + + + newtablook + + + + + + + + + + newtablook + + + + + + newtablook + + + + + + + + + + + + + + + + + + Maximized + + + + + + + View + categoryTag:Help + + + + View + categoryTag:General + activeOnClose + + ViewMenu + menuContribution:menu + + + + + View + categoryTag:Help + + + + newtablook + org.eclipse.e4.primaryDataStack + EditorStack + + + + + View + categoryTag:General + + ViewMenu + menuContribution:menu + + + + + View + categoryTag:General + + + View + categoryTag:Java + + + View + categoryTag:Java Browsing + + + + View + categoryTag:General + + ViewMenu + menuContribution:menu + + + + + View + categoryTag:General + + + View + categoryTag:Server + + + View + categoryTag:Data Management + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + + View + categoryTag:General + + ViewMenu + menuContribution:menu + + + + + View + categoryTag:Mylyn + + + + toolbarSeparator + + + + Draggable + + + + + + + + + + + + + + + toolbarSeparator + + + + Draggable + + + + + Draggable + + + + + + + + + + + + + + + + + + + Draggable + + + + + + + Draggable + + + + + + Draggable + + + + + + + Draggable + + + + + Draggable + + + + + toolbarSeparator + + + + Draggable + + + + + + + + + + + + toolbarSeparator + + + + toolbarSeparator + + + + Draggable + + + + + stretch + + + glue + + + + glue + + + Draggable + + + + + stretch + + + + Draggable + + + + + TrimStack + + + + + + + + + + + + + + + + + + + + + + + + + locale:zh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + locale:zh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + locale:zh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + locale:zh + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + platform:win32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Editor + + + View + categoryTag:Ant + + + View + categoryTag:Data Management + + + View + categoryTag:Data Management + + + View + categoryTag:Data Management + + + View + categoryTag:Debug + + + View + categoryTag:Debug + + + View + categoryTag:Debug + + + View + categoryTag:Debug + + + View + categoryTag:Debug + + + View + categoryTag:Debug + + + View + categoryTag:Debug + + + View + categoryTag:Git + + + View + categoryTag:Git + + + View + categoryTag:Git + + + View + categoryTag:Git + + + View + categoryTag:General + + + View + categoryTag:Help + + + View + categoryTag:Debug + + + View + categoryTag:Java + + + View + categoryTag:Java + + + View + categoryTag:Java + + + View + categoryTag:Java Browsing + + + View + categoryTag:Java Browsing + + + View + categoryTag:Java Browsing + + + View + categoryTag:Java Browsing + + + View + categoryTag:Java + + + View + categoryTag:General + + + View + categoryTag:Java + + + View + categoryTag:Java + + + View + categoryTag:JPA + + + View + categoryTag:JPA + + + View + categoryTag:JavaServer Faces + + + View + categoryTag:JavaServer Faces + + + View + categoryTag:Web Services + + + View + categoryTag:Maven + + + View + categoryTag:Maven + + + View + categoryTag:Mylyn + + + View + categoryTag:Mylyn + + + View + categoryTag:Mylyn + + + View + categoryTag:API Tools + + + View + categoryTag:Plug-in Development + + + View + categoryTag:Plug-in Development + + + View + categoryTag:Plug-in Development + + + View + categoryTag:Plug-in Development + + + View + categoryTag:Plug-in Development + + + View + categoryTag:Remote Systems + + + View + categoryTag:Remote Systems + + + View + categoryTag:Remote Systems + + + View + categoryTag:Remote Systems + + + View + categoryTag:Remote Systems + + + View + categoryTag:Remote Systems + + + View + categoryTag:Remote Systems + + + View + categoryTag:Remote Systems + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:CVS + + + View + categoryTag:CVS + + + View + categoryTag:Team + + + View + categoryTag:Team + + + View + categoryTag:Terminal + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:Help + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:General + + + View + categoryTag:Debug + + + View + categoryTag:JavaScript + + + View + categoryTag:JavaScript + + + View + categoryTag:JavaScript + + + View + categoryTag:JavaScript + + + View + categoryTag:JavaScript + + + View + categoryTag:Server + + + View + categoryTag:XML + + + View + categoryTag:XML + + + View + categoryTag:XML + + + View + categoryTag:XML + + + View + categoryTag:XML + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/externalLibsTimeStamps new file mode 100644 index 0000000000000000000000000000000000000000..f5666298b590a888c66b2f99be77b3cd4794bc6f GIT binary patch literal 972 zcmb7@y-or_5XZ*{FtM{Gp|ZGL4iMu~Y+Z*@J*@U@S!&<5!3_ zmOg~Of$$IJMIsTJOhuDK&f0lS*wIEs zng%??h?`SRx~`@6kdF_e&XBvzO%lf@%ohZ(P|ZFrmjTnkH8prgNlOkRp+cm8S)RE? zmY*#;lVZ~D{^ARE)3x)vp^EtAEHc-fgw8ljaCh}>*s-{M(hU;rOhpA~_@3wq?t3kl zl~}G;T;)C?4^*9F-;Spn`Vwm$(mmxN#i-Hs;2m=5Q540>=gXxPSWB-QoA5#tniwz| z!V8?F8_IYGP0^NwCQ1TFYI{MK6=o}T&xN>0_NMv`Tl1L=v=jk)A`&rW^zd;6rSufp z6l5@(-t_157&g=E|Mt~3Qgl>eV%X}>GjBU8-L-#Z>f*_H12?@3`&^RVSL^4HpF?WQ JRD1iH`2};=LB{|9 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt new file mode 100644 index 0000000..f84b816 --- /dev/null +++ b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/savedIndexNames.txt @@ -0,0 +1,29 @@ +INDEX VERSION 1.126+E:\2016Spring\robocodefiles\download\app\workspace_robo4\.metadata\.plugins\org.eclipse.jdt.core +3253539546.index +240634369.index +3357244662.index +3837392347.index +1270703585.index +743580145.index +4213330522.index +2815204631.index +972965919.index +649753860.index +2097671088.index +2394798482.index +1886545541.index +2420224983.index +9299668.index +2806151389.index +2816454019.index +2169288515.index +3228954160.index +2122446671.index +2936589608.index +1812437159.index +2690281349.index +3090911769.index +844486800.index +195189658.index +2555277089.index +4256357263.index diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat new file mode 100644 index 0000000000000000000000000000000000000000..0facbcd4b9baf082511caf207f299df748e6ab44 GIT binary patch literal 19199 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 H#FhRJzcsAQ literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/1a42e2ddbdd28c4e903ebde7bafa5867/segments.gen b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/1a42e2ddbdd28c4e903ebde7bafa5867/segments.gen new file mode 100644 index 0000000000000000000000000000000000000000..e9fa6008becd133f1cac4c5cec7f4311c6576acc GIT binary patch literal 20 QcmezW|NlP*2w;ZM07=&b0ssI2 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/26522e0d83a422eed93329ece7565cfc/segments.gen b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/26522e0d83a422eed93329ece7565cfc/segments.gen new file mode 100644 index 0000000000000000000000000000000000000000..e9fa6008becd133f1cac4c5cec7f4311c6576acc GIT binary patch literal 20 QcmezW|NlP*2w;ZM07=&b0ssI2 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen b/代码/workspace_robo4/.metadata/.plugins/org.eclipse.m2e.core/nexus/830bc118332e77292949ed1e6d2fabe0/segments.gen new file mode 100644 index 0000000000000000000000000000000000000000..e9fa6008becd133f1cac4c5cec7f4311c6576acc GIT binary patch literal 20 QcmezW|NlP*2w;ZM07=&b0ssI2 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/Module.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/Module.java new file mode 100644 index 0000000..e538d7a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/Module.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.dotnet.host; + + +import net.sf.robocode.core.*; +import net.sf.robocode.dotnet.repository.items.handlers.DotNetPropertiesHandler; +import net.sf.robocode.dotnet.repository.root.handlers.DllHandler; +import net.sf.robocode.manager.IVersionManagerBase; +import net.sf.robocode.io.Logger; +import net.sf.jni4net.Bridge; + +import java.io.File; +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public class Module extends BaseModule { + static { + // .NET proxies and their interfaces must be loaded in system class loader in order to call native methods + Init(); + } + + private static void Init() { + try { + + String libsDir; + final String version = ContainerBase.getComponent(IVersionManagerBase.class).getVersionN(); + + final java.security.CodeSource source = Module.class.getProtectionDomain().getCodeSource(); + final File file = new File(source.getLocation().toURI()).getCanonicalFile(); + + if (file.getName().equals("classes")) { + libsDir = file.getParent(); + } else if (file.getName().endsWith(".jar")) { + libsDir = file.getParent(); + } else { + throw new Error("Can't find " + file); + } + + final String nhost = libsDir + "/robocode.dotnet.nhost-" + version + ".dll"; + final String ncontrol = libsDir + "/robocode.control.dll"; + + Bridge.init(new File(libsDir)); + // Bridge.setVerbose(true); + // Bridge.setDebug(true); + Bridge.SetSystemClassLoader(Container.engineLoader); + Bridge.LoadAndRegisterAssemblyFrom(new File(ncontrol)); + Bridge.LoadAndRegisterAssemblyFrom(new File(nhost)); + + Container.cache.addComponent("DllItemHandler", DllHandler.class); + Container.cache.addComponent("CsPropertiesHandler", DotNetPropertiesHandler.class); + Container.cache.addComponent("VbPropertiesHandler", DotNetPropertiesHandler.class); + Container.cache.addComponent("DotNetPropertiesHandler", DotNetPropertiesHandler.class); + + // .NET proxies + Container.cache.addComponent("robocode.host.cs", DotNetHost.class); + Container.cache.addComponent("robocode.host.vb", DotNetHost.class); + Container.cache.addComponent("robocode.host.dotnet", DotNetHost.class); + + } catch (RuntimeException e) { + Logger.logError(e); + throw new Error("Can't initialize .NET Robocode", e); + } + } + + public void afterLoaded(List allModules) { + net.sf.robocode.dotnet.nhost.ModuleN.InitN(); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java new file mode 100644 index 0000000..852475f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java @@ -0,0 +1,382 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.installer; + + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; +import java.net.URL; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarInputStream; + + +/** + * Installer for Robocode. + * + * @author Mathew A. Nelsen (original) + * @author Flemming N. Larsen (contributor) + */ +public class AutoExtract implements ActionListener { + private JDialog licenseDialog; + private boolean accepted; + private final String[] spinner = { "-", "\\", "|", "/"}; + private String message = ""; + private static File installDir; + private static final String javaVersion = System.getProperty("java.version"); + + private boolean acceptLicense() { + String licenseText = ""; + + InputStream is; + + try { + JarFile extractJar = new JarFile("extract.jar"); + + is = extractJar.getInputStream(extractJar.getJarEntry("license/cpl-v10.html")); + } catch (IOException e) { + return true; + } + if (is == null) { + return true; + } + + BufferedReader r = new BufferedReader(new InputStreamReader(is)); + + try { + String line = r.readLine(); + + while (line != null) { + licenseText += line; + line = r.readLine(); + } + return acceptReject(licenseText); + + } catch (IOException e) { + System.err.println("Could not read line from license file: " + e); + } + return true; + } + + private boolean acceptReject(String text) { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + licenseDialog = new JDialog(); + licenseDialog.setTitle("License Agreement"); + licenseDialog.setModal(true); + licenseDialog.setLocation((screenSize.width - 500) / 2, (screenSize.height - 400) / 2); + licenseDialog.setSize(500, 400); + JTextPane t = new JTextPane(); + + t.setContentType("text/html"); + t.setText(text); + t.setFont(new Font("Dialog", Font.PLAIN, 12)); + t.setEditable(false); + + JScrollPane s = new JScrollPane(); + + s.setViewportView(t); + + licenseDialog.getContentPane().setLayout(new BorderLayout()); + licenseDialog.getContentPane().add(s, BorderLayout.CENTER); + + JPanel p = new JPanel(); + + p.setLayout(new BorderLayout()); + JButton b1 = new JButton("Accept"); + JButton b2 = new JButton("Cancel"); + + p.add(b1, BorderLayout.WEST); + p.add(b2, BorderLayout.EAST); + + b1.addActionListener(this); + b2.addActionListener(this); + + licenseDialog.getContentPane().add(p, BorderLayout.SOUTH); + + licenseDialog.setVisible(true); + + return accepted; + } + + public void actionPerformed(ActionEvent e) { + accepted = e.getActionCommand().equals("Accept"); + licenseDialog.dispose(); + licenseDialog = null; + } + + private boolean extract(File dest) { + JDialog statusDialog = new JDialog(); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + int width = 500; + int height = 100; + + statusDialog.setTitle("Installing"); + statusDialog.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2); + statusDialog.setSize(width, height); + JLabel status = new JLabel(); + + statusDialog.getContentPane().setLayout(new BorderLayout()); + statusDialog.getContentPane().add(status, BorderLayout.CENTER); + + statusDialog.setVisible(true); + + FileOutputStream fos; + String entryName; + + byte buf[] = new byte[2048]; + + final String name = AutoExtract.class.getName().replaceAll("\\.", "/") + ".class"; + String urlJar = AutoExtract.class.getClassLoader().getResource(name).toString(); + final String src = urlJar.substring("jar:file:/".length(), urlJar.indexOf("!/")); + + if (src.indexOf('!') > -1) { + final String message = src + + "\nContains an exclamation point. Please move the file to a different directory."; + + JOptionPane.showMessageDialog(null, message); + System.err.println(message); + System.exit(0); + } + JarInputStream jarIS = null; + try { + final URL url = new URL("file:/" + src); + InputStream is = url.openStream(); + jarIS = new JarInputStream(is); + + JarEntry entry = jarIS.getNextJarEntry(); + + while (entry != null) { + int spin = 0; + + entryName = entry.getName(); + if (entry.isDirectory()) { + if (!entryName.startsWith("net")) { + File dir = new File(dest, entry.getName()); + + if (!dir.exists() && !dir.mkdirs()) { + System.out.println("Can't create dir " + dir); + } + } + } else { + if (!entryName.equals(name)) { + status.setText(entryName + " " + spinner[spin++]); + + File out = new File(dest, entry.getName()); + File parentDirectory = new File(out.getParent()); + + if (!parentDirectory.exists() && !parentDirectory.mkdirs()) { + System.out.println("Can't create dir " + parentDirectory); + } + fos = new FileOutputStream(out); + + int index = 0; + int num; + int count = 0; + + while ((num = jarIS.read(buf, 0, 2048)) != -1) { + fos.write(buf, 0, num); + index += num; + count++; + if (count > 80) { + status.setText(entryName + " " + spinner[spin++] + " (" + index + " bytes)"); + if (spin > 3) { + spin = 0; + } + count = 0; + } + } + fos.close(); + + if (entryName.length() > 3 && entryName.substring(entryName.length() - 3).equals(".sh")) { + if (File.separatorChar == '/') { + Runtime.getRuntime().exec("chmod 755 " + out.toString()); + } + } + + status.setText(entryName + " " + spinner[spin] + " (" + index + " bytes)"); + } + } + entry = jarIS.getNextJarEntry(); + } + statusDialog.dispose(); + message = "Installation successful"; + return true; + } catch (IOException e) { + message = "Installation failed" + e; + return false; + } finally { + if (jarIS != null) { + try { + jarIS.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static void main(String argv[]) { + // Verify that the Java version is version 6 (1.6.0) or newer + if (javaVersion.startsWith("1.") && javaVersion.charAt(2) < '5') { + final String message = "Robocode requires Java 6 (1.6.0) or newer.\n" + + "Your system is currently running Java " + javaVersion + ".\n" + + "If you have not installed (or activated) at least\n" + "JRE 6 or JDK 6, please do so."; + + JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); + System.err.println(message); + System.exit(0); + } + + // Set native look and feel + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (RuntimeException t) {// For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF + } + + File suggestedDir; + + AutoExtract extractor = new AutoExtract(); + + if (extractor.acceptLicense()) { + if (argv.length == 1) { + suggestedDir = new File(argv[0]); + } else if (File.separatorChar == '\\') { + suggestedDir = new File("c:\\robocode\\"); + } else { + suggestedDir = new File(System.getProperty("user.home") + File.separator + "robocode" + File.separator); + } + + boolean done = false; + + while (!done) { + int rc = JOptionPane.showConfirmDialog(null, + "Robocode plugin will be installed in:\n" + suggestedDir + "\nIs this ok?", "Installing Robocode", + JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + + if (rc == JOptionPane.YES_OPTION) { + installDir = suggestedDir; + done = true; + } else if (rc == JOptionPane.NO_OPTION) { + Object r = JOptionPane.showInputDialog(null, "Please type in the installation directory", + "Installation Directory", JOptionPane.PLAIN_MESSAGE, null, null, suggestedDir); + + if (r == null) { + JOptionPane.showMessageDialog(null, "Installation cancelled."); + System.exit(0); + } else { + suggestedDir = new File(((String) r).trim()); + } + } else if (rc == JOptionPane.CANCEL_OPTION) { + JOptionPane.showMessageDialog(null, "Installation cancelled."); + System.exit(0); + } + } + if (!installDir.exists()) { + int rc = JOptionPane.showConfirmDialog(null, + installDir.getPath() + "\ndoes not exist. Would you like to create it?", "Installing Robocode", + JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + + if (rc == JOptionPane.YES_OPTION) { + if (!installDir.exists() && !installDir.mkdirs()) { + System.out.println("Can't create dir " + installDir); + } + } else { + JOptionPane.showMessageDialog(null, "Installation cancelled."); + System.exit(0); + } + } + boolean rv = extractor.extract(installDir); + + if (!rv) { + JOptionPane.showMessageDialog(null, extractor.message); + } + } else { + JOptionPane.showMessageDialog(null, "Installation cancelled."); + } + + // Delete the class file with the installer and it's parent folders in the robocode home dir + if (installDir != null) { + String installerPath = AutoExtract.class.getName().replaceAll("\\.", "/") + "$1.class"; + + deleteFileAndParentDirsIfEmpty(new File(installDir, installerPath)); + } + + System.exit(0); + } + + private static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + for (File file : dir.listFiles()) { + if (file.isDirectory()) { + // Skip directories ending with ".data" + if (file.getName().endsWith(".data")) { + continue; + } + try { + // Test for symlink and ignore. + // Robocode won't create one, but just in case a user does... + if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) { + deleteDir(file); + if (file.exists() && !file.delete()) { + System.err.println("Can't delete: " + file); + } + } else { + System.out.println("Warning: " + file + " may be a symlink. It has been ignored"); + } + } catch (IOException e) { + System.out.println( + "Warning: Cannot determine canonical file for " + file + ". It has been ignored"); + } + } else { + if (file.exists() && !file.delete()) { + System.err.println("Can't delete: " + file); + } + } + } + return dir.delete(); + } + return false; + } + + /** + * Deletes a file and afterwards deletes the parent directories that are empty. + * + * @param file the file or directory to delete + * @return true if success + */ + private static boolean deleteFileAndParentDirsIfEmpty(final File file) { + boolean wasDeleted = false; + + if (file != null && file.exists()) { + if (file.isDirectory()) { + wasDeleted = deleteDir(file); + } else { + wasDeleted = file.delete(); + + File parent = file; + + while (wasDeleted && (parent = parent.getParentFile()) != null) { + // Delete parent directory, but only if it is empty + File[] files = parent.listFiles(); + + if (files != null && files.length == 0) { + wasDeleted = deleteDir(parent); + } else { + wasDeleted = false; + } + } + } + } + return wasDeleted; + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java new file mode 100644 index 0000000..5507bb1 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxTurnRate.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestMaxTurnRate extends RobocodeTestBed { + + StringBuffer buf = new StringBuffer(); + + @Override + public String getRobotNames() { + return "tested.robotscs.MaxTurnRate,SampleCs.Target"; + } + + @Override + public String getInitialPositions() { + return "(50,50,0), (150,50,0)"; // Make sure the robots do not collide! + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + buf.append(event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot()); + + if (event.getTurnSnapshot().getTurn() == 26) { + final String out = buf.toString(); + + Assert.assertTrue(out.contains("1: 0.0, 0.0") || out.contains("1: 0.0, -0.0")); + Assert.assertTrue(out.contains("2: 0.0, -1.0") || out.contains("2: 0.0, -0.999999999")); + Assert.assertTrue(out.contains("3: 0.0, -2.0") || out.contains("3: 0.0, -1.999999999")); + Assert.assertTrue(out.contains("4: 0.0, -3.0") || out.contains("4: 0.0, -2.999999999")); + Assert.assertTrue(out.contains("5: 0.0, -4.0") || out.contains("5: 0.0, -3.999999999")); + Assert.assertTrue(out.contains("6: 0.0, -5.0") || out.contains("6: 0.0, -4.999999999")); + Assert.assertTrue(out.contains("7: 0.0, -6.0") || out.contains("7: 0.0, -5.999999999")); + Assert.assertTrue(out.contains("8: 0.0, -7.0") || out.contains("8: 0.0, -6.999999999")); + Assert.assertTrue(out.contains("9: 0.0, -8.0") || out.contains("9: 0.0, -7.999999999")); + Assert.assertTrue(out.contains("10: 0.0, -9.0") || out.contains("10: 0.0, -8.999999999")); + Assert.assertTrue(out.contains("11: 0.0, -10.0") || out.contains("11: 0.0, -9.999999999")); + Assert.assertTrue(out.contains("12: 0.0, -10.0") || out.contains("12: 0.0, -9.999999999")); + Assert.assertTrue(out.contains("13: 0.0, -10.0") || out.contains("13: 0.0, -9.999999999")); + + Assert.assertTrue(out.contains("14: 0.0, 0.0") || out.contains("14: 0.0, -0.0")); + Assert.assertTrue(out.contains("15: 0.0, 1.0") || out.contains("15: 0.0, 0.999999999")); + Assert.assertTrue(out.contains("16: 0.0, 2.0") || out.contains("16: 0.0, 1.999999999")); + Assert.assertTrue(out.contains("17: 0.0, 3.0") || out.contains("17: 0.0, 2.999999999")); + Assert.assertTrue(out.contains("18: 0.0, 4.0") || out.contains("18: 0.0, 3.999999999")); + Assert.assertTrue(out.contains("19: 0.0, 5.0") || out.contains("19: 0.0, 4.999999999")); + Assert.assertTrue(out.contains("20: 0.0, 6.0") || out.contains("20: 0.0, 5.999999999")); + Assert.assertTrue(out.contains("21: 0.0, 7.0") || out.contains("21: 0.0, 6.999999999")); + Assert.assertTrue(out.contains("22: 0.0, 8.0") || out.contains("22: 0.0, 7.999999999")); + Assert.assertTrue(out.contains("23: 0.0, 9.0") || out.contains("23: 0.0, 8.999999999")); + Assert.assertTrue(out.contains("24: 0.0, 10.0") || out.contains("24: 0.0, 9.999999999")); + Assert.assertTrue(out.contains("25: 0.0, 10.0") || out.contains("25: 0.0, 9.999999999")); + Assert.assertTrue(out.contains("26: 0.0, 10.0") || out.contains("26: 0.0, 9.999999999")); + } + } +} diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java new file mode 100644 index 0000000..e993cf8 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java @@ -0,0 +1,389 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.installer; + + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; +import java.net.URL; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarInputStream; + + +/** + * Installer for Robocode. + * + * @author Mathew A. Nelsen (original) + * @author Flemming N. Larsen (contributor) + */ +public class AutoExtract implements ActionListener { + private JDialog licenseDialog; + private boolean accepted; + private final String[] spinner = { "-", "\\", "|", "/"}; + private String message = ""; + private static final String javaVersion = System.getProperty("java.version"); + + /** + * AutoExtract constructor. + */ + public AutoExtract() { + super(); + } + + private boolean acceptLicense() { + String licenseText = ""; + + InputStream is; + + try { + JarFile extractJar = new JarFile("extract.jar"); + + is = extractJar.getInputStream(extractJar.getJarEntry("license/cpl-v10.html")); + } catch (IOException e) { + return true; + } + if (is == null) { + return true; + } + + BufferedReader r = new BufferedReader(new InputStreamReader(is)); + + try { + String line = r.readLine(); + + while (line != null) { + licenseText += line; + line = r.readLine(); + } + return acceptReject(licenseText); + + } catch (IOException e) { + System.err.println("Could not read line from license file: " + e); + } + return true; + } + + private boolean acceptReject(String text) { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + licenseDialog = new JDialog(); + licenseDialog.setTitle("License Agreement"); + licenseDialog.setModal(true); + licenseDialog.setLocation((screenSize.width - 500) / 2, (screenSize.height - 400) / 2); + licenseDialog.setSize(500, 400); + JTextPane t = new JTextPane(); + + t.setContentType("text/html"); + t.setText(text); + t.setFont(new Font("Dialog", Font.PLAIN, 12)); + t.setEditable(false); + + JScrollPane s = new JScrollPane(); + + s.setViewportView(t); + + licenseDialog.getContentPane().setLayout(new BorderLayout()); + licenseDialog.getContentPane().add(s, BorderLayout.CENTER); + + JPanel p = new JPanel(); + + p.setLayout(new BorderLayout()); + JButton b1 = new JButton("Accept"); + JButton b2 = new JButton("Cancel"); + + p.add(b1, BorderLayout.WEST); + p.add(b2, BorderLayout.EAST); + + b1.addActionListener(this); + b2.addActionListener(this); + + licenseDialog.getContentPane().add(p, BorderLayout.SOUTH); + + licenseDialog.setVisible(true); + + return accepted; + } + + public void actionPerformed(ActionEvent e) { + accepted = e.getActionCommand().equals("Accept"); + licenseDialog.dispose(); + licenseDialog = null; + } + + private boolean extract(File dest) { + JDialog statusDialog = new JDialog(); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + int width = 500; + int height = 100; + + statusDialog.setTitle("Installing"); + statusDialog.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2); + statusDialog.setSize(width, height); + JLabel status = new JLabel(); + + statusDialog.getContentPane().setLayout(new BorderLayout()); + statusDialog.getContentPane().add(status, BorderLayout.CENTER); + + statusDialog.setVisible(true); + + FileOutputStream fos; + String entryName; + + byte buf[] = new byte[2048]; + + final String name = AutoExtract.class.getName().replaceAll("\\.", "/") + ".class"; + String urlJar = AutoExtract.class.getClassLoader().getResource(name).toString(); + final String src = urlJar.substring("jar:file:/".length(), urlJar.indexOf("!/")); + + if (src.indexOf('!') > -1) { + final String message = src + + "\nContains an exclamation point. Please move the file to a different directory."; + + JOptionPane.showMessageDialog(null, message); + System.err.println(message); + System.exit(0); + } + JarInputStream jarIS = null; + try { + final URL url = new URL("file:/" + src); + InputStream is = url.openStream(); + jarIS = new JarInputStream(is); + + JarEntry entry = jarIS.getNextJarEntry(); + + while (entry != null) { + int spin = 0; + + entryName = entry.getName(); + if (entry.isDirectory()) { + if (!entryName.startsWith("net")) { + File dir = new File(dest, entry.getName()); + + if (!dir.exists() && !dir.mkdirs()) { + System.out.println("Can't create dir " + dir); + } + } + } else { + if (!entryName.equals(name)) { + status.setText(entryName + " " + spinner[spin++]); + + File out = new File(dest, entry.getName()); + File parentDirectory = new File(out.getParent()); + + if (!parentDirectory.exists() && !parentDirectory.mkdirs()) { + System.out.println("Can't create dir " + parentDirectory); + } + fos = new FileOutputStream(out); + + int index = 0; + int num; + int count = 0; + + while ((num = jarIS.read(buf, 0, 2048)) != -1) { + fos.write(buf, 0, num); + index += num; + count++; + if (count > 80) { + status.setText(entryName + " " + spinner[spin++] + " (" + index + " bytes)"); + if (spin > 3) { + spin = 0; + } + count = 0; + } + } + fos.close(); + + if (entryName.length() > 3 && entryName.substring(entryName.length() - 3).equals(".sh")) { + if (File.separatorChar == '/') { + Runtime.getRuntime().exec("chmod 755 " + out.toString()); + } + } + + status.setText(entryName + " " + spinner[spin] + " (" + index + " bytes)"); + } + } + entry = jarIS.getNextJarEntry(); + } + statusDialog.dispose(); + message = "Installation successful"; + return true; + } catch (IOException e) { + message = "Installation failed" + e; + return false; + } finally { + if (jarIS != null) { + try { + jarIS.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static void main(String argv[]) { + // Verify that the Java version is version 6 (1.6.0) or newer + if (javaVersion.startsWith("1.") && javaVersion.charAt(2) < '5') { + final String message = "Robocode requires Java 6 (1.6.0) or newer.\n" + + "Your system is currently running Java " + javaVersion + ".\n" + + "If you have not installed (or activated) at least\n" + "JRE 6 or JDK 6, please do so."; + + JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); + System.err.println(message); + System.exit(0); + } + + // Set native look and feel + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (RuntimeException t) {// For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF + } + + File installDir = null; + File suggestedDir; + + AutoExtract extractor = new AutoExtract(); + + if (extractor.acceptLicense()) { + if (argv.length == 1) { + suggestedDir = new File(argv[0]); + } else if (File.separatorChar == '\\') { + suggestedDir = new File("c:\\robocode\\"); + } else { + suggestedDir = new File(System.getProperty("user.home") + File.separator + "robocode" + File.separator); + } + + boolean done = false; + + while (!done) { + int rc = JOptionPane.showConfirmDialog(null, + "Robocode plugin will be installed in:\n" + suggestedDir + "\nIs this ok?", "Installing Robocode", + JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + + if (rc == JOptionPane.YES_OPTION) { + installDir = suggestedDir; + done = true; + } else if (rc == JOptionPane.NO_OPTION) { + Object r = JOptionPane.showInputDialog(null, "Please type in the installation directory", + "Installation Directory", JOptionPane.PLAIN_MESSAGE, null, null, suggestedDir); + + if (r == null) { + JOptionPane.showMessageDialog(null, "Installation cancelled."); + System.exit(0); + } else { + suggestedDir = new File(((String) r).trim()); + } + } else if (rc == JOptionPane.CANCEL_OPTION) { + JOptionPane.showMessageDialog(null, "Installation cancelled."); + System.exit(0); + } + } + if (!installDir.exists()) { + int rc = JOptionPane.showConfirmDialog(null, + installDir.getPath() + "\ndoes not exist. Would you like to create it?", "Installing Robocode", + JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + + if (rc == JOptionPane.YES_OPTION) { + if (!installDir.exists() && !installDir.mkdirs()) { + System.out.println("Can't create dir " + installDir); + } + } else { + JOptionPane.showMessageDialog(null, "Installation cancelled."); + System.exit(0); + } + } + boolean rv = extractor.extract(installDir); + + if (!rv) { + JOptionPane.showMessageDialog(null, extractor.message); + } + } else { + JOptionPane.showMessageDialog(null, "Installation cancelled."); + } + + // Delete the class file with the installer and it's parent folders in the robocode home dir + if (installDir != null) { + String installerPath = AutoExtract.class.getName().replaceAll("\\.", "/") + "$1.class"; + + deleteFileAndParentDirsIfEmpty(new File(installDir, installerPath)); + } + + System.exit(0); + } + + private static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + for (File file : dir.listFiles()) { + if (file.isDirectory()) { + // Skip directories ending with ".data" + if (file.getName().endsWith(".data")) { + continue; + } + try { + // Test for symlink and ignore. + // Robocode won't create one, but just in case a user does... + if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) { + deleteDir(file); + if (file.exists() && !file.delete()) { + System.err.println("Can't delete: " + file); + } + } else { + System.out.println("Warning: " + file + " may be a symlink. It has been ignored"); + } + } catch (IOException e) { + System.out.println( + "Warning: Cannot determine canonical file for " + file + ". It has been ignored"); + } + } else { + if (file.exists() && !file.delete()) { + System.err.println("Can't delete: " + file); + } + } + } + return dir.delete(); + } + return false; + } + + /** + * Deletes a file and afterwards deletes the parent directories that are empty. + * + * @param file the file or directory to delete + * @return true if success + */ + private static boolean deleteFileAndParentDirsIfEmpty(final File file) { + boolean wasDeleted = false; + + if (file != null && file.exists()) { + if (file.isDirectory()) { + wasDeleted = deleteDir(file); + } else { + wasDeleted = file.delete(); + + File parent = file; + + while (wasDeleted && (parent = parent.getParentFile()) != null) { + // Delete parent directory, but only if it is empty + File[] files = parent.listFiles(); + + if (files != null && files.length == 0) { + wasDeleted = deleteDir(parent); + } else { + wasDeleted = false; + } + } + } + } + return wasDeleted; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/HiddenAccess.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/HiddenAccess.java new file mode 100644 index 0000000..184001c --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/HiddenAccess.java @@ -0,0 +1,290 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.security; + + +import net.sf.robocode.core.ContainerBase; +import net.sf.robocode.io.Logger; +import net.sf.robocode.peer.IRobotStatics; +import robocode.BattleRules; +import robocode.Bullet; +import robocode.Event; +import robocode.RobotStatus; +import robocode.control.RobotSpecification; +import robocode.control.events.IBattleListener; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.io.File; +import java.io.FilenameFilter; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLDecoder; +import java.util.ArrayList; + + +/** + * Helpers for accessing hidden methods on events. + * + * @author Pavel Savara (original) + */ +public class HiddenAccess { + private static IHiddenEventHelper eventHelper; + private static IHiddenBulletHelper bulletHelper; + private static IHiddenSpecificationHelper specificationHelper; + private static IHiddenStatusHelper statusHelper; + private static IHiddenRulesHelper rulesHelper; + private static Method initContainer; + private static Method initContainerRe; + private static Method cleanup; + private static Method robocodeMain; + private static boolean initialized; + private static boolean foundCore = false; + + public static void init() { + if (initialized) { + return; + } + Method method; + + try { + method = Event.class.getDeclaredMethod("createHiddenHelper"); + method.setAccessible(true); + eventHelper = (IHiddenEventHelper) method.invoke(null); + method.setAccessible(false); + + method = Bullet.class.getDeclaredMethod("createHiddenHelper"); + method.setAccessible(true); + bulletHelper = (IHiddenBulletHelper) method.invoke(null); + method.setAccessible(false); + + method = RobotSpecification.class.getDeclaredMethod("createHiddenHelper"); + method.setAccessible(true); + specificationHelper = (IHiddenSpecificationHelper) method.invoke(null); + method.setAccessible(false); + + method = RobotStatus.class.getDeclaredMethod("createHiddenSerializer"); + method.setAccessible(true); + statusHelper = (IHiddenStatusHelper) method.invoke(null); + method.setAccessible(false); + + method = BattleRules.class.getDeclaredMethod("createHiddenHelper"); + method.setAccessible(true); + rulesHelper = (IHiddenRulesHelper) method.invoke(null); + method.setAccessible(false); + + ClassLoader loader = getClassLoader(); + Class main = loader.loadClass("net.sf.robocode.core.RobocodeMainBase"); + + initContainer = main.getDeclaredMethod("initContainer"); + initContainer.setAccessible(true); + + initContainerRe = main.getDeclaredMethod("initContainerForRobocodeEngine", File.class, IBattleListener.class); + initContainerRe.setAccessible(true); + + cleanup = main.getDeclaredMethod("cleanupForRobocodeEngine"); + cleanup.setAccessible(true); + + robocodeMain = main.getDeclaredMethod("robocodeMain", Object.class); + robocodeMain.setAccessible(true); + + initialized = true; + } catch (NoSuchMethodException e) { + Logger.logError(e); + } catch (InvocationTargetException e) { + Logger.logError(e); + } catch (IllegalAccessException e) { + Logger.logError(e); + } catch (ClassNotFoundException e) { + Logger.logError(e); + if (!foundCore) { + Logger.logError("Can't find robocode.core-1.x.jar module near to robocode.jar"); + Logger.logError("Class path: " + System.getProperty("robocode.class.path", null)); + } + System.exit(-1); + } catch (MalformedURLException e) { + Logger.logError(e); + } catch (MyException e) { + Logger.logError(e); + throw e; + } + + } + + private static ClassLoader getClassLoader() throws MalformedURLException { + // if other modules are .jar next to robocode.jar on same path, we will create classloader which will load them + // otherwise we rely on that they are already on classpath + StringBuilder classPath = new StringBuilder(System.getProperty("java.class.path", null)); + ClassLoader loader = ClassLoader.getSystemClassLoader(); + String path = HiddenAccess.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + + try { + path = URLDecoder.decode(path, "UCS2"); + } catch (UnsupportedEncodingException e) { + path = new File(".", "libs/robocode.jar").toString(); + } + final int i = path.lastIndexOf("robocode.jar"); + + if (i > 0) { + loader = createClassLoader(classPath, loader, path.substring(0, i)); + } + System.setProperty("robocode.class.path", classPath.toString()); + return loader; + } + + private static ClassLoader createClassLoader(StringBuilder classPath, ClassLoader loader, String dir) throws MalformedURLException { + + File dirf = new File(dir); + ArrayList urls = new ArrayList(); + + final File[] files = dirf.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + final String test = name.toLowerCase(); + + return test.endsWith(".jar") && !test.endsWith("robocode.jar"); + } + }); + + if (files != null) { + for (File file : files) { + final String name = file.toString().toLowerCase(); + + if (name.contains("robocode.core")) { + foundCore = true; + urls.add(file.toURI().toURL()); + } + if (name.contains("picocontainer")) { + urls.add(file.toURI().toURL()); + } + if (name.contains("codesize")) { + urls.add(file.toURI().toURL()); + } + classPath.append(File.pathSeparator); + classPath.append(file.toString()); + } + } + return new URLClassLoader(urls.toArray(new URL[urls.size()]), loader); + } + + public static boolean isCriticalEvent(Event e) { + return eventHelper.isCriticalEvent(e); + } + + public static void setEventTime(Event e, long newTime) { + eventHelper.setTime(e, newTime); + } + + public static void setEventPriority(Event e, int newPriority) { + eventHelper.setPriority(e, newPriority); + } + + public static void dispatch(Event event, IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + eventHelper.dispatch(event, robot, statics, graphics); + } + + public static void setDefaultPriority(Event e) { + eventHelper.setDefaultPriority(e); + } + + public static byte getSerializationType(Event e) { + return eventHelper.getSerializationType(e); + } + + public static void update(Bullet bullet, double x, double y, String victimName, boolean isActive) { + bulletHelper.update(bullet, x, y, victimName, isActive); + } + + public static RobotSpecification createSpecification(Object fileSpecification, String name, String author, String webpage, String version, String robocodeVersion, String jarFile, String fullClassName, String description) { + return specificationHelper.createSpecification(fileSpecification, name, author, webpage, version, + robocodeVersion, jarFile, fullClassName, description); + } + + public static Object getFileSpecification(RobotSpecification specification) { + return specificationHelper.getFileSpecification(specification); + } + + public static String getRobotTeamName(RobotSpecification specification) { + return specificationHelper.getTeamName(specification); + } + + public static void setTeamId(RobotSpecification specification, String teamName) { + specificationHelper.setTeamName(specification, teamName); + } + + public static RobotStatus createStatus(double energy, double x, double y, double bodyHeading, double gunHeading, double radarHeading, double velocity, + double bodyTurnRemaining, double radarTurnRemaining, double gunTurnRemaining, double distanceRemaining, double gunHeat, int others, + int numSentries, int roundNum, int numRounds, long time) { + return statusHelper.createStatus(energy, x, y, bodyHeading, gunHeading, radarHeading, velocity, + bodyTurnRemaining, radarTurnRemaining, gunTurnRemaining, distanceRemaining, gunHeat, others, numSentries, + roundNum, numRounds, time); + } + + public static BattleRules createRules(int battlefieldWidth, int battlefieldHeight, int numRounds, double gunCoolingRate, long inactivityTime, boolean hideEnemyNames, int sentryBorderSize) { + return rulesHelper.createRules(battlefieldWidth, battlefieldHeight, numRounds, gunCoolingRate, inactivityTime, + hideEnemyNames, sentryBorderSize); + } + + public static boolean isSafeThread() { + final IThreadManagerBase threadManager = ContainerBase.getComponent(IThreadManagerBase.class); + + return threadManager != null && threadManager.isSafeThread(); + } + + public static void initContainerForRobotEngine(File robocodeHome, IBattleListener listener) { + init(); + try { + initContainerRe.invoke(null, robocodeHome, listener); + } catch (IllegalAccessException e) { + Logger.logError(e); + } catch (InvocationTargetException e) { + Logger.logError(e.getCause()); + Logger.logError(e); + } + } + + public static void initContainer() { + init(); + try { + initContainer.invoke(null); + } catch (IllegalAccessException e) { + Logger.logError(e); + } catch (InvocationTargetException e) { + Logger.logError(e.getCause()); + Logger.logError(e); + } + } + + public static void cleanup() { + init(); + try { + cleanup.invoke(null); + } catch (IllegalAccessException e) { + Logger.logError(e); + } catch (InvocationTargetException e) { + Logger.logError(e.getCause()); + Logger.logError(e); + } + } + + public static void robocodeMain(final String[] args) { + init(); + try { + robocodeMain.invoke(null, (Object) args); + } catch (IllegalAccessException e) { + Logger.logError(e); + } catch (InvocationTargetException e) { + Logger.logError(e.getCause()); + Logger.logError(e); + } + } + +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/events/BattleEventDispatcher.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/events/BattleEventDispatcher.java new file mode 100644 index 0000000..9155e67 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/events/BattleEventDispatcher.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.events; + + +import static net.sf.robocode.io.Logger.logError; + +import net.sf.robocode.io.Logger; +import robocode.control.events.*; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + + +/** + * @author Flemming N. Larsen (original) + * @author Pavel Savara (original) + * + * @since 1.6.1 + */ +public class BattleEventDispatcher implements IBattleListener { + // This list is guaranteed to be thread-safe, which is necessary as it will be accessed + // by both the battle thread and battle manager thread. If this list is not thread-safe + // then ConcurentModificationExceptions will occur from time to time. + private final List listeners = new CopyOnWriteArrayList(); + + public BattleEventDispatcher() {} + + public void addListener(IBattleListener listener) { + assert (listener != null); + + listeners.add(listener); + } + + public void removeListener(IBattleListener listener) { + assert (listener != null); + listeners.remove(listener); + } + + public void onBattleStarted(BattleStartedEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onBattleStarted(event); + } catch (RuntimeException ex) { + logError("onBattleStarted " + listener.getClass(), ex); + } + } + } + + public void onBattleCompleted(BattleCompletedEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onBattleCompleted(event); + } catch (RuntimeException ex) { + logError("onBattleCompleted " + listener.getClass(), ex); + } + } + } + + public void onBattleFinished(BattleFinishedEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onBattleFinished(event); + } catch (RuntimeException ex) { + logError("onBattleFinished " + listener.getClass(), ex); + } + } + } + + public void onBattlePaused(BattlePausedEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onBattlePaused(event); + } catch (RuntimeException ex) { + logError("onBattlePaused " + listener.getClass(), ex); + } + } + } + + public void onBattleResumed(BattleResumedEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onBattleResumed(event); + } catch (RuntimeException ex) { + logError("onBattleResumed " + listener.getClass(), ex); + } + } + } + + public void onRoundStarted(RoundStartedEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onRoundStarted(event); + } catch (RuntimeException ex) { + logError("onRoundStarted " + listener.getClass(), ex); + } + } + } + + public void onRoundEnded(RoundEndedEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onRoundEnded(event); + } catch (RuntimeException ex) { + logError("onRoundEnded " + listener.getClass(), ex); + } + } + } + + public void onTurnStarted(TurnStartedEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onTurnStarted(event); + } catch (RuntimeException ex) { + logError("onTurnStarted " + listener.getClass(), ex); + } + } + } + + public void onTurnEnded(TurnEndedEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onTurnEnded(event); + } catch (RuntimeException ex) { + logError("onTurnEnded " + listener.getClass(), ex); + } + } + } + + public void onBattleMessage(BattleMessageEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onBattleMessage(event); + } catch (RuntimeException ex) { + logError("onBattleMessage " + listener.getClass(), ex); + } + } + } + + public void onBattleError(BattleErrorEvent event) { + for (IBattleListener listener : listeners) { + try { + listener.onBattleError(event); + } catch (RuntimeException ex) { + Logger.realErr.println(listener.getClass() + " " + ex.getMessage()); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMain.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMain.java new file mode 100644 index 0000000..3ba5a93 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMain.java @@ -0,0 +1,414 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.core; + + +import net.sf.robocode.battle.BattleResultsTableModel; +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.host.ICpuManager; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import net.sf.robocode.recording.BattleRecordFormat; +import net.sf.robocode.recording.IRecordManager; +import net.sf.robocode.repository.IRepositoryManager; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.sound.ISoundManager; +import net.sf.robocode.ui.IWindowManager; +import net.sf.robocode.util.StringUtil; +import net.sf.robocode.version.IVersionManager; +import robocode.control.events.*; + +import java.awt.Toolkit; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; + + +/** + * Robocode - A programming game involving battling AI tanks.
+ * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * + * @see
robocode.sourceforge.net + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Pavel Savara (contributor) + */ +public final class RobocodeMain extends RobocodeMainBase { + + private final Setup setup; + private final BattleObserver battleObserver = new BattleObserver(); + final private ISettingsManager properties; + final private IHostManager hostManager; + final private IWindowManager windowManager; + final private ISoundManager soundManager; + final private IBattleManager battleManager; + final private IRecordManager recordManager; + final private IVersionManager versionManager; + + private static class Setup { + boolean minimize; + boolean exitOnComplete; + String battleFilename; + String recordFilename; + String recordXmlFilename; + String replayFilename; + String resultsFilename; + int tps; + } + + public RobocodeMain(ISettingsManager properties, + IHostManager hostManager, + IWindowManager windowManager, + ISoundManager soundManager, + IBattleManager battleManager, + IRecordManager recordManager, + IVersionManager versionManager + ) { + setup = new Setup(); + this.properties = properties; + this.hostManager = hostManager; + this.windowManager = windowManager; + this.soundManager = soundManager; + this.battleManager = battleManager; + this.recordManager = recordManager; + this.versionManager = versionManager; + } + + public RobocodeMain(ISettingsManager properties, + IHostManager hostManager, + IWindowManager windowManager, + IBattleManager battleManager, + IRecordManager recordManager, + IVersionManager versionManager + ) { + this(properties, hostManager, windowManager, null, battleManager, recordManager, versionManager); + } + + public RobocodeMain(ISettingsManager properties, + IHostManager hostManager, + IBattleManager battleManager, + IRecordManager recordManager, + IVersionManager versionManager + ) { + this(properties, hostManager, null, battleManager, recordManager, versionManager); + } + + public void run() { + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(Thread thread, Throwable t) { + t.printStackTrace(); + } + }); + + try { + hostManager.initSecurity(); + + // Set the Look and Feel (LAF) + if (windowManager != null && windowManager.isGUIEnabled()) { + windowManager.init(); + } + properties.setOptionsBattleDesiredTPS(setup.tps); + + battleManager.addListener(battleObserver); + + if (windowManager != null && windowManager.isGUIEnabled()) { + if (!setup.minimize && setup.battleFilename == null && soundManager != null) { + soundManager.playThemeMusic(); + windowManager.showSplashScreen(); + } + windowManager.showRobocodeFrame(true, setup.minimize); + + // Play the intro battle if a battle file is not specified and this is the first time Robocode is being run + + if (setup.battleFilename == null && versionManager.isLastRunVersionChanged()) { + properties.saveProperties(); + windowManager.runIntroBattle(); + } + } + + final boolean enableCLIRecording = (setup.recordFilename != null || setup.recordXmlFilename != null); + + // Note: At this point the GUI should be opened (if enabled) before starting the battle from a battle file + if (setup.battleFilename != null) { + if (setup.replayFilename != null) { + System.err.println("You cannot run both a battle and replay a battle record in the same time."); + System.exit(8); + } + + setup.exitOnComplete = true; + + battleManager.setBattleFilename(setup.battleFilename); + if (new File(battleManager.getBattleFilename()).exists()) { + battleManager.startNewBattle(battleManager.loadBattleProperties(), false, enableCLIRecording); + } else { + System.err.println("The specified battle file '" + setup.battleFilename + "' was not found"); + System.exit(8); + } + } else if (setup.replayFilename != null) { + setup.exitOnComplete = true; + if (setup.replayFilename.toLowerCase().endsWith("xml.zip")) { + recordManager.loadRecord(setup.replayFilename, BattleRecordFormat.XML_ZIP); + } else { + recordManager.loadRecord(setup.replayFilename, BattleRecordFormat.BINARY_ZIP); + } + + if (new File(setup.replayFilename).exists()) { + battleManager.replay(); + } else { + System.err.println("The specified battle record file '" + setup.replayFilename + "' was not found"); + System.exit(8); + } + } + } catch (RuntimeException e) { + Logger.logError(e); + } + } + + public void loadSetup(String[] args) { + + final String nosecMessage = "Robocode is running without a security manager.\n" + + "Robots have full access to your system.\n" + "You should only run robots which you trust!"; + final String exMessage = "Robocode is running in experimental mode.\n" + + "Robots have access to their IRobotPeer interfaces.\n" + "You should only run robots which you trust!"; + + if (RobocodeProperties.isSecurityOff()) { + Logger.logWarning(nosecMessage); + } + if (System.getProperty("EXPERIMENTAL", "false").equals("true")) { + Logger.logWarning(exMessage); + } + + setup.tps = properties.getOptionsBattleDesiredTPS(); + + // Disable canonical file path cache under Windows as it causes trouble when returning + // paths with differently-capitalized file names. + if (System.getProperty("os.name").toLowerCase().startsWith("windows ")) { + System.setProperty("sun.io.useCanonCaches", "false"); + } + + // Initialize the system property so the AWT does not use headless mode meaning that the + // GUI (Awt and Swing) is enabled per default when running starting Robocode. + // It might be set to true later, if the -nodisplay option is set (in the setEnableGUI method). + // Read more about headless mode here: + // http://java.sun.com/developer/technicalArticles/J2SE/Desktop/headless/ + System.setProperty("java.awt.headless", "false"); + + for (int i = 0; i < args.length; i++) { + String currentArg = args[i]; + if (currentArg.equalsIgnoreCase("-cwd") && (i < args.length + 1)) { + changeDirectory(args[i + 1]); + i++; + } else if (currentArg.equalsIgnoreCase("-battle") && (i < args.length + 1)) { + setup.battleFilename = args[i + 1]; + i++; + } else if (currentArg.equalsIgnoreCase("-record") && (i < args.length + 1)) { + setup.recordFilename = args[i + 1]; + i++; + } else if (currentArg.equalsIgnoreCase("-recordXML") && (i < args.length + 1)) { + setup.recordXmlFilename = args[i + 1]; + i++; + } else if (currentArg.equalsIgnoreCase("-replay") && (i < args.length + 1)) { + setup.replayFilename = args[i + 1]; + i++; + } else if (currentArg.equalsIgnoreCase("-results") && (i < args.length + 1)) { + setup.resultsFilename = args[i + 1]; + i++; + } else if (currentArg.equalsIgnoreCase("-tps") && (i < args.length + 1)) { + setup.tps = Integer.parseInt(args[i + 1]); + if (setup.tps < 1) { + Logger.logError("tps must be > 0"); + System.exit(8); + } + i++; + } else if (currentArg.equalsIgnoreCase("-minimize")) { + setup.minimize = true; + } else if (currentArg.equalsIgnoreCase("-nodisplay")) { + if (windowManager != null) { + windowManager.setEnableGUI(false); + } + if (soundManager != null) { + soundManager.setEnableSound(false); + } + setup.tps = 10000; // set TPS to maximum + } else if (currentArg.equalsIgnoreCase("-nosound")) { + if (soundManager != null) { + soundManager.setEnableSound(false); + } + } else if (currentArg.equals("-?") || currentArg.equalsIgnoreCase("-help")) { + printUsage(); + System.exit(0); + } else { + Logger.logError("Not understood: " + currentArg); + printUsage(); + System.exit(8); + } + } + File robotsDir = FileUtil.getRobotsDir(); + + if (robotsDir == null) { + System.err.println("No valid robot directory is specified"); + System.exit(8); + } else if (!(robotsDir.exists() && robotsDir.isDirectory())) { + System.err.println('\'' + robotsDir.getAbsolutePath() + "' is not a valid robot directory"); + System.exit(8); + } + + // The Default Toolkit must be set as soon as we know if we are going to use headless mode or not. + // That is if the toolkit must be headless or not (GUI on/off). If we are running in headless mode + // from this point, a HeadlessException will be thrown if we access a AWT/Swing component. + // Read more about headless mode here: + // http://java.sun.com/developer/technicalArticles/J2SE/Desktop/headless/ + Toolkit.getDefaultToolkit(); + } + + private void changeDirectory(String robocodeDir) { + try { + FileUtil.setCwd(new File(robocodeDir)); + } catch (IOException e) { + System.err.println(robocodeDir + " is not a valid directory to start Robocode in."); + System.exit(8); + } + } + + private void printUsage() { + System.out.print( + "Usage: robocode [-?] [-help] [-cwd path] [-battle filename [-results filename]\n" + + " [-record filename] [-recordXML filename] [-replay filename]\n" + + " [-tps tps] [-minimize] [-nodisplay] [-nosound]\n\n" + "where options include:\n" + + " -? or -help Prints out the command line usage of Robocode\n" + + " -cwd Change the current working directory\n" + + " -battle Run the battle specified in a battle file\n" + + " -results Save results to the specified text file\n" + + " -record Record the battle into the specified file as binary\n" + + " -recordXML Record the battle into the specified file as XML\n" + + " -replay Replay the specified battle record\n" + + " -tps Set the TPS > 0 (Turns Per Second)\n" + + " -minimize Run minimized when Robocode starts\n" + + " -nodisplay Run with the display / GUI disabled\n" + + " -nosound Run with sound disabled\n\n" + "Java Properties include:\n" + + " -DWORKINGDIRECTORY= Set the working directory\n" + + " -DROBOTPATH= Set the robots directory (default is 'robots')\n" + + " -DBATTLEPATH= Set the battles directory (default is 'battles')\n" + + " -DNOSECURITY=true|false Enable/disable Robocode's security manager\n" + + " -Ddebug=true|false Enable/disable debugging used for preventing\n" + + " robot timeouts and skipped turns, and allows an\n" + + " an unlimited painting buffer when debugging robots\n" + + " -DlogMessages=true|false Log messages and warnings will be disabled\n" + + " -DlogErrors=true|false Log errors will be disabled\n" + + " -DEXPERIMENTAL=true|false Enable/disable access to peer in robot interfaces\n" + + " -DPARALLEL=true|false Enable/disable parallel processing of robots turns\n" + + " -DRANDOMSEED= Set seed for deterministic behavior of random\n" + + " numbers\n"); + } + + private void printResultsData(BattleCompletedEvent event) { + // Do not print out if no result file has been specified and the GUI is enabled + if ((setup.resultsFilename == null && (!setup.exitOnComplete || windowManager.isGUIEnabled()))) { + return; + } + + PrintStream out = null; + FileOutputStream fos = null; + + try { + if (setup.resultsFilename == null) { + out = Logger.realOut; + } else { + File f = new File(setup.resultsFilename); + + try { + fos = new FileOutputStream(f); + out = new PrintStream(fos); + } catch (IOException e) { + Logger.logError(e); + } + } + if (out != null) { + BattleResultsTableModel resultsTable = new BattleResultsTableModel(event.getSortedResults(), + event.getBattleRules().getNumRounds()); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + resultsTable.print(new PrintStream(baos)); + out.append(StringUtil.toBasicLatin(baos.toString())); + } + } finally { + FileUtil.cleanupStream(out); + FileUtil.cleanupStream(fos); + } + } + + private class BattleObserver extends BattleAdaptor { + boolean isReplay; + + @Override + public void onBattleStarted(BattleStartedEvent event) { + isReplay = event.isReplay(); + } + + @Override + public void onBattleCompleted(BattleCompletedEvent event) { + if (!isReplay) { + printResultsData(event); + } + if (setup.recordFilename != null) { + recordManager.saveRecord(setup.recordFilename, BattleRecordFormat.BINARY_ZIP, + new SerializableOptions(false)); + } + if (setup.recordXmlFilename != null) { + recordManager.saveRecord(setup.recordXmlFilename, BattleRecordFormat.XML, new SerializableOptions(false)); + } + } + + @Override + public void onBattleMessage(BattleMessageEvent event) { + if (System.getProperty("logMessages", "true").equalsIgnoreCase("true")) { + Logger.realOut.println(event.getMessage()); + } + } + + @Override + public void onBattleError(BattleErrorEvent event) { + if (System.getProperty("logErrors", "true").equalsIgnoreCase("true")) { + Logger.realErr.println(event.getError()); + } + } + } + + public void cleanup() { + final IWindowManager windowManager = Container.getComponent(IWindowManager.class); + + if (windowManager != null) { + windowManager.cleanup(); + } + Container.getComponent(IBattleManager.class).cleanup(); + Container.getComponent(IHostManager.class).cleanup(); + } + + public void initForRobocodeEngine(IBattleListener listener) { + final IWindowManager windowManager = Container.getComponent(IWindowManager.class); + + if (windowManager != null) { + windowManager.setSlave(true); + windowManager.setEnableGUI(false); + } + Container.getComponent(IHostManager.class).initSecurity(); + if (listener != null) { + Container.getComponent(IBattleManager.class).addListener(listener); + } + Container.getComponent(ICpuManager.class).getCpuConstant(); + Container.getComponent(IRepositoryManager.class).reload(versionManager.isLastRunVersionChanged()); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/JavaHost.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/JavaHost.java new file mode 100644 index 0000000..7dde1e9 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/JavaHost.java @@ -0,0 +1,192 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import net.sf.robocode.host.security.RobotClassLoader; +import net.sf.robocode.host.proxies.*; +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.repository.RobotType; +import static net.sf.robocode.io.Logger.logError; +import net.sf.robocode.io.Logger; +import net.sf.robocode.peer.IRobotPeer; +import net.sf.robocode.security.HiddenAccess; +import robocode.Droid; +import robocode.Robot; +import robocode.BorderSentry; +import robocode.control.RobotSpecification; +import robocode.robotinterfaces.*; + +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.*; +import java.security.AccessControlException; +import java.lang.reflect.Method; + + +/** + * @author Pavel Savara (original) + */ +public class JavaHost implements IHost { + public IRobotClassLoader createLoader(IRobotItem robotItem) { + return new RobotClassLoader(robotItem.getClassPathURL(), robotItem.getFullClassName()); + } + + public IHostingRobotProxy createRobotProxy(IHostManager hostManager, RobotSpecification robotSpecification, IRobotStatics statics, IRobotPeer peer) { + IHostingRobotProxy robotProxy; + final IRobotItem specification = (IRobotItem) HiddenAccess.getFileSpecification(robotSpecification); + + if (specification.isTeamRobot()) { + robotProxy = new TeamRobotProxy(specification, hostManager, peer, (RobotStatics) statics); + } else if (specification.isAdvancedRobot()) { + robotProxy = new AdvancedRobotProxy(specification, hostManager, peer, (RobotStatics) statics); + } else if (specification.isStandardRobot()) { + robotProxy = new StandardRobotProxy(specification, hostManager, peer, (RobotStatics) statics); + } else if (specification.isJuniorRobot()) { + robotProxy = new JuniorRobotProxy(specification, hostManager, peer, (RobotStatics) statics); + } else { + throw new AccessControlException("Unknown robot type"); + } + return robotProxy; + } + + public String[] getReferencedClasses(IRobotItem robotItem) { + IRobotClassLoader loader = null; + + try { + loader = createLoader(robotItem); + loader.loadRobotMainClass(true); + return loader.getReferencedClasses(); + + } catch (ClassNotFoundException e) { + Logger.logError(e); + return new String[0]; + } finally { + if (loader != null) { + loader.cleanup(); + } + } + } + + public RobotType getRobotType(IRobotItem robotItem, boolean resolve, boolean message) { + IRobotClassLoader loader = null; + + try { + loader = createLoader(robotItem); + Class robotClass = loader.loadRobotMainClass(resolve); + + if (robotClass == null || java.lang.reflect.Modifier.isAbstract(robotClass.getModifiers())) { + // this class is not robot + return RobotType.INVALID; + } + return checkInterfaces(robotClass, robotItem); + + } catch (RuntimeException t) { + if (message) { + logError("Got an error with " + robotItem.getFullClassName() + ": " + t); // just message here + if (t.getMessage() != null && t.getMessage().contains("Bad version number in .class file")) { + logError( + "Maybe robot was compiled with a newer Java version the Java version used for running Robocode?"); + } + } + return RobotType.INVALID; + } finally { + if (loader != null) { + loader.cleanup(); + } + } + } + + private RobotType checkInterfaces(Class robotClass, IRobotItem robotItem) { + boolean isJuniorRobot = false; + boolean isStandardRobot = false; + boolean isInteractiveRobot = false; + boolean isPaintRobot = false; + boolean isAdvancedRobot = false; + boolean isTeamRobot = false; + boolean isDroid = false; + boolean isSentryRobot = false; + + if (IAdvancedRobot.class.isAssignableFrom(robotClass)) { // Note: must be checked first + isAdvancedRobot = true; + } + if (Robot.class.isAssignableFrom(robotClass) && !isAdvancedRobot) { + isStandardRobot = true; + } + if (IJuniorRobot.class.isAssignableFrom(robotClass)) { // Note: Must be checked before checking for standard robot + isJuniorRobot = true; + if (isAdvancedRobot) { + throw new AccessControlException( + robotItem.getFullClassName() + ": Junior robot should not implement IAdvancedRobot interface."); + } + } + if (IBasicRobot.class.isAssignableFrom(robotClass)) { + if (!(isAdvancedRobot || isJuniorRobot)) { + isStandardRobot = true; + } + } + if (ITeamRobot.class.isAssignableFrom(robotClass)) { + isTeamRobot = true; + } + if (Droid.class.isAssignableFrom(robotClass)) { + isDroid = true; + } + if (BorderSentry.class.isAssignableFrom(robotClass)) { + isSentryRobot = true; + } + + if (IInteractiveRobot.class.isAssignableFrom(robotClass)) { + // in this case we make sure that robot don't waste time + if (checkMethodOverride(robotClass, Robot.class, "getInteractiveEventListener") + || checkMethodOverride(robotClass, Robot.class, "onKeyPressed", KeyEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onKeyReleased", KeyEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onKeyTyped", KeyEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onMouseClicked", MouseEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onMouseEntered", MouseEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onMouseExited", MouseEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onMousePressed", MouseEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onMouseReleased", MouseEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onMouseMoved", MouseEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onMouseDragged", MouseEvent.class) + || checkMethodOverride(robotClass, Robot.class, "onMouseWheelMoved", MouseWheelEvent.class) + ) { + isInteractiveRobot = true; + } + } + + if (IPaintRobot.class.isAssignableFrom(robotClass)) { + if (checkMethodOverride(robotClass, Robot.class, "getPaintEventListener") + || checkMethodOverride(robotClass, Robot.class, "onPaint", Graphics2D.class) + ) { + isPaintRobot = true; + } + } + + return new RobotType(isJuniorRobot, isStandardRobot, isInteractiveRobot, isPaintRobot, isAdvancedRobot, + isTeamRobot, isDroid, isSentryRobot); + } + + private boolean checkMethodOverride(Class robotClass, Class knownBase, String name, Class... parameterTypes) { + if (knownBase.isAssignableFrom(robotClass)) { + final Method getInteractiveEventListener; + + try { + getInteractiveEventListener = robotClass.getMethod(name, parameterTypes); + } catch (NoSuchMethodException e) { + return false; + } + if (getInteractiveEventListener.getDeclaringClass().equals(knownBase)) { + return false; + } + } + return true; + } + +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventManager.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventManager.java new file mode 100644 index 0000000..5621c87 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventManager.java @@ -0,0 +1,572 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.events; + + +import net.sf.robocode.host.proxies.BasicRobotProxy; +import net.sf.robocode.security.HiddenAccess; +import robocode.*; +import robocode.exception.EventInterruptedException; +import robocode.robotinterfaces.IBasicRobot; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + + +// XXX Remember to update the .NET version whenever a change is made to this class! + +/** + * This class is used for managing the event queue for a robot. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Matthew Reeder (contributor) + * @author Robert D. Maupin (contributor) + * @author Nathaniel Troutman (contributor) + * @author Pavel Savara (contributor) + */ +public final class EventManager implements IEventManager { + + private final static int MAX_PRIORITY = 100; + public final static int MAX_EVENT_STACK = 2; + public final static int MAX_QUEUE_SIZE = 256; + + private final List customEvents = new CopyOnWriteArrayList(); + private final EventQueue eventQueue; + + private final boolean[] interruptible = new boolean[MAX_PRIORITY + 1]; + private Event currentTopEvent; + private int currentTopEventPriority; + private ScannedRobotEvent dummyScannedRobotEvent; + private Map eventNames; + + private IBasicRobot robot; + private BasicRobotProxy robotProxy; + + /** + * Constructs a new EventManager. + * + * @param robotProxy the robot proxy that this event manager applies to. + */ + public EventManager(BasicRobotProxy robotProxy) { + this.robotProxy = robotProxy; + eventQueue = new EventQueue(); + + registerEventNames(); + reset(); + } + + /** + * Adds an event to the event queue. + * @param event is the event to add to the event queue. + */ + public void add(Event event) { + if (!HiddenAccess.isCriticalEvent(event)) { + final int priority = getEventPriority(event.getClass().getName()); + HiddenAccess.setEventPriority(event, priority); + } + addImpl(event); + } + + /** + * Internal method for adding an event to the event queue. + * @param event is the event to add to the event queue. + */ + private void addImpl(Event event) { + if (eventQueue != null) { + if (eventQueue.size() > MAX_QUEUE_SIZE) { + robotProxy.println( + "Not adding to " + robotProxy.getStatics().getName() + "'s queue, exceeded " + MAX_QUEUE_SIZE + + " events in queue."); + } else { + HiddenAccess.setEventTime(event, getTime()); + eventQueue.add(event); + } + } + } + + /** + * Adds an custom event to the event queue based on a condition. + * @param condition is the condition that must be met in order to trigger the custom event. + */ + public void addCustomEvent(Condition condition) { + customEvents.add(condition); + } + + /** + * Removes all events from the event queue. + * @param includingSystemEvents {@code true} if system events must be removed as well; + * {@code false} if system events should stay on the event queue. + */ + public void clearAllEvents(boolean includingSystemEvents) { + eventQueue.clear(includingSystemEvents); + // customEvents.clear(); // Custom event should not be cleared here + } + + /** + * Cleans up the event queue. + *

+ * This method should be called when the event queue is no longer needed, + * i.e. before it must be garbage collected. + */ + public void cleanup() { + // Remove all events + reset(); + + // Remove all references to robots + robot = null; + robotProxy = null; + } + + /** + * Returns a list containing all events currently in the robot's queue. + */ + public List getAllEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + events.add(e); + } + } + return events; + } + + /** + * Returns a list containing all BulletHitBulletEvents currently in the robot's queue. + */ + public List getBulletHitBulletEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof BulletHitBulletEvent) { + events.add((BulletHitBulletEvent) e); + } + } + } + return events; + } + + /** + * Returns a list containing all BulletHitEvents currently in the robot's queue. + */ + public List getBulletHitEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof BulletHitEvent) { + events.add((BulletHitEvent) e); + } + } + } + return events; + } + + /** + * Returns a list containing all BulletMissedEvents currently in the robot's queue. + */ + public List getBulletMissedEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof BulletMissedEvent) { + events.add((BulletMissedEvent) e); + } + } + } + return events; + } + + /** + * Returns a list containing all HitByBulletEvents currently in the robot's queue. + */ + public List getHitByBulletEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof HitByBulletEvent) { + events.add((HitByBulletEvent) e); + } + } + } + return events; + } + + /** + * Returns a list containing all HitRobotEvents currently in the robot's queue. + */ + public List getHitRobotEvents() { + List events = new ArrayList(); + + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof HitRobotEvent) { + events.add((HitRobotEvent) e); + } + } + } + return events; + } + + /** + * Returns a list containing all HitWallEvents currently in the robot's queue. + */ + public List getHitWallEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof HitWallEvent) { + events.add((HitWallEvent) e); + } + } + } + return events; + } + + /** + * Returns a list containing all RobotDeathEvents currently in the robot's queue. + */ + public List getRobotDeathEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof RobotDeathEvent) { + events.add((RobotDeathEvent) e); + } + } + } + return events; + } + + /** + * Returns a list containing all ScannedRobotEvents currently in the robot's queue. + */ + public List getScannedRobotEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof ScannedRobotEvent) { + events.add((ScannedRobotEvent) e); + } + } + } + return events; + } + + /** + * Returns a list containing all MessageEvents currently in the robot's queue. + */ + public List getMessageEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof MessageEvent) { + events.add((MessageEvent) e); + } + } + } + return events; + } + + /** + * Returns a list containing all StatusEvents currently in the robot's queue. + */ + public List getStatusEvents() { + List events = new ArrayList(); + synchronized (eventQueue) { + for (Event e : eventQueue) { + if (e instanceof StatusEvent) { + events.add((StatusEvent) e); + } + } + } + return events; + } + + /** + * Returns the priority of the current top event. + */ + public int getCurrentTopEventPriority() { + return currentTopEventPriority; + } + + /** + * Returns the current top event. + */ + public Event getCurrentTopEvent() { + return currentTopEvent; + } + + /** + * Checks if events with a specific event priority are interruptible. + * @param priority is the event priority that must be checked. + * @see #setInterruptible(int, boolean) + */ + public boolean isInterruptible(int priority) { + return interruptible[priority]; + } + + /** + * Sets the robot that will receive events dispatched from the event queue. + * @param robot is the robot that will receive event dispatched from the event queue. + */ + public void setRobot(IBasicRobot robot) { + this.robot = robot; + } + + /** + * Returns the priority of a ScannedRobotEvent. + */ + public int getScannedRobotEventPriority() { + return dummyScannedRobotEvent.getPriority(); + } + + /** + * Returns the current time/turn of the battle round. + */ + public long getTime() { + return robotProxy.getTimeImpl(); + } + + /** + * This is the heart of the event manager, which processes the events for a robot. + */ + public void processEvents() { + // Remove old events + eventQueue.clear(getTime() - MAX_EVENT_STACK); + + // Process custom events + for (Condition customEvent : customEvents) { + boolean conditionSatisfied = callUserCode(customEvent); + if (conditionSatisfied) { + addImpl(new CustomEvent(customEvent)); + } + } + + // Sort the events based on the time and priority of the events + eventQueue.sort(); + + // Process event queue here + Event currentEvent; + while ((currentEvent = (eventQueue.size() > 0) ? eventQueue.get(0) : null) != null + && currentEvent.getPriority() >= currentTopEventPriority) { + + if (currentEvent.getPriority() == currentTopEventPriority) { + if (currentTopEventPriority > Integer.MIN_VALUE && isInterruptible(currentTopEventPriority)) { + setInterruptible(currentTopEventPriority, false); // we're going to restart it, so reset. + + // We are already in an event handler, took action, and a new event was generated. + // So we want to break out of the old handler to process it here. + throw new EventInterruptedException(currentEvent.getPriority()); + } + break; + } + + int oldTopEventPriority = currentTopEventPriority; + + currentTopEventPriority = currentEvent.getPriority(); + currentTopEvent = currentEvent; + + eventQueue.remove(currentEvent); + try { + dispatch(currentEvent); + + setInterruptible(currentTopEventPriority, false); + + } catch (EventInterruptedException e) { + currentTopEvent = null; + } catch (RuntimeException e) { + currentTopEvent = null; + throw e; + } catch (MyException e) { + currentTopEvent = null; + throw e; + } finally { + currentTopEventPriority = oldTopEventPriority; + } + } + } + + /** + * Checks if the user's condition for a custom event is satisfied. + * @param condition is the condition to check. + * @return {@code true} if the condition is satisfied; {@code false} otherwise. + */ + private boolean callUserCode(Condition condition) { + boolean conditionSatisfied; + robotProxy.setTestingCondition(true); + try { + conditionSatisfied = condition.test(); + } finally { + robotProxy.setTestingCondition(false); + } + return conditionSatisfied; + } + + /** + * Dispatches an event for a robot. + *

+ * Too old events will not be dispatched and a critical event is always dispatched. + * + * @param event the event to dispatch to the robot. + */ + private void dispatch(Event event) { + if (robot != null && event != null) { + try { + // skip too old events + if ((event.getTime() > getTime() - MAX_EVENT_STACK) || HiddenAccess.isCriticalEvent(event)) { + HiddenAccess.dispatch(event, robot, robotProxy.getStatics(), robotProxy.getGraphicsImpl()); + } + } catch (Exception ex) { + robotProxy.println("SYSTEM: " + ex.getClass().getName() + " occurred on " + event.getClass().getName()); + ex.printStackTrace(robotProxy.getOut()); + } + } + } + + /** + * Removes the custom event with the specified condition from the event queue. + * @param condition is the condition of the custom event to remove. + */ + public void removeCustomEvent(Condition condition) { + customEvents.remove(condition); + } + + /** + * Removes all custom events from the event queue. + */ + public void resetCustomEvents() { + customEvents.clear(); + } + + /** + * Resets this event manager by removing all events from the event queue. + */ + public synchronized void reset() { + currentTopEventPriority = Integer.MIN_VALUE; + clearAllEvents(true); + customEvents.clear(); + } + + /** + * Changes the interruptible flag for events with a specific priority. + * When an event is interrupted, events with the same priority are allowed to restart the event handler. + * + * @param priority is the priority of the event to set the interruptible flag for. + * @param isInterruptable {@code true} if events with the specified priority must be interruptible + * allowing events with the same priority to restart the event handler. + * {@code false} if events with the specified priority must not be interruptible + * disallowing events with the same priority to restart the event handler. + */ + public void setInterruptible(int priority, boolean isInterruptable) { + if (priority >= 0 && priority < MAX_PRIORITY) { + interruptible[priority] = isInterruptable; + } + } + + /** + * Returns the priority of events belonging to a specific class. + * @param eventClass is a string with the full class name of the event type to get the priority from. + * @return the event priority of the specified event class. + * @see robocode.Event#getPriority() + */ + public int getEventPriority(String eventClass) { + if (eventClass == null) { + return -1; + } + final Event event = eventNames.get(eventClass); + if (event == null) { + return -1; + } + return event.getPriority(); + } + + /** + * Sets the event priority of events belonging to a specific class. + * @param eventClass is a string with the full class name of the event type to set the priority for. + * @param priority is the new priority + */ + public void setEventPriority(String eventClass, int priority) { + if (eventClass == null) { + return; + } + final Event event = eventNames.get(eventClass); + if (event == null) { + robotProxy.println("SYSTEM: Unknown event class: " + eventClass); + return; + } + if (HiddenAccess.isCriticalEvent(event)) { + robotProxy.println("SYSTEM: You may not change the priority of a system event."); + } + HiddenAccess.setEventPriority(event, priority); + } + + /** + * Registers the full and simple class names of all events used by {@link #getEventPriority(String)} and + * {@link #setEventPriority(String, int)} and sets the default priority of each event class. + */ + private void registerEventNames() { + eventNames = new HashMap(); + dummyScannedRobotEvent = new ScannedRobotEvent(null, 0, 0, 0, 0, 0, false); + registerEventNames(new BattleEndedEvent(false, null)); + registerEventNames(new BulletHitBulletEvent(null, null)); + registerEventNames(new BulletHitEvent(null, 0, null)); + registerEventNames(new BulletMissedEvent(null)); + registerEventNames(new DeathEvent()); + registerEventNames(new HitByBulletEvent(0, null)); + registerEventNames(new HitRobotEvent(null, 0, 0, false)); + registerEventNames(new HitWallEvent(0)); + registerEventNames(new KeyPressedEvent(null)); + registerEventNames(new KeyReleasedEvent(null)); + registerEventNames(new KeyTypedEvent(null)); + registerEventNames(new MessageEvent(null, null)); + registerEventNames(new MouseClickedEvent(null)); + registerEventNames(new MouseDraggedEvent(null)); + registerEventNames(new MouseEnteredEvent(null)); + registerEventNames(new MouseExitedEvent(null)); + registerEventNames(new MouseMovedEvent(null)); + registerEventNames(new MousePressedEvent(null)); + registerEventNames(new MouseReleasedEvent(null)); + registerEventNames(new MouseWheelMovedEvent(null)); + registerEventNames(new PaintEvent()); + registerEventNames(new RobotDeathEvent(null)); + registerEventNames(new RoundEndedEvent(0, 0, 0)); + registerEventNames(dummyScannedRobotEvent); + registerEventNames(new SkippedTurnEvent(0)); + registerEventNames(new StatusEvent(null)); + registerEventNames(new WinEvent()); + + // same as any line above but for custom event + final DummyCustomEvent customEvent = new DummyCustomEvent(); + eventNames.put("robocode.CustomEvent", customEvent); // full name with package name + eventNames.put("CustomEvent", customEvent); // only the class name + } + + /** + * Registers the full and simple class name of the specified event and sets the default + * priority of the event class. + * @param event an event belonging to the event class to register the class name for etc. + */ + private void registerEventNames(Event event) { + if (!HiddenAccess.isCriticalEvent(event)) { + HiddenAccess.setDefaultPriority(event); + } + final Class type = event.getClass(); + eventNames.put(type.getName(), event); // full name with package name + eventNames.put(type.getSimpleName(), event); // only the class name + } + + /** + * A dummy CustomEvent used only for registering the class name. + */ + @SuppressWarnings("serial") + private static final class DummyCustomEvent extends CustomEvent { + public DummyCustomEvent() { + super(null); + } + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/HostingRobotProxy.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/HostingRobotProxy.java new file mode 100644 index 0000000..9fdb31e --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/HostingRobotProxy.java @@ -0,0 +1,306 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.proxies; + + +import net.sf.robocode.host.events.EventManager; +import net.sf.robocode.host.io.RobotFileSystemManager; +import net.sf.robocode.host.io.RobotOutputStream; +import net.sf.robocode.host.security.RobotThreadManager; +import net.sf.robocode.host.*; +import static net.sf.robocode.io.Logger.logError; +import static net.sf.robocode.io.Logger.logMessage; +import net.sf.robocode.peer.BadBehavior; +import net.sf.robocode.peer.ExecCommands; +import net.sf.robocode.peer.IRobotPeer; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.core.Container; +import robocode.RobotStatus; +import robocode.exception.AbortedException; +import robocode.exception.DeathException; +import robocode.exception.DisabledException; +import robocode.exception.WinException; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.peer.IBasicRobotPeer; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + + +// XXX Remember to update the .NET version whenever a change is made to this class! + +/** + * @author Pavel Savara (original) + */ +abstract class HostingRobotProxy implements IHostingRobotProxy, IHostedThread { + + private final IRobotItem robotSpecification; + + protected EventManager eventManager; + private final IHostManager hostManager; + protected RobotThreadManager robotThreadManager; + protected RobotFileSystemManager robotFileSystemManager; + private IThreadManager threadManager; + + private IBasicRobot robot; + protected final IRobotPeer peer; + protected IRobotClassLoader robotClassLoader; + + protected final RobotStatics statics; + protected RobotOutputStream out; + + private final Set securityViolations = Collections.synchronizedSet(new HashSet()); + + HostingRobotProxy(IRobotItem robotSpecification, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { + this.peer = peer; + this.statics = statics; + this.hostManager = hostManager; + this.robotSpecification = robotSpecification; + + robotClassLoader = getHost(robotSpecification).createLoader(robotSpecification); + robotClassLoader.setRobotProxy(this); + + out = new RobotOutputStream(); + robotThreadManager = new RobotThreadManager(this); + + loadClassBattle(); + + robotFileSystemManager = new RobotFileSystemManager(this, hostManager.getRobotFilesystemQuota(), + robotSpecification.getWritableDirectory(), robotSpecification.getReadableDirectory(), + robotSpecification.getRootPath()); + + robotFileSystemManager.initialize(); + } + + private JavaHost getHost(IRobotItem robotSpecification) { + return (JavaHost) Container.cache.getComponent("robocode.host." + robotSpecification.getPlatform().toLowerCase()); + } + + public void cleanup() { + robot = null; + + // Remove the file system and the manager + robotFileSystemManager = null; + if (out != null) { + out.close(); + out = null; + } + + if (robotThreadManager != null) { + robotThreadManager.cleanup(); + } + robotThreadManager = null; + + // Cleanup and remove class manager + if (robotClassLoader != null) { + robotClassLoader.cleanup(); + robotClassLoader = null; + } + } + + public RobotOutputStream getOut() { + return out; + } + + public void println(String s) { + out.println(s); + } + + private void println(Throwable ex) { + ex.printStackTrace(out); + } + + public RobotStatics getStatics() { + return statics; + } + + public RobotFileSystemManager getRobotFileSystemManager() { + return robotFileSystemManager; + } + + public ClassLoader getRobotClassloader() { + return (ClassLoader) robotClassLoader; + } + + // ----------- + // battle driven methods + // ----------- + + protected abstract void initializeRound(ExecCommands commands, RobotStatus status); + + public void startRound(ExecCommands commands, RobotStatus status) { + initializeRound(commands, status); + threadManager = ((HostManager) hostManager).getThreadManager(); + robotThreadManager.start(threadManager); + } + + public void forceStopThread() { + if (!robotThreadManager.forceStop()) { + peer.punishBadBehavior(BadBehavior.UNSTOPPABLE); + peer.setRunning(false); + } + } + + public void waitForStopThread() { + if (!robotThreadManager.waitForStop()) { + peer.punishBadBehavior(BadBehavior.UNSTOPPABLE); + peer.setRunning(false); + } + } + + private void loadClassBattle() { + try { + robotClassLoader.loadRobotMainClass(true); + } catch (RuntimeException e) { + println("SYSTEM: Could not load " + statics.getName() + " : "); + println(e); + drainEnergy(); + } + } + + private boolean loadRobotRound() { + robot = null; + try { + threadManager.setLoadingRobot(this); + robot = robotClassLoader.createRobotInstance(); + if (robot == null) { + println("SYSTEM: Skipping robot: " + statics.getName()); + return false; + } + robot.setOut(out); + robot.setPeer((IBasicRobotPeer) this); + eventManager.setRobot(robot); + } catch (IllegalAccessException e) { + println("SYSTEM: Unable to instantiate this robot: " + e); + println("SYSTEM: Is your constructor marked public?"); + println(e); + robot = null; + logError(e); + return false; + } catch (RuntimeException e) { + println("SYSTEM: An error occurred during initialization of " + statics.getName()); + println("SYSTEM: " + e); + println(e); + robot = null; + logError(e); + return false; + } finally { + threadManager.setLoadingRobot(null); + } + return true; + } + + protected abstract void executeImpl(); + + public void run() { + // Only initialize AWT if we are not running in headless mode. + // Bugfix [2833271] IllegalThreadStateException with the AWT-Shutdown thread. + // Read more about headless mode here: + // http://java.sun.com/developer/technicalArticles/J2SE/Desktop/headless/ + if (System.getProperty("java.awt.headless", "true").equals("false")) { + robotThreadManager.initAWT(); + } + + if (robotSpecification.isValid() && loadRobotRound()) { + try { + if (robot != null) { + peer.setRunning(true); + + // Process all events for the first turn. + // This is done as the first robot status event must occur before the robot + // has started running. + eventManager.processEvents(); + + // Call user code + callUserCode(); + } + while (peer.isRunning()) { + executeImpl(); + } + } catch (WinException e) {// Do nothing + } catch (AbortedException e) {// Do nothing + } catch (DeathException e) { + println("SYSTEM: " + statics.getName() + " has died"); + } catch (DisabledException e) { + drainEnergy(); + + String msg = e.getMessage(); + if (msg == null) { + msg = ""; + } else { + msg = ": " + msg; + } + println("SYSTEM: Robot disabled: " + msg); + logMessage("Robot disabled: " + statics.getName()); + } catch (Exception e) { + drainEnergy(); + println(e); + logMessage(statics.getName() + ": Exception: " + e); // without stack here + } catch (ThreadDeath e) { + drainEnergy(); + println(e); + logMessage(statics.getName() + " stopped successfully."); + throw e; // must be re-thrown in order to stop the thread + } catch (RuntimeException t) { + drainEnergy(); + println(t); + logMessage(statics.getName() + ": Throwable: " + t); // without stack here + } finally { + waitForBattleEndImpl(); + } + } else { + drainEnergy(); + peer.punishBadBehavior(BadBehavior.CANNOT_START); + waitForBattleEndImpl(); + } + + peer.setRunning(false); + + // If battle is waiting for us, well, all done! + synchronized (this) { + notifyAll(); + } + } + + private void callUserCode() { + Runnable runnable = robot.getRobotRunnable(); + if (runnable != null) { + runnable.run(); + } + } + + protected abstract void waitForBattleEndImpl(); + + public void drainEnergy() { + peer.drainEnergy(); + } + + public void punishSecurityViolation(String message) { + // Prevent unit tests of failing if multiple threads are calling this method in the same time. + // We only want the a specific type of security violation logged once so we only get one error + // per security violation. + synchronized (securityViolations) { + String key = message; + + if (key.startsWith("Preventing Thread-")) { + key = key.replaceAll("\\d+", "X"); + } + if (!securityViolations.contains(key)) { + securityViolations.add(key); + logError(message); + println("SYSTEM: " + message); + + if (securityViolations.size() == 1) { + peer.drainEnergy(); + peer.punishBadBehavior(BadBehavior.SECURITY_VIOLATION); + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotClassLoader.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotClassLoader.java new file mode 100644 index 0000000..0993839 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotClassLoader.java @@ -0,0 +1,424 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.security; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.host.IHostedThread; +import net.sf.robocode.host.IRobotClassLoader; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import net.sf.robocode.io.URLJarCollector; +import robocode.robotinterfaces.IBasicRobot; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLConnection; +import java.nio.ByteBuffer; +import java.security.*; +import java.security.cert.Certificate; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +/** + * This class loader is used by robots. It isolates classes which belong to robot and load them locally. + * General java classes or robocode.api classes are loaded by parent loader and shared with Robocode engine. + * Attempts to load classes of Robocode engine are blocked. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Matthew Reeder (contributor) + * @author Robert D. Maupin (contributor) + * @author Nathaniel Troutman (contributor) + */ +public class RobotClassLoader extends URLClassLoader implements IRobotClassLoader { + + static final String UNTRUSTED_URL = "http://robocode.sf.net/untrusted"; + + private static final PermissionCollection EMPTY_PERMISSIONS = new Permissions(); + + private final String fullClassName; + + private ClassLoader parent; + private CodeSource codeSource; + + private IHostedThread robotProxy; + private Class robotClass; + + // Names on classes referenced from the robot class + private Set referencedClasses = new HashSet(); + + // Cached names on found system classes + private Set foundSystemClasses = new HashSet(); + + // Cached warning messages + private String[] staticRobotInstanceWarning; + + public RobotClassLoader(URL robotClassPath, String robotFullClassName) { + super(new URL[] { robotClassPath}, Container.systemLoader); + fullClassName = robotFullClassName; + parent = getParent(); + try { + codeSource = new CodeSource(new URL(UNTRUSTED_URL), (Certificate[]) null); + } catch (MalformedURLException ignored) {} + } + + public void setRobotProxy(Object robotProxy) { + this.robotProxy = (IHostedThread) robotProxy; + } + + public synchronized void addURL(URL url) { + super.addURL(url); + } + + public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (name.startsWith("java.lang")) { + // we always delegate java.lang stuff to parent loader + return super.loadClass(name, resolve); + } + if (RobocodeProperties.isSecurityOn()) { + testPackages(name); + } + if (!name.startsWith("robocode")) { + Class result = loadRobotClassLocaly(name, resolve); + if (result != null) { + // yes, it is in robot's class path + // we loaded it locally + return result; + } + } + + // it is robot API + // or java class + // or security is off + // so we delegate to parent class loader + return parent.loadClass(name); + } + + private void testPackages(String name) throws ClassNotFoundException { + if (name.startsWith("net.sf.robocode")) { + String message = "Robots are not allowed to reference Robocode engine in package: net.sf.robocode"; + + punishSecurityViolation(message); + throw new ClassNotFoundException(message); + } + if (name.startsWith("robocode.control")) { + String message = "Robots are not allowed to reference Robocode engine in package: robocode.control"; + + punishSecurityViolation(message); + throw new ClassNotFoundException(message); + } + if (RobocodeProperties.isSecurityOn() && name.startsWith("javax.swing")) { + String message = "Robots are not allowed to reference Robocode engine in package: javax.swing"; + + punishSecurityViolation(message); + throw new ClassNotFoundException(message); + } + } + + private Class loadRobotClassLocaly(String name, boolean resolve) throws ClassNotFoundException { + Class result = findLoadedClass(name); + if (result == null) { + ByteBuffer resource = findLocalResource(name); + if (resource != null) { + result = defineClass(name, resource, codeSource); + if (resolve) { + resolveClass(result); + } + ClassAnalyzer.getReferencedClasses(resource, referencedClasses); + } + } + return result; + } + + // this whole fun is there to be able to provide defineClass with bytes + // we need to call defineClass to be able to set codeSource to untrustedLocation + private ByteBuffer findLocalResource(final String name) { + return AccessController.doPrivileged(new PrivilegedAction() { + public ByteBuffer run() { + // try to find it in robot's class path + // this is URL, don't change to File.pathSeparator + String path = name.replace('.', '/').concat(".class"); + URL url = findResource(path); + ByteBuffer result = null; + InputStream is = null; + BufferedInputStream bis = null; + + if (url != null) { + try { + URLConnection connection = URLJarCollector.openConnection(url); + + is = connection.getInputStream(); + bis = new BufferedInputStream(is); + + result = ByteBuffer.allocate(1024 * 8); + boolean done = false; + + do { + do { + int res = bis.read(result.array(), result.position(), result.remaining()); + + if (res == -1) { + done = true; + break; + } + result.position(result.position() + res); + } while (result.remaining() != 0); + result.flip(); + if (!done) { + result = ByteBuffer.allocate(result.capacity() * 2).put(result); + } + } while (!done); + + } catch (IOException e) { + Logger.logError(e); + return null; + } finally { + FileUtil.cleanupStream(bis); + FileUtil.cleanupStream(is); + } + } + return result; + } + }); + } + + private void punishSecurityViolation(String message) { + if (robotProxy != null) { + robotProxy.punishSecurityViolation(message); + } + } + + protected PermissionCollection getPermissions(CodeSource codesource) { + if (RobocodeProperties.isSecurityOn()) { + return EMPTY_PERMISSIONS; + } + return super.getPermissions(codesource); + } + + public String[] getReferencedClasses() { + return referencedClasses.toArray(new String[referencedClasses.size()]); + } + + public synchronized Class loadRobotMainClass(boolean resolve) throws ClassNotFoundException { + try { + if (robotClass == null) { + robotClass = loadClass(fullClassName, resolve); + + if (!IBasicRobot.class.isAssignableFrom(robotClass)) { + // that's not robot + return null; + } + if (resolve) { + // resolve methods to see more referenced classes + robotClass.getMethods(); + + // iterate thru dependencies until we didn't found any new + HashSet clone; + + do { + clone = new HashSet(referencedClasses); + for (String reference : clone) { + testPackages(reference); + if (!isSystemClass(reference)) { + loadClass(reference, true); + } + } + } while (referencedClasses.size() != clone.size()); + } + } else { + warnIfStaticRobotInstanceFields(); + } + } catch (RuntimeException e) { + robotClass = null; + throw new ClassNotFoundException(e.getMessage(), e); + } + return robotClass; + } + + public IBasicRobot createRobotInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException { + loadRobotMainClass(true); + return (IBasicRobot) robotClass.newInstance(); + } + + public void cleanup() { + // Bug fix [2930266] - Robot static data isn't being GCed after battle + for (String className : getReferencedClasses()) { + cleanStaticReferences(className); + } + + parent = null; + codeSource = null; + robotProxy = null; + robotClass = null; + referencedClasses = null; + foundSystemClasses = null; + } + + /** + * Cleans all static field references on a class. + * + * @param className the name of the class containing the static references to clean. + */ + private void cleanStaticReferences(String className) { + if (isSystemClass(className)) { + return; + } + Class type = null; + try { + type = loadRobotClassLocaly(className, false); + if (type != null) { + for (Field field : getAllFields(new ArrayList(), type)) { + if (isStaticReference(field)) { + cleanStaticReference(field); + } + } + } + } catch (RuntimeException t) { + Logger.logError(t); + } + } + + private void warnIfStaticRobotInstanceFields() { + if (staticRobotInstanceWarning == null) { + List staticRobotReferences = new ArrayList(); + + for (String className : getReferencedClasses()) { // Bug fix [3028102] - ConcurrentModificationException + if (isSystemClass(className)) { + continue; + } + Class type = null; + try { + type = loadRobotClassLocaly(className, false); + } catch (RuntimeException t) { + continue; + } + if (type != null) { + for (Field field : getAllFields(new ArrayList(), type)) { + if (isStaticReference(field) && IBasicRobot.class.isAssignableFrom(field.getType()) + && field.getAnnotation(robocode.annotation.SafeStatic.class) == null) { + staticRobotReferences.add(field); + } + } + } + } + if (staticRobotReferences.size() > 0) { + StringBuilder buf = new StringBuilder(); + + buf.append("Warning: ").append(fullClassName).append( + " uses static reference to a robot with the following field(s):"); + + for (Field field : staticRobotReferences) { + buf.append("\n\t").append(field.getDeclaringClass().getName()).append('.').append(field.getName()).append(", which points to a ").append( + field.getType().getName()); + } + + staticRobotInstanceWarning = new String[] { + buf.toString(), + "Static references to robots can cause unwanted behaviour with the robot using these.", + "Please change static robot references to non-static references and recompile the robot."}; + } else { + staticRobotInstanceWarning = new String[] {}; // Signal that there is no warnings to cache + } + } else if (staticRobotInstanceWarning.length == 0) { + return; // Return, as no warnings should be written out in the robot console + } + + // Write out warnings to the robot console + if (robotProxy != null) { + for (String line : staticRobotInstanceWarning) { + robotProxy.getOut().println("SYSTEM: " + line); + } + } + } + + /** + * Cleans a static field reference class, even when it is 'private static final' + * + * @param field the field to clean, if it is a static reference. + */ + private void cleanStaticReference(Field field) { + if (field.getName().startsWith("const__")) { + // Ignore 'const__' fields used with e.g. the Clojure language + return; + } + field.setAccessible(true); + try { + // In order to set a 'private static field', we need to fix the modifier, i.e. use magic! ;-) + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + int modifiers = modifiersField.getInt(field); + modifiersField.setInt(field, modifiers & ~Modifier.FINAL); // Remove the FINAL modifier + field.set(null, null); + + } catch (RuntimeException ignore) {} + } + + /** + * Gets all fields of a class (public, protected, private) and the ones inherited from all super classes. + * @param fields the list where the fields will be added as a result of calling this method. + * @param type the class to retrieve all the fields from + * @return the list specified as input parameter containing all the retrieved fields + */ + private List getAllFields(List fields, Class type) { + if (type == null || isSystemClass(type.getName())) { + return fields; + } + try { + for (Field field: type.getDeclaredFields()) { + fields.add(field); + } + } catch (RuntimeException ignore) {// NoClassDefFoundError does occur with some robots, e.g. sgp.Drunken [1.12] + // We ignore all exceptions and errors here so we can proceed to retrieve + // field from super classes. + } + if (type.getSuperclass() != null) { + fields = getAllFields(fields, type.getSuperclass()); + } + return fields; + } + + /** + * Checks if a specified class name is a Java system class or internal Robocode class. + * @param className the class name to check. + * @return true if the class name is a system class; false otherwise. + */ + private boolean isSystemClass(String className) { + boolean isSystemClass = foundSystemClasses.contains(className); + if (!isSystemClass) { + try { + if (findSystemClass(className) != null) { + foundSystemClasses.add(className); + isSystemClass = true; + } + } catch (ClassNotFoundException ignore) {} + } + return isSystemClass; + } + + /** + * Checks if a specified field is a static reference. + * + * @param field the field to check. + * @return true if the field is static reference; false otherwise. + */ + private static boolean isStaticReference(Field field) { + return Modifier.isStatic(field.getModifiers()) + && !(field.getType().isPrimitive() || field.isEnumConstant() || field.isSynthetic()); + } +} diff --git a/代码/workspace_robo4/robocode.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java b/代码/workspace_robo4/robocode.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java new file mode 100644 index 0000000..e4c6d0a --- /dev/null +++ b/代码/workspace_robo4/robocode.installer/src/main/java/net/sf/robocode/installer/AutoExtract.java @@ -0,0 +1,705 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.installer; + + +import javax.swing.*; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; +import java.net.URL; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarInputStream; + + +/** + * Installer for Robocode. + * + * @author Mathew A. Nelsen (original) + * @author Flemming N. Larsen (contributor) + */ +public class AutoExtract implements ActionListener { + private JDialog licenseDialog; + private boolean accepted; + private static final String[] SPINNER = { "-", "\\", "|", "/"}; + private String message = ""; + private static File installDir; + private static final String osName = System.getProperty("os.name"); + private static final double osVersion = doubleValue(System.getProperty("os.version")); + private static final String javaVersion = System.getProperty("java.version"); + + private static double doubleValue(String s) { + s = s.replaceAll("[^.0-9]", ""); // Remove invalid characters, e.g. "3.0-ARCH" become "3.0" + + int p = s.indexOf("."); + + if (p >= 0) { + p = s.indexOf(".", p + 1); + } + if (p >= 0) { + s = s.substring(0, p); + } + + double d = 0.0; + + try { + d = Double.parseDouble(s); + } catch (NumberFormatException e) { + e.printStackTrace(System.err); + } + + return d; + } + + private boolean acceptLicense() { + StringBuffer licenseText = new StringBuffer(); + + InputStream is; + + try { + JarFile extractJar = new JarFile("extract.jar"); + + is = extractJar.getInputStream(extractJar.getJarEntry("license/cpl-v10.html")); + } catch (IOException e) { + return true; + } + if (is == null) { + return true; + } + + InputStreamReader isr = null; + BufferedReader br = null; + + try { + isr = new InputStreamReader(is); + br = new BufferedReader(isr); + + String line = br.readLine(); + + while (line != null) { + licenseText.append(line); + line = br.readLine(); + } + return acceptReject(licenseText.toString()); + + } catch (IOException e) { + System.err.println("Could not read line from license file: " + e); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (isr != null) { + try { + isr.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return true; + } + + private boolean acceptReject(String text) { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + licenseDialog = new JDialog(); + licenseDialog.setTitle("License Agreement"); + licenseDialog.setModal(true); + licenseDialog.setLocation((screenSize.width - 500) / 2, (screenSize.height - 400) / 2); + licenseDialog.setSize(500, 400); + JTextPane t = new JTextPane(); + + t.setContentType("text/html"); + t.setText(text); + t.setFont(new Font("Dialog", Font.PLAIN, 12)); + t.setEditable(false); + + JScrollPane s = new JScrollPane(); + + s.setViewportView(t); + + licenseDialog.getContentPane().setLayout(new BorderLayout()); + licenseDialog.getContentPane().add(s, BorderLayout.CENTER); + + JPanel p = new JPanel(); + + p.setLayout(new BorderLayout()); + JButton b1 = new JButton("Accept"); + JButton b2 = new JButton("Cancel"); + + p.add(b1, BorderLayout.WEST); + p.add(b2, BorderLayout.EAST); + + b1.addActionListener(this); + b2.addActionListener(this); + + licenseDialog.getContentPane().add(p, BorderLayout.SOUTH); + + licenseDialog.setVisible(true); + + return accepted; + } + + public void actionPerformed(ActionEvent e) { + accepted = e.getActionCommand().equals("Accept"); + licenseDialog.dispose(); + licenseDialog = null; + } + + private boolean extract(File installDir) { + JDialog statusDialog = new JDialog(); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + int width = 500; + int height = 100; + + statusDialog.setTitle("Installing"); + statusDialog.setLocation((screenSize.width - width) / 2, (screenSize.height - height) / 2); + statusDialog.setSize(width, height); + JLabel status = new JLabel(); + + statusDialog.getContentPane().setLayout(new BorderLayout()); + statusDialog.getContentPane().add(status, BorderLayout.CENTER); + + statusDialog.setVisible(true); + + FileOutputStream fos; + String entryName; + + byte buf[] = new byte[2048]; + + final String name = AutoExtract.class.getName().replaceAll("\\.", "/") + ".class"; + String urlJar = AutoExtract.class.getClassLoader().getResource(name).toString(); + final String src = urlJar.substring("jar:file:/".length(), urlJar.indexOf("!/")); + + if (src.indexOf('!') > -1) { + message = src + "\nContains an exclamation point. Please move the file to a different directory."; + JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); + return false; + } + JarInputStream jarIS = null; + + try { + final URL url = new URL("file:/" + src); + InputStream is = url.openStream(); + + jarIS = new JarInputStream(is); + + JarEntry entry; + + while ((entry = jarIS.getNextJarEntry()) != null) { + int spin = 0; + + entryName = entry.getName(); + if (entry.isDirectory()) { + if (!entryName.startsWith("net") && !(entryName.equals("desktop") && isFreeBSD())) { + File dir = new File(installDir, entry.getName()); + if (!dir.exists() && !dir.mkdirs()) { + System.err.println("Can't create dir: " + dir); + } + } + } else if (!entryName.equals(name)) { + + // Skip .bat, .sh, and .command files depending on which OS Robocode is installed + + final String entryNameLC = entryName.toLowerCase(); + + boolean skipEntry = false; + + final boolean isBatFile = entryNameLC.length() > ".bat".length() && entryNameLC.endsWith(".bat"); + final boolean isShFile = entryNameLC.length() > ".sh".length() && entryNameLC.endsWith(".sh"); + final boolean isCommandFile = entryNameLC.length() > ".command".length() + && entryNameLC.endsWith(".command"); + final boolean isDesktopFile = entryNameLC.startsWith("desktop/"); + + // Unix systems and Mac OS X + if (File.separatorChar == '/') { + // Skip .bat files under Unix and Mac OS X + // Skip .command files under Unix + skipEntry = isBatFile || (isCommandFile && !isMacOSX()) || (isDesktopFile && !isFreeBSD()); + } else { + // Under Windows the .sh and .command files are skipped + skipEntry = isShFile || isCommandFile || isDesktopFile; + } + + // If we are not skipping the entry, then copy from our .jar into the installation dir + if (!skipEntry) { + status.setText(entryName + " " + SPINNER[spin++]); + + File out = new File(installDir, entryName); + + File parentDirectory = new File(out.getParent()); + if (!parentDirectory.exists() && !parentDirectory.mkdirs()) { + System.err.println("Can't create dir: " + parentDirectory); + } + fos = new FileOutputStream(out); + + int index = 0; + int num; + int count = 0; + + while ((num = jarIS.read(buf, 0, 2048)) != -1) { + fos.write(buf, 0, num); + index += num; + count++; + if (count > 80) { + status.setText(entryName + " " + SPINNER[spin++] + " (" + index + " bytes)"); + if (spin > 3) { + spin = 0; + } + count = 0; + } + } + fos.close(); + + // Set file permissions for .sh and .command files under Unix and Mac OS X + if (File.separatorChar == '/') { + if (isShFile || isCommandFile) { + // Grant read and execute access for everyone and also write access for the owner of the file + Runtime.getRuntime().exec("chmod 755 " + out.toString()); + } + } + + status.setText(entryName + " " + SPINNER[spin] + " (" + index + " bytes)"); + } + } + } + statusDialog.dispose(); + return true; + } catch (IOException e) { + message = "Installation failed: " + e; + JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); + return false; + } finally { + if (jarIS != null) { + try { + jarIS.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public static void main(String argv[]) { + String suggestedDirName; + + if (argv.length == 1) { + suggestedDirName = argv[0]; + } else if (isWindowsOS()) { + suggestedDirName = "C:\\robocode\\"; + } else { + suggestedDirName = System.getProperty("user.home") + File.separator + "robocode" + File.separator; + } + + String message; + + if (install(new File(suggestedDirName))) { + message = "Installation successful"; + } else { + message = "Installation cancelled"; + } + + // Delete the class file with the installer and it's parent folders in the robocode home dir + if (installDir != null) { + String installerPath = AutoExtract.class.getName().replaceAll("\\.", "/") + "$1.class"; + + deleteFileAndParentDirsIfEmpty(new File(installDir, installerPath)); + } + + JOptionPane.showMessageDialog(null, message); + } + + private static boolean install(File suggestedDir) { + // Verify that the Java version is version 6 (1.6.0) or newer + if (javaVersion.startsWith("1.") && javaVersion.charAt(2) < '5') { + final String message = "Robocode requires Java 6 (1.6.0) or newer.\n" + + "Your system is currently running Java " + javaVersion + ".\n" + + "If you have not installed (or activated) at least\n" + "JRE 6 or JDK 6, please do so."; + + JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); + System.err.println(message); + return false; + } + + // Set native look and feel + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (RuntimeException t) {// For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF + } + + AutoExtract extractor = new AutoExtract(); + + if (extractor.acceptLicense()) { + boolean done = false; + + while (!done) { + int rc = JOptionPane.showConfirmDialog(null, + "Robocode will be installed in:\n" + suggestedDir + "\nIs this ok?", "Installing Robocode", + JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + + if (rc == JOptionPane.YES_OPTION) { + installDir = suggestedDir; + done = true; + } else if (rc == JOptionPane.NO_OPTION) { + Object r = JOptionPane.showInputDialog(null, "Please type in the installation directory", + "Installation Directory", JOptionPane.PLAIN_MESSAGE, null, null, suggestedDir); + + if (r != null) { + suggestedDir = new File(((String) r).trim()); + } else { + return false; + } + } else if (rc == JOptionPane.CANCEL_OPTION) { + return false; + } + } + if (!installDir.exists() && !installDir.mkdirs()) { + System.err.println("Can't create dir: " + installDir); + return false; + } + deleteOldLibs(installDir); + + // The .robotcache has been renamed to .data + File robotsCacheDir = new File(installDir, "robots/.robotcache"); + File robotsDataDir = new File(installDir, "robots/.data"); + + if (robotsCacheDir.exists()) { + // Rename ".robotcache" into ".data" + robotsCacheDir.renameTo(robotsDataDir); + } + + // Fix problem with .data starting with a underscore dir by + // renaming files containing ".data/_" into ".data" + if (robotsDataDir.exists()) { + File underScoreDir = new File(robotsDataDir, "_"); + String[] list = underScoreDir.list(); + + if (list != null) { + for (String fileName : list) { + File file = new File(underScoreDir, fileName); + + file.renameTo(new File(robotsDataDir, fileName)); + } + underScoreDir.delete(); + } + } + + // Create shortcuts and file associations + if (extractor.extract(installDir)) { + extractor.createShortcuts(installDir, "robocode.bat", "Robocode", "Robocode"); + extractor.createFileAssociations(installDir); + return true; + } + } + return false; + } + + private static void deleteOldLibs(File installDir) { + File libs = new File(installDir, "libs"); + + if (libs.exists()) { + final File[] del = libs.listFiles(new FilenameFilter() { + + public boolean accept(File dir, String name) { + String test = name.toLowerCase(); + + return test.endsWith(".jar") || test.endsWith(".dll"); + } + }); + + for (File d : del) { + if (!d.delete()) { + System.err.println("Can't delete: " + d); + } + } + } + } + + private static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + for (File file : dir.listFiles()) { + if (file.isDirectory()) { + // Skip directories ending with ".data" + if (file.getName().endsWith(".data")) { + continue; + } + try { + // Test for symlink and ignore. + // Robocode won't create one, but just in case a user does... + if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) { + deleteDir(file); + if (file.exists() && !file.delete()) { + System.err.println("Can't delete: " + file); + } + } else { + System.out.println("Warning: " + file + " may be a symlink. It has been ignored"); + } + } catch (IOException e) { + System.out.println( + "Warning: Cannot determine canonical file for " + file + ". It has been ignored"); + } + } else { + if (file.exists() && !file.delete()) { + System.err.println("Can't delete: " + file); + } + } + } + return dir.delete(); + } + return false; + } + + private void createShortcuts(File installDir, String runnable, String folder, String name) { + if (osName.toLowerCase().indexOf("win") == 0) { + if (createWindowsShortcuts(installDir, runnable, folder, name) == false) { + JOptionPane.showMessageDialog(null, + message + "\n" + "To start Robocode, enter the following at a command prompt:\n" + "cd " + + installDir.getAbsolutePath() + "\n" + "robocode.bat"); + } + } else if (osName.toLowerCase().indexOf("mac") == 0) { + if (osVersion >= 10.1) { + JOptionPane.showMessageDialog(null, + message + "\n" + "To start Robocode, browse to " + installDir + " then double-click robocode.sh\n"); + } else { + JOptionPane.showMessageDialog(null, + message + "\n" + "To start Robocode, enter the following at a command prompt:\n" + + installDir.getAbsolutePath() + "/robocode.sh"); + } + } else { + JOptionPane.showMessageDialog(null, + message + "\n" + "To start Robocode, enter the following at a command prompt:\n" + + installDir.getAbsolutePath() + "/robocode.sh"); + } + } + + private boolean createWindowsShortcuts(File installDir, String runnable, String folder, String name) { + int rc = JOptionPane.showConfirmDialog(null, + "Would you like to install a shortcut to Robocode in the Start menu? (Recommended)", "Create Shortcuts", + JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + + if (rc != JOptionPane.YES_OPTION) { + return false; + } + + final String command = getWindowsCmd() + " cscript.exe "; + + try { + File shortcutMaker = new File(installDir, "makeshortcut.vbs"); + PrintStream out = new PrintStream(new FileOutputStream(shortcutMaker)); + + out.println("WScript.Echo(\"Creating shortcuts...\")"); + out.println("Set Shell = CreateObject (\"WScript.Shell\")"); + out.println("Set fso = CreateObject(\"Scripting.FileSystemObject\")"); + out.println("ProgramsPath = Shell.SpecialFolders(\"Programs\")"); + out.println("if (not(fso.folderExists(ProgramsPath + \"\\\\" + folder + "\"))) Then"); + out.println(" fso.CreateFolder(ProgramsPath + \"\\\\" + folder + "\")"); + out.println("End If"); + out.println("Set link = Shell.CreateShortcut(ProgramsPath + \"\\\\" + folder + "\\\\" + name + ".lnk\")"); + out.println("link.Arguments = \"\""); + out.println("link.Description = \"" + name + "\""); + out.println("link.HotKey = \"\""); + out.println("link.IconLocation = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + "robocode.ico,0\""); + out.println("link.TargetPath = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + runnable + "\""); + out.println("link.WindowStyle = 1"); + out.println("link.WorkingDirectory = \"" + escaped(installDir.getAbsolutePath()) + "\""); + out.println("link.Save()"); + out.println("DesktopPath = Shell.SpecialFolders(\"Desktop\")"); + out.println("Set link = Shell.CreateShortcut(DesktopPath + \"\\\\" + name + ".lnk\")"); + out.println("link.Arguments = \"\""); + out.println("link.Description = \"" + name + "\""); + out.println("link.HotKey = \"\""); + out.println("link.IconLocation = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + "robocode.ico,0\""); + out.println("link.TargetPath = \"" + escaped(installDir.getAbsolutePath()) + "\\\\" + runnable + "\""); + out.println("link.WindowStyle = 1"); + out.println("link.WorkingDirectory = \"" + escaped(installDir.getAbsolutePath()) + "\""); + out.println("link.Save()"); + out.println("WScript.Echo(\"Shortcuts created.\")"); + + out.close(); + + Process p = Runtime.getRuntime().exec(command + " makeshortcut.vbs", null, installDir); + int rv = p.waitFor(); + + if (rv != 0) { + System.err.println("Can't create shortcut: " + shortcutMaker); + return false; + } + JOptionPane.showMessageDialog(null, + message + "\n" + "A Robocode program group has been added to your Start menu\n" + + "A Robocode icon has been added to your desktop."); + if (!shortcutMaker.delete()) { + System.err.println("Can't delete: " + shortcutMaker); + } + return true; + } catch (IOException e) { + e.printStackTrace(System.err); + } catch (InterruptedException e) { + e.printStackTrace(System.err); + } + + return false; + } + + private void createFileAssociations(File installDir) { + if (isWindowsOS()) { + createWindowsFileAssociations(installDir); + } + } + + private void createWindowsFileAssociations(File installDir) { + int rc = JOptionPane.showConfirmDialog(null, + "Would you like to create file associations for Robocode in\n" + + "the Windows Registry for the file extensions .battle and .br?\n" + + "Please notice that you might need to grant permission to add\n" + + "the file associations in the Registry, and you must be an\n" + + "administrator or granted permission to change the registry.", + "Create File Associations", + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); + + if (rc != JOptionPane.YES_OPTION) { + return; + } + + File file = null; + PrintStream out = null; + + try { + file = new File(installDir + "\\FileAssoc.reg"); + + out = new PrintStream(new FileOutputStream(file)); + + String installPath = installDir.getAbsolutePath(); + + out.print( + createWindowsRegistryFileAssociation(installPath, ".battle", "Robocode.BattleSpecification", + "Robocode Battle Specification", "-battle")); + out.print( + createWindowsRegistryFileAssociation(installPath, ".br", "Robocode.BattleRecord", "Robocode Battle Record", + "-replay")); + + out.close(); + out = null; + + Process p = Runtime.getRuntime().exec(getWindowsCmd() + file.getAbsolutePath(), null, null); + int rv; + + try { + rv = p.waitFor(); + if (rv != 0) { + System.err.println("Could not create association(s)"); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (out != null) { + out.close(); + } + if (file != null) { + if (!file.delete()) { + System.err.println("Could not delete the file: " + file); + } + } + } + } + + private static String createWindowsRegistryFileAssociation(String installDir, String fileExt, String progId, String description, String robocodeCmdParam) { + StringBuffer sb = new StringBuffer(); + + final String HKCR = "[HKEY_CLASSES_ROOT\\"; + + sb.append("REGEDIT4\n"); + sb.append(HKCR).append(fileExt).append("]\n"); + sb.append("@=\"").append(progId).append("\"\n"); + sb.append(HKCR).append(progId).append("]\n"); + sb.append("@=\"").append(description).append("\"\n"); + sb.append(HKCR).append(progId).append("\\shell]\n"); + sb.append(HKCR).append(progId).append("\\shell\\open]\n"); + sb.append(HKCR).append(progId).append("\\shell\\open\\command]\n"); + sb.append("@=\"").append(getWindowsCmd()).append("\\\"cd \\\"").append(installDir.replaceAll("[\\\\]", "\\\\\\\\")).append("\\\" && robocode.bat ").append(robocodeCmdParam).append( + " \\\"%1\\\"\\\"\"\n"); + + return sb.toString(); + } + + private static String escaped(String s) { + StringBuffer eascaped = new StringBuffer(); + + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '\\') { + eascaped.append('\\'); + } + eascaped.append(s.charAt(i)); + } + return eascaped.toString(); + } + + private static boolean isWindowsOS() { + return osName.startsWith("Windows "); + } + + private static boolean isMacOSX() { + return osName.startsWith("Mac OS X"); + } + + private static boolean isFreeBSD() { + return osName.equals("FreeBSD"); + } + + private static String getWindowsCmd() { + String os = System.getProperty("os.name"); + + return ((os.equals("Windows 95") || os.equals("Windows 95") || os.equals("Windows ME")) + ? "command.com" + : "cmd.exe") + + " /C "; + } + + /** + * Deletes a file and afterwards deletes the parent directories that are empty. + * + * @param file the file or directory to delete + * @return true if success + */ + private static boolean deleteFileAndParentDirsIfEmpty(final File file) { + boolean wasDeleted = false; + + if (file != null && file.exists()) { + if (file.isDirectory()) { + wasDeleted = deleteDir(file); + } else { + wasDeleted = file.delete(); + + File parent = file; + + while (wasDeleted && (parent = parent.getParentFile()) != null) { + // Delete parent directory, but only if it is empty + File[] files = parent.listFiles(); + + if (files != null && files.length == 0) { + wasDeleted = deleteDir(parent); + } else { + wasDeleted = false; + } + } + } + } + return wasDeleted; + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/FileTransfer.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/FileTransfer.java new file mode 100644 index 0000000..09004c4 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/FileTransfer.java @@ -0,0 +1,657 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.roborumble.netengine; + + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.Properties; +import java.util.zip.GZIPInputStream; +import java.util.zip.InflaterInputStream; + +import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; + + +/** + * Utility class for downloading files from the net and copying files. + * + * @author Flemming N. Larsen (original) + */ +public class FileTransfer { + + private final static int DEFAULT_CONNECTION_TIMEOUT = 10000; // 10 seconds + private final static int DEFAULT_READ_TIMEOUT = 10000; // 10 seconds + private final static int DEFAULT_SESSION_TIMEOUT = 10000; // 10 seconds + + private static int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; + private static int readTimeout = DEFAULT_READ_TIMEOUT; + private static int sessionTimeout = DEFAULT_SESSION_TIMEOUT; + + static { + readProperties(); + } + + /** + * Represents the download status returned when downloading files. + */ + public enum DownloadStatus { + OK, // The download was succesful + COULD_NOT_CONNECT, // Connection problem + FILE_NOT_FOUND, // The file to download was not found + } + + + /** + * Daemon worker thread containing a 'finish' flag for waiting and notifying when the thread has finished it's job. + */ + private static class WorkerThread extends Thread { + + final Object monitor = new Object(); + + volatile boolean isFinished; + + public WorkerThread(String name) { + super(name); + setDaemon(true); + } + + void notifyFinish() { + // Notify that this thread is finish + synchronized (monitor) { + isFinished = true; + monitor.notifyAll(); + } + } + } + + /* + * Returns a session id for keeping a session on a HTTP site. + * + * @param url is the url of the HTTP site. + * + * @return a session id for keeping a session on a HTTP site or null if no session is available. + */ + public static String getSessionId(String url) { + HttpURLConnection conn = null; + + try { + // Open connection + conn = FileTransfer.connectToHttpInputConnection(new URL(url)); + if (conn == null) { + throw new IOException("Could not open connection to '" + url + "'"); + } + + // Get a session id if available + final GetSessionIdThread sessionIdThread = new GetSessionIdThread(conn); + + sessionIdThread.start(); + + // Wait for the session id + synchronized (sessionIdThread.monitor) { + while (!sessionIdThread.isFinished) { + try { + sessionIdThread.monitor.wait(sessionTimeout); + sessionIdThread.interrupt(); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + + return null; + } + } + } + + // Return the session id + return sessionIdThread.sessionId; + + } catch (final IOException e) { + return null; + } finally { + // Make sure the connection is disconnected. + // This will cause threads using the connection to throw an exception + // and thereby terminate if they were hanging. + if (conn != null) { + conn.disconnect(); + } + } + } + + /** + * Worker thread used for getting the session id of an already open HTTP connection. + */ + private final static class GetSessionIdThread extends WorkerThread { + + // The resulting session id to read out + String sessionId; + + final HttpURLConnection conn; + + GetSessionIdThread(HttpURLConnection conn) { + super("FileTransfer: Get session ID"); + this.conn = conn; + } + + @Override + public void run() { + try { + // Get the cookie value + final String cookieVal = conn.getHeaderField("Set-Cookie"); + + // Extract the session id from the cookie value + if (cookieVal != null) { + sessionId = cookieVal.substring(0, cookieVal.indexOf(";")); + } + } catch (final Exception e) { + sessionId = null; + } + // Notify that this thread is finish + notifyFinish(); + } + } + + /** + * Downloads a file from a HTTP site. + * + * @param url is the url of the HTTP site to download the file from. + * @param filename is the filename of the destination file. + * @param sessionId is an optional session id if the download is session based. + * @return the download status, which is DownloadStatus.OK if the download completed successfully; otherwise an + * error occurred. + */ + public static DownloadStatus download(String url, String filename, String sessionId) { + HttpURLConnection conn = null; + + try { + // Create connection + conn = connectToHttpInputConnection(new URL(url), sessionId); + if (conn == null) { + throw new IOException("Could not open connection to: " + url); + } + + // Begin the download + final DownloadThread downloadThread = new DownloadThread(conn, filename); + + downloadThread.start(); + + // Wait for the download to complete + synchronized (downloadThread.monitor) { + while (!downloadThread.isFinished) { + try { + downloadThread.monitor.wait(); + } catch (InterruptedException e) { + return DownloadStatus.COULD_NOT_CONNECT; + } + } + } + + // Return the download status + return downloadThread.status; + + } catch (final IOException e) { + return DownloadStatus.COULD_NOT_CONNECT; + } finally { + // Make sure the connection is disconnected. + // This will cause threads using the connection to throw an exception + // and thereby terminate if they were hanging. + try { + if (conn != null) { + conn.disconnect(); + } + } catch (RuntimeException ignore) {// we expect this, right ? + } + } + } + + /** + * Worker thread used for downloading a file from an already open HTTP connection. + */ + private final static class DownloadThread extends WorkerThread { + + // The download status to be read out + DownloadStatus status = DownloadStatus.COULD_NOT_CONNECT; // Default error + + final HttpURLConnection conn; + final String filename; + + InputStream in; + OutputStream out; + + DownloadThread(HttpURLConnection conn, String filename) { + super("FileTransfer: Download"); + this.conn = conn; + this.filename = filename; + } + + @Override + public void run() { + try { + // Start getting the response code + final GetResponseCodeThread responseThread = new GetResponseCodeThread(conn); + + responseThread.start(); + + // Wait for the response to finish + synchronized (responseThread.monitor) { + while (!responseThread.isFinished) { + try { + responseThread.monitor.wait(sessionTimeout); + responseThread.interrupt(); + } catch (InterruptedException e) { + notifyFinish(); + return; + } + } + } + + final int responseCode = responseThread.responseCode; + + if (responseCode == -1) { + // Terminate if we did not get the response code + notifyFinish(); + return; + + } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) { + // Terminate if the HTTP page containing the file was not found + status = DownloadStatus.FILE_NOT_FOUND; + notifyFinish(); + return; + + } else if (responseCode != HttpURLConnection.HTTP_OK) { + // Generally, terminate if did not receive a OK response + notifyFinish(); + return; + } + + // Start getting the size of the file to download + final GetContentLengthThread contentLengthThread = new GetContentLengthThread(conn); + + contentLengthThread.start(); + + // Wait for the file size + synchronized (contentLengthThread.monitor) { + while (!contentLengthThread.isFinished) { + try { + contentLengthThread.monitor.wait(sessionTimeout); + contentLengthThread.interrupt(); + } catch (InterruptedException e) { + notifyFinish(); + return; + } + } + } + + final int size = contentLengthThread.contentLength; + + if (size == -1) { + // Terminate if we did not get the content length + notifyFinish(); + return; + } + + // Get the input stream from the connection + in = getInputStream(conn); + + // Prepare the output stream for the file output + out = new FileOutputStream(filename); + + // Download the file + + final byte[] buf = new byte[4096]; + + int totalRead = 0; + int bytesRead; + + // Start thread for reading bytes into the buffer + + while (totalRead < size) { + // Start reading bytes into the buffer + final ReadInputStreamToBufferThread readThread = new ReadInputStreamToBufferThread(in, buf); + + readThread.start(); + + // Wait for the reading to finish + synchronized (readThread.monitor) { + while (!readThread.isFinished) { + try { + readThread.monitor.wait(sessionTimeout); + readThread.interrupt(); + } catch (InterruptedException e) { + notifyFinish(); + return; + } + } + } + + bytesRead = readThread.bytesRead; + if (bytesRead == -1) { + // Read completed has completed + notifyFinish(); + break; + } + + // Write the byte buffer to the output + out.write(buf, 0, bytesRead); + + totalRead += bytesRead; + } + + // If we reached this point, the download was successful + status = DownloadStatus.OK; + + notifyFinish(); + + } catch (final IOException e) { + status = DownloadStatus.COULD_NOT_CONNECT; + } finally { + // Make sure the input stream is closed + if (in != null) { + try { + in.close(); + } catch (final IOException e) { + e.printStackTrace(); + } + } + // Make sure the output stream is closed + if (out != null) { + try { + out.close(); + } catch (final IOException e) { + e.printStackTrace(); + } + } + } + } + } + + + /** + * Worker thread used for getting the response code of an already open HTTP connection. + */ + final static class GetResponseCodeThread extends WorkerThread { + + // The response code to read out + int responseCode; + + final HttpURLConnection conn; + + GetResponseCodeThread(HttpURLConnection conn) { + super("FileTransfer: Get response code"); + this.conn = conn; + } + + @Override + public void run() { + try { + // Get the response code + responseCode = conn.getResponseCode(); + } catch (final Exception e) { + responseCode = -1; + } + // Notify that this thread is finish + notifyFinish(); + } + } + + + /** + * Worker thread used for getting the content length of an already open HTTP connection. + */ + final static class GetContentLengthThread extends WorkerThread { + + // The content length to read out + int contentLength; + + final HttpURLConnection conn; + + GetContentLengthThread(HttpURLConnection conn) { + super("FileTransfer: Get content length"); + this.conn = conn; + } + + @Override + public void run() { + try { + // Get the content length + contentLength = conn.getContentLength(); + } catch (final Exception e) { + contentLength = -1; + } + // Notify that this thread is finish + notifyFinish(); + } + } + + + /** + * Worker thread used for reading bytes from an already open input stream into a byte buffer. + */ + final static class ReadInputStreamToBufferThread extends WorkerThread { + + int bytesRead; + + final InputStream in; + + final byte[] buf; + + ReadInputStreamToBufferThread(InputStream in, byte[] buf) { + super("FileTransfer: Read input stream to buffer"); + this.in = in; + this.buf = buf; + } + + @Override + public void run() { + try { + // Read bytes into the buffer + bytesRead = in.read(buf); + } catch (final Exception e) { + bytesRead = -1; + } + // Notify that this thread is finish + notifyFinish(); + } + } + + /** + * Copies a file into another file. + * + * @param srcFile is the filename of the source file to copy. + * @param destFile is the filename of the destination file to copy the file into. + * @return true if the file was copied; false otherwise + */ + public static boolean copy(String srcFile, String destFile) { + FileInputStream in = null; + FileOutputStream out = null; + + try { + if (srcFile.equals(destFile)) { + throw new IOException("You cannot copy a file onto itself"); + } + final byte[] buf = new byte[4096]; + + in = new FileInputStream(srcFile); + out = new FileOutputStream(destFile); + + while (in.available() > 0) { + out.write(buf, 0, in.read(buf, 0, buf.length)); + } + } catch (final IOException e) { + return false; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (out != null) { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return true; + } + + /** + * Opens and connects to a {@link java.net.HttpURLConnection} for input only, and where the connection timeout and + * read timeout are controlled by properties. + * + * @param url is the URL to open a connection to. + * @return a HttpURLConnection intended for reading input only. + * @throws IOException if an I/O exception occurs. + */ + public static HttpURLConnection connectToHttpInputConnection(URL url) throws IOException { + return connectToHttpInputConnection(url, null); + } + + /** + * Opens and connects to a {@link java.net.HttpURLConnection} for input only, and where the connection timeout and + * read timeout are controlled by properties. + * + * @param url is the URL to open a connection to. + * @param sessionId is a optional session id. + * @return a HttpURLConnection intended for reading input only. + * @throws IOException if an I/O exception occurs. + */ + public static HttpURLConnection connectToHttpInputConnection(URL url, String sessionId) throws IOException { + HttpURLConnection conn = (HttpURLConnection) openURLConnection(url, false); // not for output + + conn.setRequestMethod("GET"); + if (sessionId != null) { + conn.setRequestProperty("Cookie", sessionId); + } + conn.connect(); + return conn; + } + + /** + * Opens a {link {@link java.net.URLConnection} for output (and input) where the connection timeout and read timeout + * are controlled by properties. + * + * @param url is the URL to open. + * @return a URLConnection for output. + * @throws IOException if an I/O exception occurs. + */ + public static URLConnection openOutputURLConnection(URL url) throws IOException { + return openURLConnection(url, true); // for output + } + + /** + * Convenient method used for getting an input stream from an URLConnection. + * This method checks if a GZIPInputStream or InflaterInputStream should be used to wrap the input stream from the + * URLConnection depending on the content encoding. + * + * @param conn is the URLConnection + * @return an input stream from the URLConnection, which can be a GZIPInputStream or InflaterInputStream. + * @throws IOException if an I/O exception occurs. + */ + public static InputStream getInputStream(URLConnection conn) throws IOException { + // Get input stream + InputStream in = conn.getInputStream(); + + // Get the encoding returned by the server + String encoding = conn.getContentEncoding(); + + // Check if we need to use a gzip or inflater input stream depending on the content encoding + if ("gzip".equalsIgnoreCase(encoding)) { + in = new GZIPInputStream(in); + } else if ("deflate".equalsIgnoreCase(encoding)) { + in = new InflaterInputStream(in); + } + return in; + } + + /** + * Convenient method used for getting an output stream from an URLConnection. + * This method checks if a GZIPOutputStream or DeflaterOutputStream should be used to wrap the output stream from + * the URLConnection depending on the content encoding. + * + * @param conn is the URLConnection + * @return an output stream from the URLConnection, which can be a GZIPOutputStream or DeflaterOutputStream. + * @throws IOException if an I/O exception occurs. + */ + public static OutputStream getOutputStream(URLConnection conn) throws IOException { + // Get output stream + OutputStream out = conn.getOutputStream(); + + // // Get the encoding returned by the server + // String encoding = conn.getContentEncoding(); + // + // // Check if we need to use a gzip or inflater input stream depending on the content encoding + // if ("gzip".equalsIgnoreCase(encoding)) { + // out = new GZIPOutputStream(out); + // } else if ("deflate".equalsIgnoreCase(encoding)) { + // out = new DeflaterOutputStream(out); + // } + return out; + } + + /** + * Opens a {link {@link java.net.URLConnection} for input and optional output where the connection timeout and read + * timeout are controlled by properties. + * + * @param url is the URL to open. + * @param isOutput is a flag specifying if the opened connection is for output. + * @return a URLConnection. + * @throws IOException if an I/O exception occurs. + */ + public static URLConnection openURLConnection(URL url, boolean isOutput) throws IOException { + URLConnection conn = url.openConnection(); + + conn.setDoInput(true); + conn.setDoOutput(isOutput); + + conn.setConnectTimeout(connectionTimeout); + conn.setReadTimeout(readTimeout); + + if (!isOutput) { + // Allow both GZip and Deflate (ZLib) encodings + conn.setRequestProperty("Accept-Encoding", "gzip, deflate"); + conn.setRequestProperty("User-Agent", "RoboRumble@Home - gzip, deflate"); + } + return conn; + } + + /** + * Reads the roborumble.properties file and stores property values into global variables. + */ + private static void readProperties() { + Properties props = getProperties("./roborumble/roborumble.properties"); + + // Get connection timeout + String value = props.getProperty("connection.open.timeout"); + + if (value != null) { + try { + connectionTimeout = Integer.parseInt(value); + } catch (NumberFormatException ignore) {} + } + + // Get connection read timeout + value = props.getProperty("connection.read.timeout"); + if (value != null) { + try { + readTimeout = Integer.parseInt(value); + } catch (NumberFormatException ignore) {} + } + + // Get download session timeout + value = props.getProperty("download.session.timeout"); + if (value != null) { + try { + sessionTimeout = Integer.parseInt(value); + } catch (NumberFormatException ignore) {} + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/AwtAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/AwtAttack.java new file mode 100644 index 0000000..5722779 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/AwtAttack.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import robocode.ScannedRobotEvent; + +import javax.swing.*; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + + +/** + * @author Pavel Savara (original) + */ +public class AwtAttack extends AdvancedRobot { + + @Override + public void run() { + // noinspection InfiniteLoopStatement + for (;;) { + turnLeft(100); + ahead(10); + turnLeft(100); + back(10); + } + } + + @Override + public void onScannedRobot(ScannedRobotEvent event) { + awtAttack(); + } + + private void awtAttack() { + try { + Runnable doHack = new Runnable() { + public void run() { + writeAttack(); + + JFrame frame; + + frame = new JFrame(); + frame.setName("Hack"); + frame.setVisible(true); + + } + }; + + javax.swing.SwingUtilities.invokeLater(doHack); + } catch (RuntimeException e) { + // swalow security exception + e.printStackTrace(out); + } + } + + private void writeAttack() { + FileOutputStream fs; + + try { + fs = new FileOutputStream("C:\\Robocode.attack"); + fs.write(0xBA); + fs.write(0xDF); + fs.write(0x00); + fs.write(0xD0); + fs.close(); + out.println("Hacked!!!"); + } catch (FileNotFoundException e) { + e.printStackTrace(out); + } catch (IOException e) { + e.printStackTrace(out); + } catch (RuntimeException e) { + // swalow security exception + e.printStackTrace(out); + } + } + +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorAwtAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorAwtAttack.java new file mode 100644 index 0000000..47ae244 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorAwtAttack.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import javax.swing.*; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + + +/** + * @author Flemming N. Larsen (original) + */ +public class ConstructorAwtAttack extends robocode.AdvancedRobot { + + public ConstructorAwtAttack() { + awtAttack(); + } + + private void awtAttack() { + try { + Runnable doHack = new Runnable() { + public void run() { + writeAttack(); + + JFrame frame; + + frame = new JFrame(); + frame.setName("Hack"); + frame.setVisible(true); + + } + }; + + javax.swing.SwingUtilities.invokeLater(doHack); + } catch (RuntimeException e) { + // swallow security exception + e.printStackTrace(out); + } + } + + private void writeAttack() { + FileOutputStream fs; + + try { + fs = new FileOutputStream("C:\\Robocode.attack"); + fs.write(0xBA); + fs.write(0xDF); + fs.write(0x00); + fs.write(0xD0); + fs.close(); + out.println("Hacked!!!"); + } catch (FileNotFoundException e) { + e.printStackTrace(out); + } catch (IOException e) { + e.printStackTrace(out); + } catch (RuntimeException e) { + // swallow security exception + e.printStackTrace(out); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorThreadAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorThreadAttack.java new file mode 100644 index 0000000..0c5a0f8 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorThreadAttack.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +/** + * @author Flemming N. Larsen (original) + */ +public class ConstructorThreadAttack extends robocode.AdvancedRobot { + + public ConstructorThreadAttack() { + runAttack(); + runAttack2(); + } + + private void runAttack() { + try { + Attacker a = new Attacker(); + Thread t = new Thread(a); + + t.start(); + } catch (RuntimeException e) { + // swallow security exception + e.printStackTrace(out); + } + } + + private void runAttack2() { + try { + Attacker a = new Attacker(); + ThreadGroup tg = new ThreadGroup("MyAttack"); + + tg.setMaxPriority(10); + Thread t = new Thread(tg, a); + + t.start(); + } catch (RuntimeException e) { + // swallow security exception + e.printStackTrace(out); + } + } + + private class Attacker implements Runnable { + + public synchronized void run() { + if (Thread.currentThread().getPriority() > 4) { + out.println("Priority attack"); + } + runAttack2(); + + try { + this.wait(); + } catch (InterruptedException e) {} + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileAttack.java new file mode 100644 index 0000000..9f76ccf --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileAttack.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import robocode.ScannedRobotEvent; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + + +/** + * @author Pavel Savara (original) + */ +public class FileAttack extends AdvancedRobot { + + @Override + public void run() { + // noinspection InfiniteLoopStatement + for (;;) { + turnLeft(100); + ahead(10); + turnLeft(100); + back(10); + } + } + + @Override + public void onScannedRobot(ScannedRobotEvent event) { + readAttack(); + writeAttack(); + } + + private void readAttack() { + try { + FileInputStream fs = new FileInputStream("C:\\MSDOS.SYS"); + + System.out.print(fs.read()); + System.out.print(fs.read()); + System.out.print(fs.read()); + System.out.print(fs.read()); + fs.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(out); + } catch (IOException e) { + e.printStackTrace(out); + } catch (RuntimeException e) { + // swalow security exception + e.printStackTrace(out); + } + } + + private void writeAttack() { + FileOutputStream fs; + + try { + fs = new FileOutputStream("C:\\Robocode.attack"); + fs.write(0xBA); + fs.write(0xDF); + fs.write(0x00); + fs.write(0xD0); + fs.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(out); + } catch (IOException e) { + e.printStackTrace(out); + } catch (RuntimeException e) { + // swalow security exception + e.printStackTrace(out); + } + } + +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/IncludeNamespaceAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/IncludeNamespaceAttack.java new file mode 100644 index 0000000..c5ecdb9 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/IncludeNamespaceAttack.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import net.sf.robocode.security.HiddenAccess; +import robocode.AdvancedRobot; +import robocode.ScannedRobotEvent; + + +/** + * @author Pavel Savara (original) + */ +public class IncludeNamespaceAttack extends AdvancedRobot { + + @Override + public void run() { + // noinspection InfiniteLoopStatement + for (;;) { + turnLeft(100); + ahead(10); + turnLeft(100); + back(10); + } + } + + @Override + public void onScannedRobot(ScannedRobotEvent event) { + namespaceAttack(); + } + + private void namespaceAttack() { + try { + HiddenAccess.createRules(10, 10, 10, 10, 1, false, 100); + } catch (RuntimeException e) { + // Swallow security exception + e.printStackTrace(out); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadAttack.java new file mode 100644 index 0000000..bb21f8c --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadAttack.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import robocode.ScannedRobotEvent; + +import java.util.concurrent.atomic.AtomicInteger; + + +/** + * @author Pavel Savara (original) + */ +public class ThreadAttack extends AdvancedRobot { + + @Override + public void run() { + // noinspection InfiniteLoopStatement + for (;;) { + turnLeft(100); + ahead(10); + turnLeft(100); + back(10); + } + } + + @Override + public void onScannedRobot(ScannedRobotEvent event) { + runAttack(); + runAttack2(); + } + + private void runAttack() { + try { + Attacker a = new Attacker(); + Thread t = new Thread(a); + + t.start(); + } catch (RuntimeException e) { + // swallow security exception + e.printStackTrace(out); + } + } + + private void runAttack2() { + try { + Attacker a = new Attacker(); + ThreadGroup tg = new ThreadGroup("MyAttack"); + + tg.setMaxPriority(10); + Thread t = new Thread(tg, a); + + t.start(); + } catch (RuntimeException e) { + // swallow security exception + e.printStackTrace(out); + } + } + + private AtomicInteger counter = new AtomicInteger(); + + private class Attacker implements Runnable { + + public synchronized void run() { + final int id = counter.incrementAndGet(); + + out.println("Running id:" + id); + + if (Thread.currentThread().getPriority() > 4) { + out.println("Priority attack"); + } + runAttack2(); + + try { + this.wait(); + } catch (InterruptedException e) { + out.println("Interrupted id:" + id); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadGroupAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadGroupAttack.java new file mode 100644 index 0000000..963b549 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ThreadGroupAttack.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.*; + + +/** + * This nasty robot tries to interrupt the thread of each opponent robot that it scans. + * It enumerates the threads recursively of thread group that is a parent of its own + * thread group to find out, which threads that are active. These threads are all robot + * threads. + * + * This robot is inspired by the hacker.Destroyer 1.3, which proved a security breach in + * Robocode 1.7.2.1 Beta. The security breach was reported with: + * Bug [3021140] Possible for robot to kill other robot threads. + * + * The security manager of Robocode must make sure that unsafe (robot) threads cannot + * access thread groups other than its own thread group within checkAccess(Thread). + * + * @author Flemming N. Larsen (original) + */ +public class ThreadGroupAttack extends Robot { + private Thread[] threads = new Thread[100]; + + public void run() { + runAttack(); + + while (true) { + turnGunLeft(30); + } + } + + private void runAttack() { + try { + new Thread(new Runnable() { + public void run() { + ThreadGroup parentGroup = Thread.currentThread().getThreadGroup().getParent(); + + while (true) { + parentGroup.enumerate(threads, true); + try { + Thread.sleep(0); + } catch (InterruptedException ignore) {} + } + } + }).start(); + } catch (RuntimeException t) { + t.printStackTrace(out); + } + } + + public void onScannedRobot(ScannedRobotEvent e) { + attackRobotThread(e.getName()); + } + + private void attackRobotThread(String robotName) { + for (Thread t : threads) { + if (t != null && robotName.equals(t.getName())) { + t.interrupt(); + out.println("Interrupted: " + robotName); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/UndeadThread.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/UndeadThread.java new file mode 100644 index 0000000..75fcbfa --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/UndeadThread.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; + + +/** + * @author Pavel Savara (original) + */ +public class UndeadThread extends AdvancedRobot { + + @Override + public void run() { + out.println("I will live forever!"); + // noinspection InfiniteLoopStatement + while (true) { + try { + body(); + } catch (RuntimeException t) { + // spamming the console + out.println("Swalowed it, HA HA HA HA HAAAAA !!!!!"); + out.println(t); + } + } + } + + private void body() { + // noinspection InfiniteLoopStatement + for (;;) { + turnLeft(100); + ahead(10); + turnLeft(100); + back(10); + } + } + +} diff --git a/代码/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/Assert.java b/代码/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/Assert.java new file mode 100644 index 0000000..27c29dd --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/Assert.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.helpers; + + +import robocode.util.Utils; + + +/** + * @author Pavel Savara (original) + */ +public class Assert extends org.junit.Assert { + public static void assertNear(double v1, double v2) { + org.junit.Assert.assertEquals(v1, v2, Utils.NEAR_DELTA); + } + + public static void allAssertNear(double v1, double v2) { + try { + assertNear(v1, v2); + } catch (RuntimeException ex) { + ex.printStackTrace(System.err); + } + } + + public static void allAssertThat(T t, org.hamcrest.Matcher tMatcher) { + try { + org.junit.Assert.assertThat(t, tMatcher); + } catch (RuntimeException ex) { + ex.printStackTrace(System.err); + } + } + +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditWindow.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditWindow.java new file mode 100644 index 0000000..a0f8e9b --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditWindow.java @@ -0,0 +1,485 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.IRepositoryManager; +import net.sf.robocode.ui.editor.theme.EditorThemeProperties; +import net.sf.robocode.ui.editor.theme.EditorThemePropertiesManager; +import net.sf.robocode.ui.editor.theme.EditorThemePropertyChangeAdapter; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.event.InternalFrameAdapter; +import javax.swing.event.InternalFrameEvent; +import javax.swing.filechooser.FileFilter; + +import java.awt.Font; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.StringTokenizer; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Matthew Reeder (contributor) + */ +@SuppressWarnings("serial") +public class EditWindow extends JInternalFrame { + + private String fileName; + private String robotName; + public boolean modified; + private final RobocodeEditor editor; + private final IRepositoryManager repositoryManager; + private final File robotsDirectory; + private EditorPanel editorPanel; + private EditorPane editorPane; + + public EditWindow(IRepositoryManager repositoryManager, RobocodeEditor editor, File robotsDirectory) { + super("Edit Window", true, true, true, true); + this.editor = editor; + this.robotsDirectory = robotsDirectory; + this.repositoryManager = repositoryManager; + initialize(); + } + + public EditorPane getEditorPane() { + if (editorPane == null) { + editorPane = editorPanel.getEditorPane(); + InputMap im = editorPane.getInputMap(); + + // FIXME: Replace hack with better solution than using 'ctrl H' + im.put(KeyStroke.getKeyStroke("ctrl H"), editor.getReplaceAction()); + } + return editorPane; + } + + public String getFileName() { + return fileName; + } + + public String getRobotName() { + return robotName; + } + + private void initialize() { + try { + addInternalFrameListener(new InternalFrameAdapter() { + @Override + public void internalFrameClosing(InternalFrameEvent e) { + if (!modified || fileSave(true)) { + editor.setLineStatus(-1); + dispose(); + } + editor.removeFromWindowMenu(EditWindow.this); + } + + @Override + public void internalFrameDeactivated(InternalFrameEvent e) { + editor.setLineStatus(-1); + } + + @Override + public void internalFrameIconified(InternalFrameEvent e) { + editor.setLineStatus(-1); + } + }); + setFrameIcon(new ImageIcon(EditWindow.class.getResource("/net/sf/robocode/ui/icons/robocode-icon.png"))); + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + + setSize(750, 500); + + editor.addToWindowMenu(this); + + editorPanel = new EditorPanel(); + setContentPane(editorPanel); + + EditorThemeProperties currentThemeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + Font font = currentThemeProps.getFont(); + editorPanel.setFont(font); + + // Make sure the source editor window gets focus with a blinking cursor + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + editorPanel.getEditorPane().requestFocus(); + } + }); + + EditorThemePropertiesManager.addListener(new EditorThemePropertyChangeAdapter() { + @Override + public void onFontChanged(Font newFont) { + editorPanel.setFont(newFont); + } + }); + + final JavaDocument document = (JavaDocument) editorPanel.getEditorPane().getDocument(); + + document.addDocumentListener(new DocumentListener() { + public void removeUpdate(DocumentEvent e) { + updateModificationState(); + } + + public void insertUpdate(DocumentEvent e) { + updateModificationState(); + } + + public void changedUpdate(DocumentEvent e) { + updateModificationState(); + } + + // Bug-361 Problem in the text editor related with the .java file modification + private void updateModificationState() { + setModified(editorPanel.getEditorPane().isModified()); + } + }); + } catch (RuntimeException e) { + Logger.logError(e); + } + } + + public void setFileName(String newFileName) { + fileName = newFileName; + updateTitle(); + } + + public void setRobotName(String newRobotName) { + robotName = newRobotName; + updateTitle(); + } + + private void updateTitle() { + StringBuffer titleBuf = new StringBuffer("Editing"); + if (fileName != null) { + titleBuf.append(" - ").append(fileName); + } else if (robotName != null) { + titleBuf.append(" - ").append(robotName); + } + if (modified) { + titleBuf.append(" *"); + } + setTitle(titleBuf.toString()); + } + + private void setModified(boolean modified) { + boolean updated = (modified != this.modified); + if (updated) { + this.modified = modified; + updateTitle(); + editor.setSaveFileMenuItemsEnabled(modified); + } + } + + public void compile() { + if (!fileSave(true, true)) { + error("You must save before compiling."); + return; + } + if (editor.getCompiler() != null) { + // The compiler + refresh of the repository is done in a thread in order to avoid the compiler + // window hanging while compiling. The SwingUtilities.invokeLater() does not do a good job here + // (window is still hanging). Hence, a real thread running beside the EDT is used, which does a + // great job, where each each new print from the compiler is written out as soon as it is ready + // in the output stream. + new Thread(new Runnable() { + public void run() { + if (fileName == null) { + error("You must save before compiling."); + return; + } + editor.getCompiler().compile(getRobotDir(), fileName); + repositoryManager.refresh(fileName); + } + }).start(); + } else { + JOptionPane.showMessageDialog(editor, "No compiler installed.", "Error", JOptionPane.ERROR_MESSAGE); + } + } + + private void error(String msg) { + Object[] options = { + "OK" + }; + + JOptionPane.showOptionDialog(this, msg, "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, + options, options[0]); + } + + public boolean fileSave(boolean confirm) { + return fileSave(confirm, false); + } + + private boolean fileSave(boolean confirm, boolean mustSave) { + if (confirm) { + if (!modified) { + return true; + } + String s = fileName; + + if (s == null) { + s = robotName; + } + if (s == null) { + s = "This file"; + } + int ok = JOptionPane.showConfirmDialog(this, s + " has been modified. Do you wish to save it?", + "Modified file", JOptionPane.YES_NO_CANCEL_OPTION); + + if (ok == JOptionPane.NO_OPTION) { + return !mustSave; + } + if (ok == JOptionPane.CANCEL_OPTION) { + return false; + } + } + String fileName = getFileName(); + + if (fileName == null) { + return fileSaveAs(); + } + + String reasonableFilename = getReasonableFilename(); + + if (reasonableFilename != null) { + try { + String a = new File(reasonableFilename).getCanonicalPath(); + String b = new File(fileName).getCanonicalPath(); + + if (!a.equals(b)) { + int ok = JOptionPane.showConfirmDialog(this, + fileName + " should be saved in: \n" + reasonableFilename + + "\n Would you like to save it there instead?", + "Name has changed", + JOptionPane.YES_NO_CANCEL_OPTION); + + if (ok == JOptionPane.CANCEL_OPTION) { + return false; + } + if (ok == JOptionPane.YES_OPTION) { + return fileSaveAs(); + } + } + } catch (IOException e) { + Logger.logError("Unable to check reasonable filename: ", e); + } + } + + BufferedWriter bufferedWriter = null; + OutputStreamWriter outputStreamWriter = null; + FileOutputStream fileOutputStream = null; + + try { + fileOutputStream = new FileOutputStream(fileName); + outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF8"); + bufferedWriter = new BufferedWriter(outputStreamWriter); + + getEditorPane().write(bufferedWriter); + setModified(false); + } catch (IOException e) { + error("Cannot write file: " + e); + return false; + } finally { + FileUtil.cleanupStream(bufferedWriter); + } + return true; + } + + private String getRobotDir() { + String saveDir = robotsDirectory.getPath() + File.separatorChar; + + String text = getEditorPane().getText(); + int pIndex = text.indexOf("package "); + + if (pIndex >= 0) { + int pEIndex = text.indexOf(";", pIndex); + + if (pEIndex > 0) { + String packageTree = text.substring(pIndex + 8, pEIndex) + File.separatorChar; + + packageTree = packageTree.replace('.', File.separatorChar); + + saveDir += packageTree; + } + } + return saveDir; + } + + public boolean fileSaveAs() { + String javaFileName = null; + String saveDir = getRobotDir(); + + String text = getEditorPane().getText(); + + int pIndex = text.indexOf("public class "); + + if (pIndex >= 0) { + int pEIndex = text.indexOf(" ", pIndex + 13); + + if (pEIndex > 0) { + int pEIndex2 = text.indexOf("\n", pIndex + 13); + + if (pEIndex2 > 0 && pEIndex2 < pEIndex) { + pEIndex = pEIndex2; + } + javaFileName = text.substring(pIndex + 13, pEIndex).trim() + ".java"; + } else { + pEIndex = text.indexOf("\n", pIndex + 13); + if (pEIndex > 0) { + javaFileName = text.substring(pIndex + 13, pEIndex).trim() + ".java"; + } + } + } + + File f = new File(saveDir); + + if (!f.exists()) { + int ok = JOptionPane.showConfirmDialog(this, + "Your robot should be saved in the directory: " + saveDir + + "\nThis directory does not exist, would you like to create it?", + "Create Directory", + JOptionPane.YES_NO_CANCEL_OPTION); + + if (ok == JOptionPane.YES_OPTION) { + if (!f.exists() && !f.mkdirs()) { + Logger.logError("Cannot create: " + f); + } + f = new File(saveDir); + } + if (ok == JOptionPane.CANCEL_OPTION) { + return false; + } + } + + JFileChooser chooser; + + chooser = new JFileChooser(f); + chooser.setCurrentDirectory(f); + + FileFilter filter = new FileFilter() { + @Override + public boolean accept(File pathname) { + if (pathname.isDirectory()) { + return true; + } + String fn = pathname.getName(); + int idx = fn.lastIndexOf('.'); + String extension = ""; + + if (idx >= 0) { + extension = fn.substring(idx); + } + return extension.equalsIgnoreCase(".java"); + } + + @Override + public String getDescription() { + return "Robots"; + } + }; + + chooser.setFileFilter(filter); + + boolean done = false; + + while (!done) { + done = true; + if (javaFileName != null) { + chooser.setSelectedFile(new File(f, javaFileName)); + } + int rv = chooser.showSaveDialog(this); + String robotFileName; + + if (rv == JFileChooser.APPROVE_OPTION) { + robotFileName = chooser.getSelectedFile().getPath(); + File outFile = new File(robotFileName); + + if (outFile.exists()) { + int ok = JOptionPane.showConfirmDialog(this, + robotFileName + " already exists. Are you sure you want to replace it?", "Warning", + JOptionPane.YES_NO_CANCEL_OPTION); + + if (ok == JOptionPane.NO_OPTION) { + done = false; + continue; + } + if (ok == JOptionPane.CANCEL_OPTION) { + return false; + } + } + setFileName(robotFileName); + fileSave(false); + } else { + return false; + } + } + + return true; + } + + public String getPackage() { + String text = getEditorPane().getText(); + int pIndex = text.indexOf("package "); + + if (pIndex >= 0) { + int pEIndex = text.indexOf(";", pIndex); + + if (pEIndex > 0) { + return text.substring(pIndex + 8, pEIndex); + } + } + return ""; + } + + private String getReasonableFilename() { + StringBuffer fileName = new StringBuffer(robotsDirectory.getPath()).append(File.separatorChar); + String javaFileName; + String packageTree = null; + + String text = getEditorPane().getText(); + StringTokenizer tokenizer = new StringTokenizer(text, " \t\r\n;"); + String token; + boolean inComment = false; + + while (tokenizer.hasMoreTokens()) { + token = tokenizer.nextToken(); + if (!inComment && (token.equals("/*") || token.equals("/**"))) { + inComment = true; + } + if (inComment && (token.equals("*/") || token.equals("**/"))) { + inComment = false; + } + if (inComment) { + continue; + } + + if (packageTree == null && token.equals("package")) { + packageTree = tokenizer.nextToken(); + if (packageTree == null || packageTree.length() == 0) { + return null; + } + packageTree = packageTree.replace('.', File.separatorChar); + packageTree += File.separator; + fileName.append(packageTree); + } + if (token.equals("class")) { + javaFileName = tokenizer.nextToken() + ".java"; + fileName.append(javaFileName); + return fileName.toString(); + } + } + return null; + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/WindowMenuItem.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/WindowMenuItem.java new file mode 100644 index 0000000..bda1627 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/WindowMenuItem.java @@ -0,0 +1,291 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.io.File; + + +/** + * Customized JMenuItem where each item is bound to a specific JInternalFrame, + * so we can have a dynamic menu of open windows. + * + * @author Matthew Reeder (original) + */ +@SuppressWarnings("serial") +public class WindowMenuItem extends JCheckBoxMenuItem implements ActionListener { + + // Maximum number of windows that will be shown on the menu (to get the rest, you'll + // have to open the dialog). The number 9 is also the number of most recently used + // files that normally show up in other applications. The reason is so that you can + // give them dynamic hotkeys from 1 to 9. Otherwise, there's no reason (besides + // avoiding taking up way too much space) to limit the size of the menu. + public static final int WINDOW_MENU_MAX_SIZE = 9; + // Number of static menu items before the dynamic menu (including seperators) + public static final int PRECEDING_WINDOW_MENU_ITEMS = 3; + // Number of static menu items after the dynamic menu (including seperators + // and the More Windows... menu item) + public static final int SUBSEQUENT_WINDOW_MENU_ITEMS = 1; + // Normal max length of a window name + public static final int MAX_WINDOW_NAME_LENGTH = 30; + // I make one "special" menu item that isn't tied to a window. Since it has + // similar needs for enabling/visibility and labeling, I made it the same class. + public static final int REGULAR_WINDOW = 0, SPECIAL_MORE = 2; + private EditWindow window; + private JMenu parentMenu; + private final int type; + + public WindowMenuItem(EditWindow window, JMenu parentMenu) { + super(); + this.window = window; + this.parentMenu = parentMenu; + type = REGULAR_WINDOW; + parentMenu.add(this, parentMenu.getMenuComponentCount() - SUBSEQUENT_WINDOW_MENU_ITEMS); + addActionListener(this); + } + + /** + * WindowMenuItem Constructor for "More Windows..." menu. + */ + public WindowMenuItem() { + type = SPECIAL_MORE; + } + + /** + * Event handler for the menu item + *

+ * Brings the window to the front. This should be called for the "More + * Windows..." Item, because it doesn't make itself its own ActionListener. + *

+ * Note that e can be null, and this menu item might not be showing (if this + * is called from the "More Windows" dialog). + */ + public void actionPerformed(ActionEvent e) { + if (window.isIcon()) { + try { + window.setIcon(false); + } catch (RuntimeException ignored) {} + } + if (window.getDesktopPane() != null) { + window.getDesktopPane().setSelectedFrame(window); + } + window.toFront(); + window.grabFocus(); + try { + window.setSelected(true); + } catch (RuntimeException ignored) {} + } + + /** + * Returns the label that should be used. If the menu item is supposed to be + * hidden, this may not be a real valid label. + */ + @Override + public String getText() { + if (type == SPECIAL_MORE) { + Container parent = getParent(); + + if (parent == null) { + return ""; + } + + int numWindows = parent.getComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; + + if (numWindows <= 0) { + return "No Windows Open"; + } + + return "More Windows..."; + } + if (window == null || parentMenu == null) { + return ""; + } + String text = (getIndex() + 1) + " " + getFileName(); + + if (window.modified) { + text += " *"; + } + return text; + } + + protected String getFileName() { + if (window.getFileName() == null) { + return "Untitled " + (getPrecedingNewFiles() + 1); + } + + String name = window.getFileName(); + + if (name.length() < MAX_WINDOW_NAME_LENGTH) { + return name; + } + if (name.indexOf(File.separatorChar) < 0) { + return name; + } // If there are no separators, I can't really intelligently truncate. + int startLength = name.indexOf(File.separatorChar, 1) + 1; + int endLength = name.length() - name.lastIndexOf(File.separatorChar); + + if (endLength + startLength + 3 > name.length()) { + return name; + } // return name anyways, since we're not getting it any shorter. + + boolean change; + + do { + change = false; + int newEndLength = name.length() - name.lastIndexOf(File.separatorChar, name.length() - endLength - 1); + + if (newEndLength + startLength + 3 <= MAX_WINDOW_NAME_LENGTH) { + endLength = newEndLength; + change = true; + } + int newStartLength = name.indexOf(File.separatorChar, startLength + 1) + 1; + + if (endLength + startLength + 3 <= MAX_WINDOW_NAME_LENGTH) { + startLength = newStartLength; + change = true; + } + } while (change); + + return name.substring(0, startLength) + "..." + name.substring(name.length() - endLength); + } + + /** + * @return how many nameless windows occur before this one in the parent. + */ + protected int getPrecedingNewFiles() { + int count = 0; + + for (int i = 0; i < WINDOW_MENU_MAX_SIZE + && i < parentMenu.getMenuComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS + && parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS) != this; i++) { + if (parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS) instanceof WindowMenuItem + && ((WindowMenuItem) parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS)).window.getFileName() + == null) { + count++; + } + } + return count; + } + + /** + * Figures out what index (from 0 to WINDOW_MENU_MAX_SIZE-1) this item is in + * the window menu. + *

+ * @return -1 if this item isn't showing. + */ + protected int getIndex() { + for (int i = 0; i < WINDOW_MENU_MAX_SIZE + && i < parentMenu.getMenuComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; i++) { + if (this == parentMenu.getMenuComponent(i + PRECEDING_WINDOW_MENU_ITEMS)) { + return i; + } + } + return -1; + } + + /** + * Returns the index of the character in the label that should be underlined + */ + @Override + public int getDisplayedMnemonicIndex() { + return (type == SPECIAL_MORE) ? 11 : 0; + } + + /** + * Returns the keyboard mnemonic for this item, which is the virtual key + * code for its 1-based index. + */ + @Override + public int getMnemonic() { + return (type == SPECIAL_MORE) ? KeyEvent.VK_S : KeyEvent.VK_1 + getIndex(); + } + + /** + * Returns true if this item should be showing. + *

+ * Returns false if there are more than WINDOW_MENU_MAX_SIZE items before it + * in the menu. + */ + @Override + public boolean isVisible() { + if (type == SPECIAL_MORE) { + Container parent = getParent(); + + if (parent == null) { + return true; + } + int numWindows = parent.getComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; + + updateSelection(); + return (numWindows <= 0) || (numWindows > WINDOW_MENU_MAX_SIZE); + } + updateSelection(); + return getIndex() >= 0; + } + + /** + * Returns true if this item should be enabled (selectable). + *

+ * Returns false if it is a More Windows... item and there are no windows. + */ + @Override + public boolean isEnabled() { + if (type == SPECIAL_MORE) { + Container parent = getParent(); + + if (parent == null) { + return true; + } + int numWindows = parent.getComponentCount() - PRECEDING_WINDOW_MENU_ITEMS - SUBSEQUENT_WINDOW_MENU_ITEMS; + + return (numWindows > 0); + } + return true; + } + + /** + * Determines if this menu item should currently show as "selected". + *

+ * The item should be seleced if the window it's tied to has focus. + */ + @Override + public boolean isSelected() { + return (type != SPECIAL_MORE) && (window != null && window.getDesktopPane() != null) + && window.getDesktopPane().getSelectedFrame() == window; + } + + /** + * Makes sure the underlying menu item knows if we're selected. + */ + public void updateSelection() { + setSelected(isSelected()); // Sort of a silly thing to do... + setEnabled(isEnabled()); + } + + /** + * @return the EditWindow that this menu item is tied to. + */ + public EditWindow getEditWindow() { + return window; + } + + /** + * Creates a string representation of this object. + *

+ * Handy for repurposing the menu items as list items :-) + */ + @Override + public String toString() { + return (type == SPECIAL_MORE) ? "" : getFileName(); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/WindowManager.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/WindowManager.java new file mode 100644 index 0000000..bbdae95 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/WindowManager.java @@ -0,0 +1,632 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import net.sf.robocode.battle.BattleProperties; +import net.sf.robocode.battle.BattleResultsTableModel; +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.core.Container; +import net.sf.robocode.host.ICpuManager; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.repository.IRepositoryManager; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.battle.AwtBattleAdaptor; +import net.sf.robocode.ui.dialog.*; +import net.sf.robocode.ui.packager.RobotPackager; +import net.sf.robocode.ui.editor.IRobocodeEditor; +import net.sf.robocode.version.IVersionManager; +import robocode.control.events.BattleCompletedEvent; +import robocode.control.events.IBattleListener; +import robocode.control.snapshot.ITurnSnapshot; + +import javax.swing.*; +import javax.swing.filechooser.FileFilter; +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.util.Locale; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Luis Crespo (contributor) + */ +public class WindowManager implements IWindowManagerExt { + + private final static int TIMER_TICKS_PER_SECOND = 50; + private final AwtBattleAdaptor awtAdaptor; + private RobotPackager robotPackager; + private RobotExtractor robotExtractor; + private final ISettingsManager settingsManager; + private final IBattleManager battleManager; + private final ICpuManager cpuManager; + private final IRepositoryManager repositoryManager; + private final IVersionManager versionManager; + private final IImageManager imageManager; + private IRobotDialogManager robotDialogManager; + private RobocodeFrame robocodeFrame; + + private boolean isGUIEnabled = true; + private boolean isSlave; + private boolean centerRankings = true; + private boolean oldRankingHideState = true; + private boolean showResults = true; + + public WindowManager(ISettingsManager settingsManager, IBattleManager battleManager, ICpuManager cpuManager, IRepositoryManager repositoryManager, IImageManager imageManager, IVersionManager versionManager) { + this.settingsManager = settingsManager; + this.battleManager = battleManager; + this.repositoryManager = repositoryManager; + this.cpuManager = cpuManager; + this.versionManager = versionManager; + this.imageManager = imageManager; + awtAdaptor = new AwtBattleAdaptor(battleManager, TIMER_TICKS_PER_SECOND, true); + + // we will set UI better priority than robots and battle have + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + Thread.currentThread().setPriority(Thread.NORM_PRIORITY + 2); + } catch (SecurityException ex) {// that's a pity + } + } + }); + } + + public void setBusyPointer(boolean enabled) { + robocodeFrame.setBusyPointer(enabled); + } + + public synchronized void addBattleListener(IBattleListener listener) { + awtAdaptor.addListener(listener); + } + + public synchronized void removeBattleListener(IBattleListener listener) { + awtAdaptor.removeListener(listener); + } + + public boolean isGUIEnabled() { + return isGUIEnabled; + } + + public void setEnableGUI(boolean enable) { + isGUIEnabled = enable; + + // Set the system property so the AWT headless mode. + // Read more about headless mode here: + // http://java.sun.com/developer/technicalArticles/J2SE/Desktop/headless/ + System.setProperty("java.awt.headless", "" + !enable); + } + + public void setSlave(boolean value) { + isSlave = value; + } + + public boolean isSlave() { + return isSlave; + } + + public boolean isIconified() { + return robocodeFrame.isIconified(); + } + + public boolean isShowResultsEnabled() { + return settingsManager.getOptionsCommonShowResults() && showResults; + } + + public void setEnableShowResults(boolean enable) { + showResults = enable; + } + + public ITurnSnapshot getLastSnapshot() { + return awtAdaptor.getLastSnapshot(); + } + + public int getFPS() { + return isIconified() ? 0 : awtAdaptor.getFPS(); + } + + public RobocodeFrame getRobocodeFrame() { + if (robocodeFrame == null) { + this.robocodeFrame = Container.getComponent(RobocodeFrame.class); + } + return robocodeFrame; + } + + public void showRobocodeFrame(boolean visible, boolean iconified) { + RobocodeFrame frame = getRobocodeFrame(); + + if (iconified) { + frame.setState(Frame.ICONIFIED); + } + + if (visible) { + // Pack frame to size all components + WindowUtil.packCenterShow(frame); + + WindowUtil.setStatusLabel(frame.getStatusLabel()); + + frame.checkUpdateOnStart(); + + } else { + frame.setVisible(false); + } + } + + public void showAboutBox() { + packCenterShow(Container.getComponent(AboutBox.class), true); + } + + public String showBattleOpenDialog(final String defExt, final String name) { + JFileChooser chooser = new JFileChooser(battleManager.getBattlePath()); + + chooser.setFileFilter( + new FileFilter() { + @Override + public boolean accept(File pathname) { + return pathname.isDirectory() + || pathname.getName().toLowerCase().lastIndexOf(defExt.toLowerCase()) + == pathname.getName().length() - defExt.length(); + } + + @Override + public String getDescription() { + return name; + } + }); + + if (chooser.showOpenDialog(getRobocodeFrame()) == JFileChooser.APPROVE_OPTION) { + return chooser.getSelectedFile().getPath(); + } + return null; + } + + public String saveBattleDialog(String path, final String defExt, final String name) { + File f = new File(path); + + JFileChooser chooser; + + chooser = new JFileChooser(f); + + javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() { + @Override + public boolean accept(File pathname) { + return pathname.isDirectory() + || pathname.getName().toLowerCase().lastIndexOf(defExt.toLowerCase()) + == pathname.getName().length() - defExt.length(); + } + + @Override + public String getDescription() { + return name; + } + }; + + chooser.setFileFilter(filter); + int rv = chooser.showSaveDialog(getRobocodeFrame()); + String result = null; + + if (rv == JFileChooser.APPROVE_OPTION) { + result = chooser.getSelectedFile().getPath(); + int idx = result.lastIndexOf('.'); + String extension = ""; + + if (idx > 0) { + extension = result.substring(idx); + } + if (!(extension.equalsIgnoreCase(defExt))) { + result += defExt; + } + } + return result; + } + + public void showVersionsTxt() { + showInBrowser("file://" + new File(FileUtil.getCwd(), "").getAbsoluteFile() + File.separator + "versions.md"); + } + + public void showHelpApi() { + showInBrowser( + "file://" + new File(FileUtil.getCwd(), "").getAbsoluteFile() + File.separator + "javadoc" + File.separator + + "index.html"); + } + + public void showReadMe() { + showInBrowser("file://" + new File(FileUtil.getCwd(), "ReadMe.html").getAbsoluteFile()); + } + + public void showFaq() { + showInBrowser("http://robowiki.net/w/index.php?title=Robocode/FAQ"); + } + + public void showOnlineHelp() { + showInBrowser("http://robowiki.net/w/index.php?title=Robocode/Getting_Started"); + } + + public void showJavaDocumentation() { + showInBrowser("http://docs.oracle.com/javase/6/docs/api/"); + } + + public void showRobocodeHome() { + showInBrowser("http://robocode.sourceforge.net"); + } + + public void showRoboWiki() { + showInBrowser("http://robowiki.net"); + } + + public void showGoogleGroupRobocode() { + showInBrowser("https://groups.google.com/forum/?fromgroups#!forum/robocode"); + } + + public void showRobocodeRepository() { + showInBrowser("http://robocoderepository.com"); + } + + public void showOptionsPreferences() { + try { + battleManager.pauseBattle(); + + WindowUtil.packCenterShow(getRobocodeFrame(), Container.getComponent(PreferencesDialog.class)); + } finally { + battleManager.resumeIfPausedBattle(); // THIS is just dirty hack-fix of more complex problem with desiredTPS and pausing. resumeBattle() belongs here. + } + } + + public void showResultsDialog(BattleCompletedEvent event) { + final ResultsDialog dialog = Container.getComponent(ResultsDialog.class); + + dialog.setup(event.getSortedResults(), event.getBattleRules().getNumRounds()); + packCenterShow(dialog, true); + } + + public void showRankingDialog(boolean visible) { + boolean currentRankingHideState = settingsManager.getOptionsCommonDontHideRankings(); + + // Check if the Ranking hide states has changed + if (currentRankingHideState != oldRankingHideState) { + // Remove current visible RankingDialog, if it is there + Container.getComponent(RankingDialog.class).dispose(); + + // Replace old RankingDialog, as the owner window must be replaced from the constructor + Container.cache.removeComponent(RankingDialog.class); + Container.cache.addComponent(RankingDialog.class); + + // Reset flag for centering the dialog the first time it is shown + centerRankings = true; + } + + RankingDialog rankingDialog = Container.getComponent(RankingDialog.class); + + if (visible) { + packCenterShow(rankingDialog, centerRankings); + centerRankings = false; // only center the first time Rankings are shown + } else { + rankingDialog.dispose(); + } + + // Save current Ranking hide state + oldRankingHideState = currentRankingHideState; + } + + public void showRobocodeEditor() { + JFrame editor = (JFrame) net.sf.robocode.core.Container.getComponent(IRobocodeEditor.class); + + if (!editor.isVisible()) { + WindowUtil.packCenterShow(editor); + } else { + editor.setVisible(true); + } + } + + public void showRobotPackager() { + if (robotPackager != null) { + robotPackager.dispose(); + robotPackager = null; + } + + robotPackager = net.sf.robocode.core.Container.factory.getComponent(RobotPackager.class); + WindowUtil.packCenterShow(robotPackager); + } + + public void showRobotExtractor(JFrame owner) { + if (robotExtractor != null) { + robotExtractor.dispose(); + robotExtractor = null; + } + + robotExtractor = new net.sf.robocode.ui.dialog.RobotExtractor(owner, this, repositoryManager); + WindowUtil.packCenterShow(robotExtractor); + } + + public void showSplashScreen() { + RcSplashScreen splashScreen = Container.getComponent(RcSplashScreen.class); + + packCenterShow(splashScreen, true); + + WindowUtil.setStatusLabel(splashScreen.getSplashLabel()); + + repositoryManager.reload(versionManager.isLastRunVersionChanged()); + + WindowUtil.setStatusLabel(splashScreen.getSplashLabel()); + cpuManager.getCpuConstant(); + + WindowUtil.setStatus(""); + WindowUtil.setStatusLabel(null); + + splashScreen.dispose(); + } + + public void showNewBattleDialog(BattleProperties battleProperties) { + try { + battleManager.pauseBattle(); + final NewBattleDialog battleDialog = Container.createComponent(NewBattleDialog.class); + + battleDialog.setup(settingsManager, battleProperties); + WindowUtil.packCenterShow(getRobocodeFrame(), battleDialog); + } finally { + battleManager.resumeBattle(); + } + } + + public boolean closeRobocodeEditor() { + IRobocodeEditor editor = net.sf.robocode.core.Container.getComponent(IRobocodeEditor.class); + + return editor == null || !((JFrame) editor).isVisible() || editor.close(); + } + + public void showCreateTeamDialog() { + TeamCreator teamCreator = Container.getComponent(TeamCreator.class); + + WindowUtil.packCenterShow(teamCreator); + } + + public void showImportRobotDialog() { + JFileChooser chooser = new JFileChooser(); + + chooser.setFileFilter(new FileFilter() { + @Override + public boolean accept(File pathname) { + if (pathname.isHidden()) { + return false; + } + if (pathname.isDirectory()) { + return true; + } + String filename = pathname.getName(); + + if (filename.equals("robocode.jar")) { + return false; + } + int idx = filename.lastIndexOf('.'); + + String extension = ""; + + if (idx >= 0) { + extension = filename.substring(idx); + } + return extension.equalsIgnoreCase(".jar") || extension.equalsIgnoreCase(".zip"); + } + + @Override + public String getDescription() { + return "Jar Files"; + } + }); + + chooser.setDialogTitle("Select the robot .jar file to copy to " + repositoryManager.getRobotsDirectory()); + + if (chooser.showDialog(getRobocodeFrame(), "Import") == JFileChooser.APPROVE_OPTION) { + File inputFile = chooser.getSelectedFile(); + String fileName = inputFile.getName(); + String extension = ""; + + int idx = fileName.lastIndexOf('.'); + + if (idx >= 0) { + extension = fileName.substring(idx); + } + if (!extension.equalsIgnoreCase(".jar")) { + fileName += ".jar"; + } + File outputFile = new File(repositoryManager.getRobotsDirectory(), fileName); + + if (inputFile.equals(outputFile)) { + JOptionPane.showMessageDialog(getRobocodeFrame(), + outputFile.getName() + " is already in the robots directory!"); + return; + } + if (outputFile.exists()) { + if (JOptionPane.showConfirmDialog(getRobocodeFrame(), outputFile + " already exists. Overwrite?", + "Warning", JOptionPane.YES_NO_OPTION) + == JOptionPane.NO_OPTION) { + return; + } + } + if (JOptionPane.showConfirmDialog(getRobocodeFrame(), + "Robocode will now copy " + inputFile.getName() + " to " + outputFile.getParent(), "Import robot", + JOptionPane.OK_CANCEL_OPTION) + == JOptionPane.OK_OPTION) { + try { + FileUtil.copy(inputFile, outputFile); + repositoryManager.refresh(); + JOptionPane.showMessageDialog(getRobocodeFrame(), "Robot imported successfully."); + } catch (IOException e) { + JOptionPane.showMessageDialog(getRobocodeFrame(), "Import failed: " + e); + } + } + } + } + + /** + * Shows a web page using the browser manager. + * + * @param url The URL of the web page + */ + private void showInBrowser(String url) { + try { + BrowserManager.openURL(url); + } catch (IOException e) { + JOptionPane.showMessageDialog(getRobocodeFrame(), e.getMessage(), "Unable to open browser!", + JOptionPane.ERROR_MESSAGE); + } + } + + public void showSaveResultsDialog(BattleResultsTableModel tableModel) { + JFileChooser chooser = new JFileChooser(); + + chooser.setFileFilter(new FileFilter() { + + @Override + public boolean accept(File pathname) { + if (pathname.isHidden()) { + return false; + } + if (pathname.isDirectory()) { + return true; + } + String filename = pathname.getName(); + int idx = filename.lastIndexOf('.'); + + String extension = ""; + + if (idx >= 0) { + extension = filename.substring(idx); + } + return extension.equalsIgnoreCase(".csv"); + } + + @Override + public String getDescription() { + return "Comma Separated Value (CSV) File Format"; + } + }); + + chooser.setDialogTitle("Save battle results"); + + if (chooser.showSaveDialog(getRobocodeFrame()) == JFileChooser.APPROVE_OPTION) { + + String filename = chooser.getSelectedFile().getPath(); + + if (!filename.endsWith(".csv")) { + filename += ".csv"; + } + + boolean append = settingsManager.getOptionsCommonAppendWhenSavingResults(); + + tableModel.saveToFile(filename, append); + } + } + + /** + * Packs, centers, and shows the specified window on the screen. + * @param window the window to pack, center, and show + * @param center {@code true} if the window must be centered; {@code false} otherwise + */ + private void packCenterShow(Window window, boolean center) { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + window.pack(); + if (center) { + window.setLocation((screenSize.width - window.getWidth()) / 2, (screenSize.height - window.getHeight()) / 2); + } + window.setVisible(true); + } + + public void cleanup() { + if (isGUIEnabled()) { + getRobocodeFrame().dispose(); + } + } + + public void setStatus(String s) { + WindowUtil.setStatus(s); + } + + public void messageWarning(String s) { + WindowUtil.messageWarning(s); + } + + public IRobotDialogManager getRobotDialogManager() { + if (robotDialogManager == null) { + robotDialogManager = new RobotDialogManager(); + } + return robotDialogManager; + } + + public void init() { + setLookAndFeel(); + imageManager.initialize(); // Make sure this one is initialized so all images are available + awtAdaptor.subscribe(isGUIEnabled); + } + + /** + * Sets the Look and Feel (LAF). This method first try to set the LAF to the + * system's LAF. If this fails, it try to use the cross platform LAF. + * If this also fails, the LAF will not be changed. + */ + private void setLookAndFeel() { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (RuntimeException t) { + // Work-around for problems with setting Look and Feel described here: + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6468089 + Locale.setDefault(Locale.US); + + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (RuntimeException t2) { + // For some reason Ubuntu 7 can cause a NullPointerException when trying to getting the LAF + System.err.println("Could not set the Look and Feel (LAF). The default LAF is used instead"); + } + } + // Java 1.6 provide system specific anti-aliasing. Enable it, if it has not been set + if (new Double(System.getProperty("java.specification.version")) >= 1.6) { + String aaFontSettings = System.getProperty("awt.useSystemAAFontSettings"); + + if (aaFontSettings == null) { + System.setProperty("awt.useSystemAAFontSettings", "on"); + } + } + } + + public void runIntroBattle() { + final File intro = new File(FileUtil.getCwd(), "battles/intro.battle"); + if (intro.exists()) { + battleManager.setBattleFilename(intro.getPath()); + battleManager.loadBattleProperties(); + + final boolean origShowResults = showResults; // save flag for showing the results + + showResults = false; + try { + battleManager.startNewBattle(battleManager.loadBattleProperties(), true, false); + battleManager.setDefaultBattleProperties(); + robocodeFrame.afterIntroBattle(); + } finally { + showResults = origShowResults; // always restore the original flag for showing the results + } + } + } + + public void setVisibleForRobotEngine(boolean visible) { + if (visible && !isGUIEnabled()) { + // The GUI must be enabled in order to show the window + setEnableGUI(true); + + // Set the Look and Feel (LAF) + init(); + } + + if (isGUIEnabled()) { + showRobocodeFrame(visible, false); + showResults = visible; + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battle/AwtBattleAdaptor.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battle/AwtBattleAdaptor.java new file mode 100644 index 0000000..11436ae --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battle/AwtBattleAdaptor.java @@ -0,0 +1,335 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.battle; + + +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.battle.events.BattleEventDispatcher; +import net.sf.robocode.battle.snapshot.RobotSnapshot; +import net.sf.robocode.io.Logger; +import robocode.control.events.*; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicInteger; + + +/** + * @author Pavel Savara (original) + */ +public final class AwtBattleAdaptor { + private boolean isEnabled; + private final IBattleManager battleManager; + private final BattleEventDispatcher battleEventDispatcher = new BattleEventDispatcher(); + private final BattleObserver observer; + private final Timer timerTask; + + private final AtomicReference snapshot; + private final AtomicBoolean isRunning; + private final AtomicBoolean isPaused; + private final AtomicInteger majorEvent; + private final AtomicInteger lastMajorEvent; + private ITurnSnapshot lastSnapshot; + private StringBuilder[] outCache; + + public AwtBattleAdaptor(IBattleManager battleManager, int maxFps, boolean skipSameFrames) { + this.battleManager = battleManager; + snapshot = new AtomicReference(null); + + this.skipSameFrames = skipSameFrames; + timerTask = new Timer(1000 / maxFps, new TimerTask()); + isRunning = new AtomicBoolean(false); + isPaused = new AtomicBoolean(false); + majorEvent = new AtomicInteger(0); + lastMajorEvent = new AtomicInteger(0); + + observer = new BattleObserver(); + } + + protected void finalize() throws Throwable { + try { + timerTask.stop(); + battleManager.removeListener(observer); + } finally { + super.finalize(); + } + } + + public void subscribe(boolean isEnabled) { + if (this.isEnabled && !isEnabled) { + battleManager.removeListener(observer); + timerTask.stop(); + isEnabled = false; + } else if (!this.isEnabled && isEnabled) { + battleManager.addListener(observer); + isEnabled = true; + } + } + + public synchronized void addListener(IBattleListener listener) { + battleEventDispatcher.addListener(listener); + } + + public synchronized void removeListener(IBattleListener listener) { + battleEventDispatcher.removeListener(listener); + } + + public ITurnSnapshot getLastSnapshot() { + return lastSnapshot; + } + + // this is always dispatched on AWT thread + private void awtOnTurnEnded(boolean forceRepaint, boolean readoutText) { + try { + ITurnSnapshot current = snapshot.get(); + + if (current == null) { // !isRunning.get() || + // paint logo + lastSnapshot = null; + battleEventDispatcher.onTurnEnded(new TurnEndedEvent(null)); + } else { + if (lastSnapshot != current || !skipSameFrames || forceRepaint) { + lastSnapshot = current; + + IRobotSnapshot[] robots = null; + + if (readoutText) { + synchronized (snapshot) { + robots = lastSnapshot.getRobots(); + + for (int i = 0; i < robots.length; i++) { + RobotSnapshot robot = (RobotSnapshot) robots[i]; + + final StringBuilder cache = outCache[i]; + + if (cache.length() > 0) { + robot.setOutputStreamSnapshot(cache.toString()); + outCache[i].setLength(0); + } + } + } + } + + battleEventDispatcher.onTurnEnded(new TurnEndedEvent(lastSnapshot)); + + if (readoutText) { + for (IRobotSnapshot robot : robots) { + ((RobotSnapshot) robot).setOutputStreamSnapshot(null); + } + } + + calculateFPS(); + } + } + } catch (RuntimeException t) { + Logger.logError(t); + } + } + + public int getFPS() { + return fps; + } + + // FPS (frames per second) calculation + private int fps; + private long measuredFrameCounter; + private long measuredFrameStartTime; + private final boolean skipSameFrames; + + private void calculateFPS() { + // Calculate the current frames per second (FPS) + + if (measuredFrameCounter++ == 0) { + measuredFrameStartTime = System.nanoTime(); + } + + long deltaTime = System.nanoTime() - measuredFrameStartTime; + + if (deltaTime / 1000000000 >= 1) { + fps = (int) (measuredFrameCounter * 1000000000L / deltaTime); + measuredFrameCounter = 0; + } + } + + private class TimerTask implements ActionListener { + public void actionPerformed(ActionEvent e) { + awtOnTurnEnded(false, true); + } + } + + + // BattleObserver methods are always called by battle thread + // but everything inside invokeLater {} block in on AWT thread + private class BattleObserver extends BattleAdaptor { + + @Override + public void onTurnEnded(final TurnEndedEvent event) { + if (lastMajorEvent.get() == majorEvent.get()) { + // snapshot is updated out of order, but always within the same major event + snapshot.set(event.getTurnSnapshot()); + } + + final IRobotSnapshot[] robots = event.getTurnSnapshot().getRobots(); + + for (int i = 0; i < robots.length; i++) { + RobotSnapshot robot = (RobotSnapshot) robots[i]; + final int r = i; + final String text = robot.getOutputStreamSnapshot(); + + if (text != null && text.length() != 0) { + robot.setOutputStreamSnapshot(null); + EventQueue.invokeLater(new Runnable() { + public void run() { + synchronized (snapshot) { + outCache[r].append(text); + } + } + }); + } + } + if (isPaused.get()) { + EventQueue.invokeLater(new Runnable() { + public void run() { + awtOnTurnEnded(false, true); + } + }); + } + } + + @Override + public void onRoundStarted(final RoundStartedEvent event) { + if (lastMajorEvent.get() == majorEvent.get()) { + snapshot.set(event.getStartSnapshot()); + } + majorEvent.incrementAndGet(); + EventQueue.invokeLater(new Runnable() { + public void run() { + awtOnTurnEnded(true, false); + battleEventDispatcher.onRoundStarted(event); + lastMajorEvent.incrementAndGet(); + } + }); + } + + @Override + public void onBattleStarted(final BattleStartedEvent event) { + majorEvent.incrementAndGet(); + EventQueue.invokeLater(new Runnable() { + public void run() { + isRunning.set(true); + isPaused.set(false); + synchronized (snapshot) { + outCache = new StringBuilder[event.getRobotsCount()]; + for (int i = 0; i < event.getRobotsCount(); i++) { + outCache[i] = new StringBuilder(1024); + } + } + snapshot.set(null); + battleEventDispatcher.onBattleStarted(event); + lastMajorEvent.incrementAndGet(); + awtOnTurnEnded(true, false); + timerTask.start(); + } + }); + } + + @Override + public void onBattleFinished(final BattleFinishedEvent event) { + majorEvent.incrementAndGet(); + EventQueue.invokeLater(new Runnable() { + public void run() { + isRunning.set(false); + isPaused.set(false); + timerTask.stop(); + // flush text cache + awtOnTurnEnded(true, true); + + battleEventDispatcher.onBattleFinished(event); + lastMajorEvent.incrementAndGet(); + snapshot.set(null); + + // paint logo + awtOnTurnEnded(true, true); + } + }); + } + + @Override + public void onBattleCompleted(final BattleCompletedEvent event) { + majorEvent.incrementAndGet(); + EventQueue.invokeLater(new Runnable() { + public void run() { + battleEventDispatcher.onBattleCompleted(event); + lastMajorEvent.incrementAndGet(); + awtOnTurnEnded(true, true); + } + }); + } + + @Override + public void onRoundEnded(final RoundEndedEvent event) { + majorEvent.incrementAndGet(); + EventQueue.invokeLater(new Runnable() { + public void run() { + battleEventDispatcher.onRoundEnded(event); + lastMajorEvent.incrementAndGet(); + awtOnTurnEnded(true, true); + } + }); + } + + @Override + public void onBattlePaused(final BattlePausedEvent event) { + EventQueue.invokeLater(new Runnable() { + public void run() { + timerTask.stop(); + battleEventDispatcher.onBattlePaused(event); + awtOnTurnEnded(true, true); + isPaused.set(true); + } + }); + } + + @Override + public void onBattleResumed(final BattleResumedEvent event) { + EventQueue.invokeLater(new Runnable() { + public void run() { + battleEventDispatcher.onBattleResumed(event); + if (isRunning.get()) { + timerTask.start(); + isPaused.set(false); + } + } + }); + } + + @Override + public void onBattleMessage(final BattleMessageEvent event) { + EventQueue.invokeLater(new Runnable() { + public void run() { + battleEventDispatcher.onBattleMessage(event); + } + }); + } + + @Override + public void onBattleError(final BattleErrorEvent event) { + EventQueue.invokeLater(new Runnable() { + public void run() { + battleEventDispatcher.onBattleError(event); + } + }); + } + } +} From 0679bddf0bad3a5566c45543cd1ec92bd924cb88 Mon Sep 17 00:00:00 2001 From: zhoudaxia <1018795633@qq.cin> Date: Thu, 25 Aug 2016 10:33:02 +0800 Subject: [PATCH 5/5] lmy --- 代码/workspace_robo4/.gitignore | 11 + 代码/workspace_robo4/README.md | 12 + .../RemoteSystemsTempFiles/.project | 12 + 代码/workspace_robo4/jacobe.cmd | 17 + 代码/workspace_robo4/jacobe.sh | 24 + 代码/workspace_robo4/mvn.cmd | 15 + 代码/workspace_robo4/mvn.sh | 16 + 代码/workspace_robo4/mvnassembly.cmd | 12 + 代码/workspace_robo4/mvnassembly.sh | 11 + 代码/workspace_robo4/plugins/.project | 11 + .../workspace_robo4/plugins/dotnet/ReadMe.txt | 88 + .../plugins/dotnet/generateProxies.cmd | 41 + 代码/workspace_robo4/plugins/dotnet/mvn.cmd | 20 + .../plugins/dotnet/mvnassembly.cmd | 12 + 代码/workspace_robo4/plugins/dotnet/pom.xml | 62 + .../plugins/dotnet/robocode.dotnet.api/.project | 8 + .../.settings/org.eclipse.jdt.core.prefs | 10 + .../plugins/dotnet/robocode.dotnet.api/pom.xml | 52 + .../robocode.dotnet.api/robocode.dotnet.api.iml | 66 + .../robocode.dotnet.api/robotAPI.shfbproj | 87 + .../dotnet/robocode.dotnet.api/src/.gitignore | 3 + .../robocode.dotnet.api/src/AssemblyInf.cs | 12 + .../src/net/sf/robocode/io/LoggerN.cs | 132 + .../src/net/sf/robocode/nio/Buffer.cs | 508 +++ .../src/net/sf/robocode/nio/ByteBuffer.cs | 1604 +++++++++ .../src/net/sf/robocode/nio/HeapByteBuffer.cs | 380 ++ .../net/sf/robocode/nio/InvalidMarkException.cs | 116 + .../src/net/sf/robocode/peer/IRobotStaticsN.cs | 23 + .../net/sf/robocode/security/HiddenAccessN.cs | 131 + .../sf/robocode/security/IHiddenBulletHelper.cs | 20 + .../sf/robocode/security/IHiddenEventHelper.cs | 29 + .../sf/robocode/security/IHiddenRandomHelper.cs | 20 + .../sf/robocode/security/IHiddenRulesHelper.cs | 21 + .../sf/robocode/security/IHiddenStatusHelper.cs | 25 + .../security/RobocodeInternalPermission.cs | 151 + .../serialization/ISerializableHelperN.cs | 22 + .../sf/robocode/serialization/RbSerializerN.cs | 524 +++ .../src/robocode.dotnet.api.csproj | 164 + .../src/robocode/AdvancedRobot.cs | 2226 ++++++++++++ .../src/robocode/BattleEndedEvent.cs | 126 + .../src/robocode/BattleResults.cs | 225 ++ .../src/robocode/BattleRules.cs | 137 + .../robocode.dotnet.api/src/robocode/Bullet.cs | 217 ++ .../src/robocode/BulletHitBulletEvent.cs | 116 + .../src/robocode/BulletHitEvent.cs | 128 + .../src/robocode/BulletMissedEvent.cs | 102 + .../src/robocode/Condition.cs | 155 + .../src/robocode/CustomEvent.cs | 123 + .../src/robocode/DeathEvent.cs | 78 + .../robocode.dotnet.api/src/robocode/Event.cs | 279 ++ .../src/robocode/GunTurnCompleteCondition.cs | 52 + .../src/robocode/HitByBulletEvent.cs | 177 + .../src/robocode/HitRobotEvent.cs | 172 + .../src/robocode/HitWallEvent.cs | 103 + .../src/robocode/IBorderSentry.cs | 32 + .../robocode.dotnet.api/src/robocode/IDroid.cs | 23 + .../src/robocode/IGraphics.cs | 160 + .../src/robocode/JuniorRobot.cs | 1324 +++++++ .../src/robocode/KeyEvent.cs | 78 + .../src/robocode/KeyPressedEvent.cs | 96 + .../src/robocode/KeyReleasedEvent.cs | 98 + .../src/robocode/KeyTypedEvent.cs | 98 + .../robocode.dotnet.api/src/robocode/Keys.cs | 292 ++ .../src/robocode/MessageEvent.cs | 77 + .../src/robocode/MouseClickedEvent.cs | 103 + .../src/robocode/MouseDraggedEvent.cs | 103 + .../src/robocode/MouseEnteredEvent.cs | 104 + .../src/robocode/MouseEvent.cs | 91 + .../src/robocode/MouseExitedEvent.cs | 103 + .../src/robocode/MouseMovedEvent.cs | 104 + .../src/robocode/MousePressedEvent.cs | 105 + .../src/robocode/MouseReleasedEvent.cs | 104 + .../src/robocode/MouseWheelMovedEvent.cs | 134 + .../src/robocode/MoveCompleteCondition.cs | 52 + .../src/robocode/PaintEvent.cs | 50 + .../src/robocode/RadarTurnCompleteCondition.cs | 52 + .../src/robocode/RateControlRobot.cs | 364 ++ .../robocode.dotnet.api/src/robocode/Robot.cs | 1927 +++++++++++ .../src/robocode/RobotDeathEvent.cs | 95 + .../src/robocode/RobotStatus.cs | 401 +++ .../src/robocode/RoundEndedEvent.cs | 134 + .../robocode.dotnet.api/src/robocode/Rules.cs | 214 ++ .../src/robocode/ScannedRobotEvent.cs | 238 ++ .../src/robocode/SkippedTurnEvent.cs | 125 + .../src/robocode/StatusEvent.cs | 66 + .../src/robocode/TeamRobot.cs | 193 ++ .../robocode.dotnet.api/src/robocode/Thread.cs | 134 + .../src/robocode/TurnCompleteCondition.cs | 52 + .../src/robocode/WinEvent.cs | 80 + .../exception/EventInterruptedException.cs | 48 + .../src/robocode/exception/RobotException.cs | 45 + .../robocode/robotinterfaces/IAdvancedEvents.cs | 52 + .../robocode/robotinterfaces/IAdvancedRobot.cs | 32 + .../robocode/robotinterfaces/IBasicEvents.cs | 270 ++ .../robocode/robotinterfaces/IBasicEvents2.cs | 38 + .../robocode/robotinterfaces/IBasicEvents3.cs | 40 + .../src/robocode/robotinterfaces/IBasicRobot.cs | 59 + .../robotinterfaces/IInteractiveEvents.cs | 183 + .../robotinterfaces/IInteractiveRobot.cs | 36 + .../robocode/robotinterfaces/IJuniorRobot.cs | 38 + .../robocode/robotinterfaces/IPaintEvents.cs | 42 + .../src/robocode/robotinterfaces/IPaintRobot.cs | 24 + .../src/robocode/robotinterfaces/IRunnable.cs | 22 + .../src/robocode/robotinterfaces/ITeamEvents.cs | 38 + .../src/robocode/robotinterfaces/ITeamRobot.cs | 33 + .../robotinterfaces/peer/IAdvancedRobotPeer.cs | 659 ++++ .../robotinterfaces/peer/IBasicRobotPeer.cs | 698 ++++ .../robotinterfaces/peer/IJuniorRobotPeer.cs | 65 + .../robotinterfaces/peer/IStandardRobotPeer.cs | 248 ++ .../robotinterfaces/peer/ITeamRobotPeer.cs | 129 + .../src/robocode/util/Utils.cs | 206 ++ .../dotnet/robocode.dotnet.content/.classpath | 13 + .../dotnet/robocode.dotnet.content/.project | 19 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../dotnet/robocode.dotnet.content/pom.xml | 33 + .../robocode.dotnet.content.iml | 147 + .../src/main/resources/libs/control/.gitignore | 3 + .../libs/control/BattleRunnnerSample.csproj | 69 + .../libs/control/BattleRunnnerSample.sln | 20 + .../src/main/resources/libs/control/Program.cs | 82 + .../src/main/resources/robocode.bat | 9 + .../src/main/resources/robots/SamplesCs.csproj | 89 + .../dotnet/robocode.dotnet.control.api/.project | 10 + .../.settings/org.eclipse.jdt.core.prefs | 10 + .../Content Layout.content | 4 + .../Introduction.aml | 113 + .../controlAPI.shfbproj | 81 + .../dotnet/robocode.dotnet.control.api/pom.xml | 66 + .../robocode.dotnet.control.api.iml | 74 + .../robocode.dotnet.control.api/src/.gitignore | 3 + .../src/generated/java/util/Random.generated.cs | 172 + .../control/BattleSpecification.generated.cs | 207 ++ .../BattlefieldSpecification.generated.cs | 95 + .../robocode/control/RandomFactory.generated.cs | 105 + .../control/RobocodeEngine.generated.cs | 296 ++ .../robocode/control/RobotResults.generated.cs | 95 + .../robocode/control/RobotSetup.generated.cs | 94 + .../control/RobotSpecification.generated.cs | 159 + .../events/BattleCompletedEvent.generated.cs | 94 + .../events/BattleErrorEvent.generated.cs | 72 + .../control/events/BattleEvent.generated.cs | 49 + .../events/BattleFinishedEvent.generated.cs | 72 + .../events/BattleMessageEvent.generated.cs | 72 + .../events/BattlePausedEvent.generated.cs | 61 + .../events/BattleResumedEvent.generated.cs | 61 + .../events/BattleStartedEvent.generated.cs | 94 + .../control/events/IBattleListener.generated.cs | 331 ++ .../control/events/RoundEndedEvent.generated.cs | 94 + .../events/RoundStartedEvent.generated.cs | 83 + .../control/events/TurnEndedEvent.generated.cs | 72 + .../events/TurnStartedEvent.generated.cs | 61 + .../control/snapshot/BulletState.generated.cs | 195 ++ .../snapshot/IBulletSnapshot.generated.cs | 431 +++ .../snapshot/IDebugProperty.generated.cs | 119 + .../snapshot/IRobotSnapshot.generated.cs | 795 +++++ .../snapshot/IScoreSnapshot.generated.cs | 558 +++ .../control/snapshot/ITurnSnapshot.generated.cs | 249 ++ .../control/snapshot/RobotState.generated.cs | 189 + .../src/glue/robocode/control/RandomFactory.cs | 76 + .../src/glue/robocode/control/RobocodeEngine.cs | 29 + .../robocode/control/BattleSpecification.cs | 257 ++ .../control/BattlefieldSpecification.cs | 77 + .../robocode/control/IRobocodeEngine.cs | 237 ++ .../robocode/control/RobocodeEngine.cs | 1682 +++++++++ .../robocode/control/RobotSetup.cs | 70 + .../robocode/control/RobotSpecification.cs | 148 + .../control/events/BattleCompletedEvent.cs | 86 + .../robocode/control/events/BattleErrorEvent.cs | 44 + .../robocode/control/events/BattleEvent.cs | 22 + .../control/events/BattleFinishedEvent.cs | 47 + .../control/events/BattleMessageEvent.cs | 44 + .../control/events/BattlePausedEvent.cs | 24 + .../control/events/BattleResumedEvent.cs | 24 + .../control/events/BattleStartedEvent.cs | 71 + .../robocode/control/events/RoundEndedEvent.cs | 72 + .../control/events/RoundStartedEvent.cs | 58 + .../robocode/control/events/TurnEndedEvent.cs | 45 + .../robocode/control/events/TurnStartedEvent.cs | 24 + .../robocode/control/snapshot/BulletState.cs | 58 + .../control/snapshot/IBulletSnapshot.cs | 123 + .../robocode/control/snapshot/IDebugProperty.cs | 37 + .../robocode/control/snapshot/IRobotSnapshot.cs | 248 ++ .../robocode/control/snapshot/IScoreSnapshot.cs | 165 + .../robocode/control/snapshot/ITurnSnapshot.cs | 81 + .../robocode/control/snapshot/RobotState.cs | 41 + .../src/robocode.dotnet.control.api.csproj | 200 ++ .../src/robocode.ico | Bin 0 -> 25214 bytes .../robocode.dotnet.distribution/.classpath | 14 + .../robocode.dotnet.distribution/.project | 22 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../dotnet-setup.asm.xml | 119 + .../dotnet/robocode.dotnet.distribution/pom.xml | 76 + .../robocode.dotnet.distribution.iml | 149 + .../dotnet/robocode.dotnet.host/.classpath | 16 + .../dotnet/robocode.dotnet.host/.project | 18 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../plugins/dotnet/robocode.dotnet.host/pom.xml | 164 + .../robocode.dotnet.host.iml | 169 + .../src/main/java/java_/util/Random_.java | 33 + .../net/sf/robocode/core/ContainerBase_.java | 33 + .../net/sf/robocode/dotnet/host/DotNetHost.java | 58 + .../net/sf/robocode/dotnet/nhost/ModuleN.java | 49 + .../repository/items/DotNetRobotItem.java | 30 + .../items/handlers/DotNetPropertiesHandler.java | 57 + .../dotnet/repository/root/DllRoot.java | 120 + .../dotnet/repository/root/DllRootHelper.java | 56 + .../repository/root/handlers/DllHandler.java | 62 + .../net/sf/robocode/host/IHostManager_.java | 73 + .../main/java/net/sf/robocode/host/IHost_.java | 52 + .../net/sf/robocode/host/RobotStatics_.java | 34 + .../host/proxies/IHostingRobotProxy_.java | 55 + .../main/java/net/sf/robocode/io/Logger_.java | 33 + .../robocode/manager/IVersionManagerBase_.java | 55 + .../java/net/sf/robocode/peer/BadBehavior_.java | 33 + .../java/net/sf/robocode/peer/IRobotPeer_.java | 73 + .../net/sf/robocode/peer/IRobotStatics_.java | 55 + .../net/sf/robocode/repository/IRobotItem_.java | 166 + .../sf/robocode/repository/IRobotSpecItem_.java | 127 + .../net/sf/robocode/repository/RobotType_.java | 33 + .../net/sf/robocode/security/HiddenAccess_.java | 33 + .../serialization/ISerializableHelper_.java | 52 + .../robocode/serialization/RbSerializer_.java | 33 + .../src/main/java/robocode/BattleRules_.java | 34 + .../robocode/control/BattleSpecification_.java | 33 + .../control/BattlefieldSpecification_.java | 33 + .../java/robocode/control/RandomFactory_.java | 33 + .../java/robocode/control/RobocodeEngine_.java | 33 + .../java/robocode/control/RobotResults_.java | 33 + .../main/java/robocode/control/RobotSetup_.java | 33 + .../robocode/control/RobotSpecification_.java | 33 + .../control/events/BattleCompletedEvent_.java | 33 + .../control/events/BattleErrorEvent_.java | 33 + .../robocode/control/events/BattleEvent_.java | 33 + .../control/events/BattleFinishedEvent_.java | 33 + .../control/events/BattleMessageEvent_.java | 33 + .../control/events/BattlePausedEvent_.java | 33 + .../control/events/BattleResumedEvent_.java | 33 + .../control/events/BattleStartedEvent_.java | 33 + .../control/events/IBattleListener_.java | 76 + .../control/events/RoundEndedEvent_.java | 33 + .../control/events/RoundStartedEvent_.java | 33 + .../control/events/TurnEndedEvent_.java | 33 + .../control/events/TurnStartedEvent_.java | 33 + .../robocode/control/snapshot/BulletState_.java | 33 + .../control/snapshot/IBulletSnapshot_.java | 85 + .../control/snapshot/IDebugProperty_.java | 49 + .../control/snapshot/IRobotSnapshot_.java | 127 + .../control/snapshot/IScoreSnapshot_.java | 100 + .../control/snapshot/ITurnSnapshot_.java | 64 + .../robocode/control/snapshot/RobotState_.java | 33 + .../robocode/exception/AbortedException_.java | 33 + .../robocode/exception/DeathException_.java | 33 + .../robocode/exception/DisabledException_.java | 33 + .../java/robocode/exception/WinException_.java | 33 + .../net/sf/robocode/dotnet/host/TestCLR.java | 24 + .../plugins/dotnet/robocode.dotnet.iml | 65 + .../dotnet/robocode.dotnet.installer/.classpath | 6 + .../dotnet/robocode.dotnet.installer/.project | 14 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../dotnet/robocode.dotnet.installer/pom.xml | 27 + .../robocode.dotnet.installer.iml | 67 + .../plugins/dotnet/robocode.dotnet.ipr | 118 + .../plugins/dotnet/robocode.dotnet.iws | 418 +++ .../dotnet/robocode.dotnet.nhost/.project | 11 + .../.settings/org.eclipse.jdt.core.prefs | 10 + .../dotnet/robocode.dotnet.nhost/pom.xml | 93 + .../robocode.dotnet.nhost.iml | 75 + .../dotnet/robocode.dotnet.nhost/src/.gitignore | 3 + .../sf/robocode/core/ContainerBase.generated.cs | 73 + .../dotnet/host/DotNetHost.generated.cs | 129 + .../robocode/dotnet/nhost/ModuleN.generated.cs | 82 + .../repository/root/DllRootHelper.generated.cs | 117 + .../net/sf/robocode/host/IHost.generated.cs | 154 + .../sf/robocode/host/IHostManager.generated.cs | 323 ++ .../proxies/IHostingRobotProxy.generated.cs | 163 + .../net/sf/robocode/io/Logger.generated.cs | 175 + .../manager/IVersionManagerBase.generated.cs | 171 + .../sf/robocode/peer/BadBehavior.generated.cs | 112 + .../sf/robocode/peer/IRobotPeer.generated.cs | 313 ++ .../sf/robocode/peer/IRobotStatics.generated.cs | 171 + .../robocode/repository/IRobotItem.generated.cs | 1045 ++++++ .../repository/IRobotSpecItem.generated.cs | 788 +++++ .../robocode/repository/RobotType.generated.cs | 196 ++ .../robocode/security/HiddenAccess.generated.cs | 293 ++ .../ISerializableHelper.generated.cs | 149 + .../serialization/RbSerializer.generated.cs | 1036 ++++++ .../exception/AbortedException.generated.cs | 78 + .../exception/DeathException.generated.cs | 78 + .../exception/DisabledException.generated.cs | 78 + .../exception/WinException.generated.cs | 78 + .../src/host/DotNetHost.cs | 50 + .../robocode.dotnet.nhost/src/host/ModuleN.cs | 79 + .../src/host/RobotStatics.cs | 312 ++ .../src/host/events/EventManager.cs | 702 ++++ .../src/host/events/EventQueue.cs | 53 + .../src/host/proxies/AdvancedRobotProxy.cs | 227 ++ .../src/host/proxies/BasicRobotProxy.cs | 716 ++++ .../src/host/proxies/GraphicsProxy.cs | 1284 +++++++ .../src/host/proxies/HostingRobotProxy.cs | 302 ++ .../src/host/proxies/JuniorRobotProxy.cs | 121 + .../src/host/proxies/StandardRobotProxy.cs | 136 + .../src/host/proxies/TeamRobotProxy.cs | 149 + .../src/host/security/QuotaStream.cs | 117 + .../src/host/security/RobotFileSystemManager.cs | 134 + .../src/host/seed/AppDomainSeed.cs | 170 + .../src/host/seed/AppDomainShell.cs | 163 + .../src/host/seed/HostingSeed.cs | 183 + .../src/host/seed/HostingShell.cs | 88 + .../robocode.dotnet.nhost/src/io/Logger.cs | 34 + .../src/mono/reflection/CILReader.cs | 419 +++ .../src/peer/BulletCommand.cs | 95 + .../src/peer/BulletStatus.cs | 80 + .../src/peer/DebugProperty.cs | 93 + .../src/peer/ExecCommands.cs | 490 +++ .../src/peer/ExecResults.cs | 253 ++ .../src/peer/TeamMessage.cs | 75 + .../src/repository/RobotType.cs | 44 + .../src/repository/root/DllRootHelper.cs | 84 + .../src/robocode.dotnet.nhost.csproj | 187 + .../src/serialization/RbSerializer.cs | 59 + .../src/utils/Reflection.cs | 189 + .../src/utils/Reflection.security.cs | 99 + .../dotnet/robocode.dotnet.ntests/.project | 14 + .../.settings/org.eclipse.jdt.core.prefs | 10 + .../dotnet/robocode.dotnet.ntests/pom.xml | 70 + .../robocode.dotnet.ntests.iml | 85 + .../src/AssemblyLoadTest.cs | 42 + .../robocode.dotnet.ntests/src/SimpleTest.cs | 125 + .../robocode.dotnet.ntests/src/TestBase.cs | 87 + .../src/robocode.dotnet.ntests.csproj | 108 + .../dotnet/robocode.dotnet.robotscs/.project | 10 + .../.settings/org.eclipse.jdt.core.prefs | 10 + .../dotnet/robocode.dotnet.robotscs/pom.xml | 51 + .../robocode.dotnet.robotscs.iml | 67 + ...ongNameIWouldSayTooLongMaybeEventLongerCs.cs | 22 + .../src/NoPackageShortNameCs.cs | 22 + .../src/SampleCs.csproj | 91 + .../robocode.dotnet.robotscs/src/SampleCs.sln | 20 + .../src/robocode.dotnet.robotscs.csproj | 114 + .../src/robocode/BadNamespaceCs.cs | 23 + .../src/tested/robotscs/Ahead.cs | 23 + .../src/tested/robotscs/BadFirePower.cs | 36 + .../src/tested/robotscs/BattleLost.cs | 41 + .../src/tested/robotscs/BattleWin.cs | 60 + .../src/tested/robotscs/BodyTurnRate.cs | 87 + .../src/tested/robotscs/CustomEvents.cs | 40 + .../src/tested/robotscs/DieFast.cs | 20 + .../src/tested/robotscs/EnvAttack.cs | 30 + .../src/tested/robotscs/EventPriorityFilter.cs | 37 + .../src/tested/robotscs/FairPlay.cs | 28 + .../src/tested/robotscs/FileAttack.cs | 69 + .../src/tested/robotscs/FileWriteSize.cs | 31 + .../src/tested/robotscs/FormsAttack.cs | 59 + .../src/tested/robotscs/GunHeat.cs | 24 + .../src/tested/robotscs/GunTurnRate.cs | 78 + .../src/tested/robotscs/HttpAttack.cs | 27 + .../src/tested/robotscs/InteruptibleEvent.cs | 36 + .../src/tested/robotscs/JuniorEvents.cs | 150 + .../src/tested/robotscs/MaxTurnRate.cs | 46 + .../src/tested/robotscs/MaxVelocity.cs | 75 + .../src/tested/robotscs/PrivateConstructor.cs | 18 + .../robotscs/RadarTurnRateAndSetAdjust.cs | 138 + .../src/tested/robotscs/Random.cs | 28 + .../src/tested/robotscs/RateControl.cs | 61 + .../src/tested/robotscs/ReflectionAttack.cs | 26 + .../src/tested/robotscs/RobotDeathEvents.cs | 41 + .../src/tested/robotscs/SkipTurns.cs | 88 + .../src/tested/robotscs/TestTeam.team | 7 + .../src/tested/robotscs/ThreadAttack.cs | 61 + .../TooLongNameThisIsReallyTooLongNameCs.cs | 25 + .../src/tested/robotscs/UndeadThread.cs | 64 + .../src/tested/robotscs/WatchBullets.cs | 93 + .../TooLongNamespaceCs.cs | 25 + .../dotnet/robocode.dotnet.samples/.project | 10 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../dotnet/robocode.dotnet.samples/pom.xml | 50 + .../robocode.dotnet.samples.iml | 68 + .../robocode.dotnet.samples/src/SampleCs.csproj | 91 + .../robocode.dotnet.samples/src/SampleCs.sln | 20 + .../src/SampleCs/Corners.cs | 155 + .../src/SampleCs/Crazy.cs | 107 + .../src/SampleCs/Fire.cs | 83 + .../src/SampleCs/Interactive.cs | 218 ++ .../src/SampleCs/MyFirstJuniorRobot.cs | 61 + .../src/SampleCs/MyFirstRobot.cs | 50 + .../src/SampleCs/PaintingRobot.cs | 83 + .../src/SampleCs/PointD.cs | 27 + .../src/SampleCs/RamFire.cs | 98 + .../src/SampleCs/RobotColors.cs | 22 + .../src/SampleCs/SittingDuck.cs | 86 + .../src/SampleCs/SpinBot.cs | 70 + .../src/SampleCs/Target.cs | 64 + .../src/SampleCs/TrackFire.cs | 83 + .../src/SampleCs/Tracker.cs | 154 + .../src/SampleCs/VelociRobot.cs | 60 + .../src/SampleCs/Walls.cs | 95 + .../src/SampleCsSentry/BorderGuard.cs | 763 ++++ .../src/SampleCsTeam/MyCsTeam.team | 7 + .../src/SampleCsTeam/MyFirstDroid.cs | 63 + .../src/SampleCsTeam/MyFirstLeader.cs | 98 + .../src/SampleFs/MyFirstRobot.fs | 23 + .../SampleFs/robocode.dotnet.samplesfs.fsproj | 57 + .../src/robocode.dotnet.samples.csproj | 93 + .../plugins/dotnet/robocode.dotnet.sln | 50 + .../dotnet/robocode.dotnet.tests/.classpath | 21 + .../dotnet/robocode.dotnet.tests/.project | 21 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../config/robocode.properties | 34 + .../dotnet/robocode.dotnet.tests/pom.xml | 71 + .../robocode.dotnet.tests.iml | 200 ++ .../test/robotscs/TestCustomEvents.java | 57 + .../test/robotscs/TestDuplicatesAndScore.java | 172 + .../robocode/test/robotscs/TestEnvAttack.java | 52 + .../test/robotscs/TestEventPriorityFilter.java | 47 + .../robocode/test/robotscs/TestFileAttack.java | 59 + .../robocode/test/robotscs/TestFileWrite.java | 51 + .../test/robotscs/TestFileWriteSize.java | 90 + .../robocode/test/robotscs/TestFormsAttack.java | 53 + .../robocode/test/robotscs/TestHttpAttack.java | 48 + .../test/robotscs/TestInteruptibleEvent.java | 48 + .../sf/robocode/test/robotscs/TestJunior.java | 52 + .../net/sf/robocode/test/robotscs/TestLost.java | 61 + .../robocode/test/robotscs/TestMaxVelocity.java | 81 + .../sf/robocode/test/robotscs/TestNames.java | 38 + .../sf/robocode/test/robotscs/TestPosition.java | 77 + .../test/robotscs/TestPrivateConstructor.java | 55 + .../sf/robocode/test/robotscs/TestRandom.java | 53 + .../test/robotscs/TestReflectionAttack.java | 51 + .../test/robotscs/TestRobotDeathEvents.java | 42 + .../sf/robocode/test/robotscs/TestScoring.java | 84 + .../test/robotscs/TestSkippedTurns.java | 53 + .../test/robotscs/TestThreadAttack.java | 46 + .../test/robotscs/TestUndeadThread.java | 52 + .../robocode/test/robotscs/TestWatchBullet.java | 61 + .../net/sf/robocode/test/robotscs/TestWin.java | 74 + .../test/resources/config/robocode.properties | 4 + .../plugins/dotnet/tools/.gitignore | 1 + .../plugins/dotnet/tools/keys/.gitignore | 1 + .../plugins/dotnet/tools/keys/gennetkey.cmd | 9 + .../plugins/dotnet/tools/loadTools.cmd | 23 + .../proxygen/robocode.control.proxygen.xml | 56 + .../tools/proxygen/robocode.proxygen.net.xml | 28 + .../dotnet/tools/proxygen/robocode.proxygen.xml | 45 + .../workspace_robo4/plugins/testing/.gitignore | 1 + 代码/workspace_robo4/plugins/testing/mvn.cmd | 19 + 代码/workspace_robo4/plugins/testing/mvn.sh | 20 + .../plugins/testing/mvnassembly.cmd | 12 + .../plugins/testing/mvnassembly.sh | 11 + 代码/workspace_robo4/plugins/testing/pom.xml | 21 + .../testing/robocode.testing.api/.classpath | 9 + .../testing/robocode.testing.api/.project | 14 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../testing/robocode.testing.api/pom.xml | 59 + .../robocode.testing.api.iml | 88 + .../robocode/control/testing/RobotTestBed.java | 329 ++ .../control/testing/RobotTestBedAssert.java | 32 + .../java/robocode/control/testing/package.html | 12 + .../testing/robocode.testing.content/.classpath | 7 + .../testing/robocode.testing.content/.project | 16 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../testing/robocode.testing.content/pom.xml | 33 + .../robocode.testing.content.iml | 67 + .../src/main/resources/testing/Read.Me.txt | 33 + .../src/main/resources/testing/compile.cmd | 10 + .../src/main/resources/testing/test.cmd | 10 + .../robocode.testing.distribution/.classpath | 12 + .../robocode.testing.distribution/.project | 19 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../robocode.testing.distribution/pom.xml | 72 + .../robocode.testing.distribution.iml | 90 + .../testing-setup.asm.xml | 79 + .../plugins/testing/robocode.testing.iml | 65 + .../robocode.testing.installer/.classpath | 6 + .../testing/robocode.testing.installer/.project | 14 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../testing/robocode.testing.installer/pom.xml | 27 + .../robocode.testing.installer.iml | 67 + .../plugins/testing/robocode.testing.ipr | 112 + .../plugins/testing/robocode.testing.iws | 418 +++ .../testing/robocode.testing.samples/.classpath | 13 + .../testing/robocode.testing.samples/.project | 16 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../testing/robocode.testing.samples/pom.xml | 65 + .../robocode.testing.samples.iml | 110 + .../src/main/java/sample/TestWallBehavior.java | 104 + 代码/workspace_robo4/pom.xml | 61 + 代码/workspace_robo4/robocode.api/.classpath | 6 + .../Launch Dir Builder.launch | 21 + 代码/workspace_robo4/robocode.api/.gitignore | 1 + 代码/workspace_robo4/robocode.api/.project | 26 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../robocode.api/Robocode.launch | 30 + 代码/workspace_robo4/robocode.api/pom.xml | 60 + .../robocode.api/robocode.api.iml | 67 + .../src/main/java/gl4java/GLFont.java | 16 + .../src/main/java/gl4java/GLFunc.java | 16 + .../main/java/net/sf/robocode/api/Module.java | 54 + .../sf/robocode/battle/IBattleManagerBase.java | 28 + .../net/sf/robocode/core/ContainerBase.java | 22 + .../main/java/net/sf/robocode/core/IModule.java | 19 + .../net/sf/robocode/gui/IWindowManagerBase.java | 16 + .../main/java/net/sf/robocode/io/FileUtil.java | 352 ++ .../main/java/net/sf/robocode/io/Logger.java | 109 + .../net/sf/robocode/io/RobocodeProperties.java | 79 + .../robocode/manager/IVersionManagerBase.java | 19 + .../net/sf/robocode/peer/IRobotStatics.java | 22 + .../robocode/repository/CodeSizeCalculator.java | 55 + .../repository/IRepositoryManagerBase.java | 21 + .../robocode/security/IHiddenBulletHelper.java | 19 + .../robocode/security/IHiddenEventHelper.java | 28 + .../robocode/security/IHiddenRulesHelper.java | 19 + .../security/IHiddenSpecificationHelper.java | 23 + .../robocode/security/IHiddenStatusHelper.java | 22 + .../robocode/security/IThreadManagerBase.java | 21 + .../net/sf/robocode/security/SafeComponent.java | 28 + .../serialization/ISerializableHelper.java | 21 + .../sf/robocode/serialization/RbSerializer.java | 539 +++ .../java/net/sf/robocode/util/StringUtil.java | 61 + .../main/java/net/sf/robocode/util/UrlUtil.java | 35 + .../src/main/java/robocode/AdvancedRobot.java | 2027 +++++++++++ .../main/java/robocode/BattleEndedEvent.java | 144 + .../src/main/java/robocode/BattleResults.java | 282 ++ .../src/main/java/robocode/BattleRules.java | 148 + .../src/main/java/robocode/BorderSentry.java | 35 + .../src/main/java/robocode/Bullet.java | 261 ++ .../java/robocode/BulletHitBulletEvent.java | 120 + .../src/main/java/robocode/BulletHitEvent.java | 161 + .../main/java/robocode/BulletMissedEvent.java | 102 + .../src/main/java/robocode/Condition.java | 147 + .../src/main/java/robocode/CustomEvent.java | 143 + .../src/main/java/robocode/DeathEvent.java | 98 + .../src/main/java/robocode/Droid.java | 24 + .../src/main/java/robocode/Event.java | 266 ++ .../java/robocode/GunTurnCompleteCondition.java | 70 + .../main/java/robocode/HitByBulletEvent.java | 205 ++ .../src/main/java/robocode/HitRobotEvent.java | 209 ++ .../src/main/java/robocode/HitWallEvent.java | 122 + .../src/main/java/robocode/JuniorRobot.java | 907 +++++ .../src/main/java/robocode/KeyEvent.java | 44 + .../src/main/java/robocode/KeyPressedEvent.java | 114 + .../main/java/robocode/KeyReleasedEvent.java | 114 + .../src/main/java/robocode/KeyTypedEvent.java | 114 + .../src/main/java/robocode/MessageEvent.java | 92 + .../main/java/robocode/MouseClickedEvent.java | 120 + .../main/java/robocode/MouseDraggedEvent.java | 121 + .../main/java/robocode/MouseEnteredEvent.java | 120 + .../src/main/java/robocode/MouseEvent.java | 43 + .../main/java/robocode/MouseExitedEvent.java | 120 + .../src/main/java/robocode/MouseMovedEvent.java | 120 + .../main/java/robocode/MousePressedEvent.java | 120 + .../main/java/robocode/MouseReleasedEvent.java | 120 + .../java/robocode/MouseWheelMovedEvent.java | 124 + .../java/robocode/MoveCompleteCondition.java | 70 + .../src/main/java/robocode/PaintEvent.java | 69 + .../robocode/RadarTurnCompleteCondition.java | 70 + .../main/java/robocode/RateControlRobot.java | 450 +++ .../src/main/java/robocode/Robocode.java | 29 + .../java/robocode/RobocodeFileOutputStream.java | 157 + .../main/java/robocode/RobocodeFileWriter.java | 85 + .../src/main/java/robocode/Robot.java | 1550 +++++++++ .../src/main/java/robocode/RobotDeathEvent.java | 113 + .../src/main/java/robocode/RobotStatus.java | 426 +++ .../src/main/java/robocode/RoundEndedEvent.java | 152 + .../src/main/java/robocode/Rules.java | 229 ++ .../main/java/robocode/ScannedRobotEvent.java | 314 ++ .../main/java/robocode/SkippedTurnEvent.java | 150 + .../src/main/java/robocode/StatusEvent.java | 81 + .../src/main/java/robocode/TeamRobot.java | 73 + .../java/robocode/TurnCompleteCondition.java | 70 + .../src/main/java/robocode/WinEvent.java | 98 + .../java/robocode/_AdvancedRadiansRobot.java | 179 + .../src/main/java/robocode/_AdvancedRobot.java | 273 ++ .../src/main/java/robocode/_Robot.java | 149 + .../src/main/java/robocode/_RobotBase.java | 92 + .../java/robocode/annotation/SafeStatic.java | 26 + .../java/robocode/annotation/package-info.java | 12 + .../robocode/control/BattleSpecification.java | 234 ++ .../control/BattlefieldSpecification.java | 71 + .../java/robocode/control/IRobocodeEngine.java | 150 + .../java/robocode/control/RandomFactory.java | 119 + .../java/robocode/control/RobocodeEngine.java | 364 ++ .../java/robocode/control/RobocodeListener.java | 64 + .../java/robocode/control/RobotResults.java | 188 + .../main/java/robocode/control/RobotSetup.java | 62 + .../robocode/control/RobotSpecification.java | 178 + .../robocode/control/events/BattleAdaptor.java | 101 + .../control/events/BattleCompletedEvent.java | 89 + .../control/events/BattleErrorEvent.java | 45 + .../robocode/control/events/BattleEvent.java | 27 + .../control/events/BattleFinishedEvent.java | 49 + .../control/events/BattleMessageEvent.java | 45 + .../control/events/BattlePausedEvent.java | 32 + .../control/events/BattleResumedEvent.java | 32 + .../control/events/BattleStartedEvent.java | 74 + .../control/events/IBattleListener.java | 163 + .../control/events/RoundEndedEvent.java | 75 + .../control/events/RoundStartedEvent.java | 61 + .../robocode/control/events/TurnEndedEvent.java | 48 + .../control/events/TurnStartedEvent.java | 32 + .../robocode/control/events/package-info.java | 13 + .../java/robocode/control/package-info.java | 105 + .../robocode/control/snapshot/BulletState.java | 101 + .../control/snapshot/IBulletSnapshot.java | 131 + .../control/snapshot/IDebugProperty.java | 33 + .../control/snapshot/IRobotSnapshot.java | 242 ++ .../control/snapshot/IScoreSnapshot.java | 146 + .../control/snapshot/ITurnSnapshot.java | 75 + .../robocode/control/snapshot/RobotState.java | 122 + .../robocode/control/snapshot/package-info.java | 12 + .../robocode/exception/AbortedException.java | 28 + .../java/robocode/exception/DeathException.java | 26 + .../robocode/exception/DisabledException.java | 24 + .../exception/EventInterruptedException.java | 26 + .../java/robocode/exception/RobotException.java | 24 + .../java/robocode/exception/WinException.java | 24 + .../java/robocode/exception/package-info.java | 12 + .../src/main/java/robocode/package-info.java | 12 + .../java/robocode/robocodeGL/EllipseGL.java | 50 + .../main/java/robocode/robocodeGL/LabelGL.java | 25 + .../main/java/robocode/robocodeGL/LineGL.java | 42 + .../main/java/robocode/robocodeGL/PointGL.java | 37 + .../java/robocode/robocodeGL/RectangleGL.java | 49 + .../java/robocode/robocodeGL/RenderElement.java | 47 + .../robocode/robocodeGL/system/GLRenderer.java | 26 + .../robotinterfaces/IAdvancedEvents.java | 60 + .../robotinterfaces/IAdvancedRobot.java | 40 + .../robocode/robotinterfaces/IBasicEvents.java | 278 ++ .../robocode/robotinterfaces/IBasicEvents2.java | 46 + .../robocode/robotinterfaces/IBasicEvents3.java | 45 + .../robocode/robotinterfaces/IBasicRobot.java | 77 + .../robotinterfaces/IInteractiveEvents.java | 223 ++ .../robotinterfaces/IInteractiveRobot.java | 44 + .../robocode/robotinterfaces/IJuniorRobot.java | 40 + .../robocode/robotinterfaces/IPaintEvents.java | 53 + .../robocode/robotinterfaces/IPaintRobot.java | 31 + .../robocode/robotinterfaces/ITeamEvents.java | 27 + .../robocode/robotinterfaces/ITeamRobot.java | 40 + .../robocode/robotinterfaces/package-info.java | 12 + .../peer/IAdvancedRobotPeer.java | 751 ++++ .../robotinterfaces/peer/IBasicRobotPeer.java | 738 ++++ .../robotinterfaces/peer/IJuniorRobotPeer.java | 67 + .../peer/IStandardRobotPeer.java | 205 ++ .../robotinterfaces/peer/ITeamRobotPeer.java | 47 + .../robotinterfaces/peer/package-info.java | 12 + .../src/main/java/robocode/util/Utils.java | 178 + .../main/java/robocode/util/package-info.java | 13 + .../workspace_robo4/robocode.battle/.classpath | 12 + 代码/workspace_robo4/robocode.battle/.project | 19 + .../.settings/org.eclipse.jdt.core.prefs | 9 + 代码/workspace_robo4/robocode.battle/pom.xml | 35 + .../robocode.battle/robocode.battle.iml | 85 + .../java/net/sf/robocode/battle/BaseBattle.java | 475 +++ .../java/net/sf/robocode/battle/Battle.java | 886 +++++ .../net/sf/robocode/battle/BattleManager.java | 404 +++ .../sf/robocode/battle/BoundingRectangle.java | 62 + .../java/net/sf/robocode/battle/Command.java | 14 + .../java/net/sf/robocode/battle/IBattle.java | 32 + .../java/net/sf/robocode/battle/Module.java | 30 + .../net/sf/robocode/battle/peer/BulletPeer.java | 364 ++ .../sf/robocode/battle/peer/ContestantPeer.java | 24 + .../battle/peer/ContestantStatistics.java | 57 + .../sf/robocode/battle/peer/ExplosionPeer.java | 52 + .../robocode/battle/peer/IRobotPeerBattle.java | 70 + .../net/sf/robocode/battle/peer/RobotPeer.java | 1764 ++++++++++ .../robocode/battle/peer/RobotStatistics.java | 298 ++ .../net/sf/robocode/battle/peer/TeamPeer.java | 94 + .../sf/robocode/battle/peer/TeamStatistics.java | 191 + .../battle/snapshot/BulletSnapshot.java | 360 ++ .../robocode/battle/snapshot/RobotSnapshot.java | 729 ++++ .../robocode/battle/snapshot/ScoreSnapshot.java | 562 +++ .../robocode/battle/snapshot/TurnSnapshot.java | 297 ++ .../net/sf/robocode/recording/BattlePlayer.java | 149 + .../sf/robocode/recording/BattleRecordInfo.java | 330 ++ .../sf/robocode/recording/BattleRecorder.java | 142 + .../sf/robocode/recording/RecordManager.java | 448 +++ .../workspace_robo4/robocode.content/.classpath | 7 + .../workspace_robo4/robocode.content/.project | 18 + .../.settings/org.eclipse.jdt.core.prefs | 9 + 代码/workspace_robo4/robocode.content/pom.xml | 62 + .../robocode.content/robocode.content.iml | 67 + .../src/main/resources/ReadMe.html | 233 ++ .../src/main/resources/ReadMe.txt | 471 +++ .../src/main/resources/battles/intro.battle | 8 + .../src/main/resources/battles/sample.battle | 8 + .../main/resources/compilers/CompilerTest.java | 12 + .../src/main/resources/desktop/robocode.png | Bin 0 -> 3918 bytes .../desktop/robocodeMeleeRumble.desktop | 9 + .../desktop/robocodeRoboRumble.desktop | 9 + .../resources/desktop/robocodeRobocode.desktop | 9 + .../desktop/robocodeTeamRumble.desktop | 9 + .../resources/desktop/robocodeTwinDuel.desktop | 9 + .../src/main/resources/desktop/roborumble.png | Bin 0 -> 3401 bytes .../src/main/resources/license/epl-v10.html | 188 + .../src/main/resources/meleerumble.bat | 9 + .../src/main/resources/meleerumble.command | 13 + .../src/main/resources/meleerumble.sh | 13 + .../src/main/resources/robocode.bat | 9 + .../src/main/resources/robocode.command | 13 + .../src/main/resources/robocode.ico | Bin 0 -> 370070 bytes .../src/main/resources/robocode.sh | 13 + .../src/main/resources/roborumble.bat | 9 + .../src/main/resources/roborumble.command | 13 + .../src/main/resources/roborumble.ico | Bin 0 -> 32038 bytes .../src/main/resources/roborumble.sh | 13 + .../main/resources/roborumble/meleerumble.txt | 244 ++ .../resources/roborumble/roborumble.properties | 6 + .../main/resources/roborumble/roborumble.txt | 241 ++ .../main/resources/roborumble/teamrumble.txt | 203 ++ .../src/main/resources/roborumble/twinduel.txt | 203 ++ .../src/main/resources/teamrumble.bat | 9 + .../src/main/resources/teamrumble.command | 13 + .../src/main/resources/teamrumble.sh | 13 + .../main/resources/templates/newjavafile.tpt | 8 + .../main/resources/templates/newjuniorrobot.tpt | 54 + .../src/main/resources/templates/newrobot.tpt | 56 + .../editor/Robocode Black Theme.properties | 23 + .../editor/Robocode White Theme.properties | 23 + .../src/main/resources/twinduel.bat | 9 + .../src/main/resources/twinduel.command | 13 + .../src/main/resources/twinduel.sh | 13 + 代码/workspace_robo4/robocode.core/.classpath | 12 + 代码/workspace_robo4/robocode.core/.project | 16 + .../.settings/org.eclipse.jdt.core.prefs | 9 + 代码/workspace_robo4/robocode.core/pom.xml | 61 + .../robocode.core/robocode.core.iml | 91 + .../sf/robocode/battle/BattleProperties.java | 333 ++ .../battle/BattleRankingTableModel.java | 199 ++ .../battle/BattleResultsTableModel.java | 253 ++ .../net/sf/robocode/battle/IBattleManager.java | 94 + .../sf/robocode/cachecleaner/CacheCleaner.java | 73 + .../java/net/sf/robocode/core/BaseModule.java | 19 + .../java/net/sf/robocode/core/Container.java | 257 ++ .../net/sf/robocode/core/EngineClassLoader.java | 97 + .../main/java/net/sf/robocode/core/Module.java | 42 + .../net/sf/robocode/core/RobocodeMainBase.java | 92 + .../java/net/sf/robocode/host/ICpuManager.java | 18 + .../java/net/sf/robocode/host/IHostManager.java | 43 + .../net/sf/robocode/host/IRobotClassLoader.java | 23 + .../java/net/sf/robocode/host/RobotStatics.java | 319 ++ .../main/java/net/sf/robocode/io/JarJar.java | 17 + .../net/sf/robocode/io/URLJarCollector.java | 176 + .../java/net/sf/robocode/peer/BadBehavior.java | 19 + .../net/sf/robocode/peer/BulletCommand.java | 80 + .../java/net/sf/robocode/peer/BulletStatus.java | 71 + .../net/sf/robocode/peer/DebugProperty.java | 106 + .../java/net/sf/robocode/peer/ExecCommands.java | 428 +++ .../java/net/sf/robocode/peer/ExecResults.java | 177 + .../java/net/sf/robocode/peer/IRobotPeer.java | 39 + .../java/net/sf/robocode/peer/TeamMessage.java | 66 + .../robocode/recording/BattleRecordFormat.java | 19 + .../sf/robocode/recording/IRecordManager.java | 29 + .../robocode/repository/CodeSizeCalculator.java | 55 + .../robocode/repository/IRepositoryManager.java | 56 + .../net/sf/robocode/repository/IRobotItem.java | 35 + .../sf/robocode/repository/IRobotSpecItem.java | 76 + .../sf/robocode/repository/RobotProperties.java | 84 + .../net/sf/robocode/repository/RobotType.java | 137 + .../sf/robocode/repository/TeamProperties.java | 66 + .../robotpaint/Graphics2DSerialized.java | 2340 +++++++++++++ .../sf/robocode/robotpaint/IGraphicsProxy.java | 24 + .../serialization/IXmlSerializable.java | 21 + .../serialization/SerializableOptions.java | 44 + .../sf/robocode/serialization/XmlReader.java | 189 + .../sf/robocode/serialization/XmlWriter.java | 142 + .../sf/robocode/settings/ISettingsListener.java | 16 + .../sf/robocode/settings/ISettingsManager.java | 317 ++ .../sf/robocode/settings/SettingsManager.java | 896 +++++ .../net/sf/robocode/sound/ISoundManager.java | 18 + .../java/net/sf/robocode/ui/IWindowManager.java | 55 + .../robocode/util/AlphanumericComparator.java | 197 ++ .../sf/robocode/version/IVersionManager.java | 20 + .../java/net/sf/robocode/version/Version.java | 178 + .../net/sf/robocode/version/VersionManager.java | 224 ++ .../src/main/resources/battleRecord.xsd | 193 ++ .../src/main/resources/battleRecordS.xsd | 193 ++ .../sf/robocode/serialization/ObjectCloner.java | 90 + .../serialization/RbSerializerTest.java | 261 ++ .../net/sf/robocode/version/VersionTest.java | 135 + .../robocode.distribution/.classpath | 19 + .../robocode.distribution/.project | 27 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../robocode.distribution/pom.xml | 73 + .../robocode.distribution.iml | 91 + .../robocode.distribution/setup.asm.xml | 96 + .../robocode.distribution/src.asm.xml | 53 + 代码/workspace_robo4/robocode.dummy.zip | Bin 0 -> 3658 bytes 代码/workspace_robo4/robocode.host/.classpath | 13 + 代码/workspace_robo4/robocode.host/.project | 17 + .../.settings/org.eclipse.jdt.core.prefs | 9 + 代码/workspace_robo4/robocode.host/pom.xml | 31 + .../robocode.host/robocode.host.iml | 93 + .../java/net/sf/robocode/host/CpuManager.java | 86 + .../java/net/sf/robocode/host/HostManager.java | 106 + .../main/java/net/sf/robocode/host/IHost.java | 26 + .../net/sf/robocode/host/IHostedThread.java | 32 + .../net/sf/robocode/host/IThreadManager.java | 43 + .../main/java/net/sf/robocode/host/Module.java | 26 + .../net/sf/robocode/host/events/EventQueue.java | 53 + .../sf/robocode/host/events/IEventManager.java | 50 + .../host/io/BufferedPipedInputStream.java | 40 + .../host/io/BufferedPipedOutputStream.java | 169 + .../robocode/host/io/RobotFileOutputStream.java | 75 + .../host/io/RobotFileSystemManager.java | 336 ++ .../sf/robocode/host/io/RobotOutputStream.java | 294 ++ .../host/jarjar/JarJarURLConnection.java | 182 + .../host/proxies/AdvancedRobotProxy.java | 216 ++ .../robocode/host/proxies/BasicRobotProxy.java | 567 +++ .../host/proxies/IHostingRobotProxy.java | 28 + .../robocode/host/proxies/JuniorRobotProxy.java | 114 + .../host/proxies/StandardRobotProxy.java | 103 + .../robocode/host/proxies/TeamRobotProxy.java | 126 + .../robocode/host/security/ClassAnalyzer.java | 248 ++ .../host/security/RobocodePermission.java | 100 + .../host/security/RobocodeSecurityManager.java | 128 + .../host/security/RobocodeSecurityPolicy.java | 322 ++ .../host/security/RobotThreadManager.java | 343 ++ .../host/security/SecureInputStream.java | 103 + .../host/security/SecurePrintStream.java | 293 ++ .../robocode/host/security/ThreadManager.java | 213 ++ .../RobocodeObjectInputStream.java | 40 + .../net/sf/robocode/host/jarjar/JarJarTest.java | 72 + .../robocode.host/src/test/resources/Outer.jar | Bin 0 -> 611 bytes 代码/workspace_robo4/robocode.iml | 65 + .../robocode.installer/.classpath | 6 + .../workspace_robo4/robocode.installer/.project | 14 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../workspace_robo4/robocode.installer/pom.xml | 27 + .../robocode.installer/robocode.installer.iml | 67 + 代码/workspace_robo4/robocode.ipr | 122 + 代码/workspace_robo4/robocode.iws | 418 +++ .../robocode.repository/.classpath | 10 + .../robocode.repository/.project | 17 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../workspace_robo4/robocode.repository/pom.xml | 29 + .../robocode.repository/robocode.repository.iml | 83 + .../net/sf/robocode/repository/IRepository.java | 105 + .../java/net/sf/robocode/repository/Module.java | 38 + .../net/sf/robocode/repository/Repository.java | 199 ++ .../robocode/repository/RepositoryManager.java | 480 +++ .../repository/items/IRepositoryItem.java | 38 + .../repository/items/RepositoryItem.java | 77 + .../sf/robocode/repository/items/RobotItem.java | 608 ++++ .../repository/items/RobotSpecItem.java | 259 ++ .../sf/robocode/repository/items/TeamItem.java | 258 ++ .../repository/items/handlers/ClassHandler.java | 74 + .../repository/items/handlers/ItemHandler.java | 60 + .../items/handlers/PropertiesHandler.java | 104 + .../items/handlers/SourceHandler.java | 87 + .../repository/items/handlers/TeamHandler.java | 70 + .../repository/packager/JarCreator.java | 267 ++ .../repository/packager/JarExtractor.java | 92 + .../repository/parsers/ClasspathFileParser.java | 63 + .../sf/robocode/repository/root/BaseRoot.java | 78 + .../robocode/repository/root/ClasspathRoot.java | 138 + .../repository/root/IRepositoryRoot.java | 38 + .../sf/robocode/repository/root/JarRoot.java | 177 + .../root/handlers/ClassPathHandler.java | 85 + .../repository/root/handlers/JarHandler.java | 70 + .../repository/root/handlers/RootHandler.java | 52 + .../robocode.roborumble/.classpath | 13 + .../robocode.roborumble/.project | 20 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../robocode.roborumble/MeleeRumble.launch | 20 + .../robocode.roborumble/RoboRumble.launch | 20 + .../robocode.roborumble/TeamRumble.launch | 20 + .../workspace_robo4/robocode.roborumble/pom.xml | 51 + .../robocode.roborumble/robocode.roborumble.iml | 86 + .../roborumble/battlesengine/BattlesRunner.java | 235 ++ .../battlesengine/CompetitionsSelector.java | 77 + .../battlesengine/PrepareBattles.java | 579 ++++ .../roborumble/netengine/BotsDownload.java | 625 ++++ .../roborumble/netengine/ResultsUpload.java | 328 ++ .../roborumble/netengine/UpdateRatingFiles.java | 130 + .../robocode/roborumble/util/ExcludesUtil.java | 80 + .../roborumble/util/PropertiesUtil.java | 102 + .../main/java/roborumble/RoboRumbleAtHome.java | 152 + .../workspace_robo4/robocode.samples/.classpath | 8 + .../workspace_robo4/robocode.samples/.project | 16 + .../.settings/org.eclipse.jdt.core.prefs | 9 + 代码/workspace_robo4/robocode.samples/pom.xml | 45 + .../robocode.samples/robocode.samples.iml | 69 + .../src/main/java/sample/Corners.java | 140 + .../src/main/java/sample/Crazy.java | 103 + .../src/main/java/sample/Fire.java | 84 + .../src/main/java/sample/Interactive.java | 223 ++ .../src/main/java/sample/Interactive_v2.java | 263 ++ .../main/java/sample/MyFirstJuniorRobot.java | 60 + .../src/main/java/sample/MyFirstRobot.java | 53 + .../src/main/java/sample/PaintingRobot.java | 87 + .../src/main/java/sample/RamFire.java | 86 + .../src/main/java/sample/SittingDuck.html | 24 + .../src/main/java/sample/SittingDuck.java | 96 + .../src/main/java/sample/SpinBot.java | 70 + .../src/main/java/sample/Target.java | 65 + .../src/main/java/sample/TrackFire.java | 80 + .../src/main/java/sample/Tracker.java | 144 + .../src/main/java/sample/VelociRobot.java | 59 + .../src/main/java/sample/Walls.java | 94 + .../src/main/java/sampleex/Alien.java | 82 + .../main/java/sampleex/AlienComposition.java | 95 + .../src/main/java/sampleex/MasterAndSlave.java | 115 + .../main/java/sampleex/ProxyOfGreyEminence.java | 73 + .../src/main/java/sampleex/RegullarMonk.java | 17 + .../src/main/java/sampleex/Slave.java | 40 + .../src/main/java/samplesentry/BorderGuard.java | 716 ++++ .../src/main/java/sampleteam/MyFirstDroid.java | 62 + .../src/main/java/sampleteam/MyFirstLeader.java | 89 + .../src/main/java/sampleteam/Point.java | 33 + .../src/main/java/sampleteam/RobotColors.java | 29 + .../main/resources/sample/Corners.properties | 9 + .../src/main/resources/sample/Crazy.properties | 9 + .../src/main/resources/sample/Fire.properties | 9 + .../resources/sample/Interactive.properties | 9 + .../resources/sample/Interactive_v2.properties | 8 + .../sample/MyFirstJuniorRobot.properties | 9 + .../resources/sample/MyFirstRobot.properties | 9 + .../resources/sample/PaintingRobot.properties | 10 + .../main/resources/sample/RamFire.properties | 9 + .../resources/sample/SittingDuck.properties | 9 + .../main/resources/sample/SpinBot.properties | 9 + .../src/main/resources/sample/Target.properties | 9 + .../main/resources/sample/TrackFire.properties | 9 + .../main/resources/sample/Tracker.properties | 9 + .../resources/sample/VelociRobot.properties | 9 + .../src/main/resources/sample/Walls.properties | 9 + .../main/resources/sampleex/Alien.properties | 9 + .../sampleex/MasterAndSlave.properties | 9 + .../sampleex/ProxyOfGreyEminence.properties | 9 + .../samplesentry/BorderGuard.properties | 9 + .../main/resources/sampleteam/MyFirstTeam.team | 7 + .../workspace_robo4/robocode.sound/.classpath | 10 + 代码/workspace_robo4/robocode.sound/.project | 17 + .../.settings/org.eclipse.jdt.core.prefs | 9 + 代码/workspace_robo4/robocode.sound/pom.xml | 19 + .../robocode.sound/robocode.sound.iml | 77 + .../main/java/net/sf/robocode/sound/Module.java | 22 + .../java/net/sf/robocode/sound/SoundCache.java | 219 ++ .../net/sf/robocode/sound/SoundManager.java | 376 ++ .../sound/sounds/13831_adcbicycle_22.wav | Bin 0 -> 74240 bytes .../net/sf/robocode/sound/sounds/explode.wav | Bin 0 -> 23160 bytes .../net/sf/robocode/sound/sounds/shellhit.wav | Bin 0 -> 46496 bytes .../net/sf/robocode/sound/sounds/zap.wav | Bin 0 -> 18076 bytes .../robocode.tests.robots/.classpath | 9 + .../robocode.tests.robots/.project | 17 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../robocode.tests.robots/pom.xml | 45 + .../robocode.tests.robots.iml | 70 + ...ongNameIWouldSayTooLongMaybeEventLonger.java | 24 + .../src/main/java/NoPackageShortName.java | 24 + .../src/main/java/robocode/BadNamespace.java | 24 + .../src/main/java/tested/robots/Ahead.java | 23 + .../main/java/tested/robots/BadFirePower.java | 34 + .../src/main/java/tested/robots/BattleLost.java | 45 + .../src/main/java/tested/robots/BattleWin.java | 59 + .../main/java/tested/robots/BodyTurnRate.java | 75 + .../tested/robots/ConstructorHttpAttack.java | 40 + .../robots/ConstructorReflectionAttack.java | 49 + .../tested/robots/ConstructorSocketAttack.java | 62 + .../main/java/tested/robots/CustomEvents.java | 56 + .../java/tested/robots/DecelerationCaveat1.java | 35 + .../java/tested/robots/DecelerationCaveat2.java | 35 + .../java/tested/robots/DecelerationCaveat3.java | 34 + .../src/main/java/tested/robots/DieFast.java | 22 + .../src/main/java/tested/robots/EnvAttack.java | 32 + .../java/tested/robots/EventPriorityFilter.java | 40 + .../src/main/java/tested/robots/FairPlay.java | 28 + .../tested/robots/FileOutputStreamAttack.java | 42 + .../main/java/tested/robots/FileWriteSize.java | 58 + .../src/main/java/tested/robots/GunHeat.java | 27 + .../main/java/tested/robots/GunTurnRate.java | 70 + .../src/main/java/tested/robots/HttpAttack.java | 40 + .../java/tested/robots/InteruptibleEvent.java | 46 + .../main/java/tested/robots/JuniorEvents.java | 135 + .../main/java/tested/robots/MaxTurnRate.java | 41 + .../main/java/tested/robots/MaxVelocity.java | 72 + .../java/tested/robots/PrivateConstructor.java | 20 + .../robots/RadarTurnRateAndSetAdjust.java | 134 + .../src/main/java/tested/robots/Random.java | 30 + .../main/java/tested/robots/RateControl.java | 46 + .../java/tested/robots/ReflectionAttack.java | 34 + .../java/tested/robots/ReverseDirection.java | 30 + .../java/tested/robots/RobotDeathEvents.java | 40 + .../src/main/java/tested/robots/SkipTurns.java | 80 + .../main/java/tested/robots/SocketAttack.java | 49 + .../TooLongNameThisIsReallyTooLongName.java | 27 + .../main/java/tested/robots/WatchBullets.java | 71 + .../TooLongNamespace.java | 27 + .../main/resources/tested/robots/TestTeam.team | 7 + .../workspace_robo4/robocode.tests/.classpath | 18 + 代码/workspace_robo4/robocode.tests/.project | 22 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../robocode.tests/config/robocode.properties | 3 + 代码/workspace_robo4/robocode.tests/pom.xml | 59 + .../robocode.tests/robocode.tests.iml | 103 + .../robocode/test/helpers/RobocodeTestBed.java | 209 ++ .../core/util/AlphanumericComparatorTest.java | 60 + .../host/security/RobotClassLoaderTest.java | 84 + .../robocode/test/robots/TestAcceleration.java | 197 ++ .../sf/robocode/test/robots/TestAwtAttack.java | 82 + .../robocode/test/robots/TestBodyTurnRate.java | 128 + .../robocode/test/robots/TestBulletPower.java | 59 + .../test/robots/TestConstructorAwtAttack.java | 76 + .../test/robots/TestConstructorHttpAttack.java | 55 + .../robots/TestConstructorReflectionAttack.java | 49 + .../robots/TestConstructorSocketAttack.java | 55 + .../robots/TestConstructorThreadAttack.java | 41 + .../robocode/test/robots/TestCustomEvents.java | 56 + .../test/robots/TestDuplicatesAndScore.java | 159 + .../sf/robocode/test/robots/TestEnvAttack.java | 52 + .../test/robots/TestEventPriorityFilter.java | 47 + .../sf/robocode/test/robots/TestFairPlay.java | 66 + .../sf/robocode/test/robots/TestFileAttack.java | 74 + .../test/robots/TestFileOutputStreamAttack.java | 49 + .../sf/robocode/test/robots/TestFileWrite.java | 51 + .../robocode/test/robots/TestFileWriteSize.java | 70 + .../sf/robocode/test/robots/TestGunHeat.java | 90 + .../robocode/test/robots/TestGunTurnRate.java | 61 + .../sf/robocode/test/robots/TestHttpAttack.java | 49 + .../test/robots/TestIncludeNamespaceAttack.java | 38 + .../test/robots/TestInteruptibleEvent.java | 48 + .../net/sf/robocode/test/robots/TestJunior.java | 52 + .../net/sf/robocode/test/robots/TestLost.java | 61 + .../robocode/test/robots/TestMaxTurnRate.java | 72 + .../robocode/test/robots/TestMaxVelocity.java | 81 + .../net/sf/robocode/test/robots/TestNames.java | 38 + .../sf/robocode/test/robots/TestPosition.java | 78 + .../test/robots/TestPrivateConstructor.java | 54 + .../robots/TestRadarTurnRateAndSetAdjust.java | 59 + .../net/sf/robocode/test/robots/TestRandom.java | 53 + .../robots/TestRankingsWithTargetRobots.java | 70 + .../robocode/test/robots/TestRateControl.java | 121 + .../test/robots/TestReflectionAttack.java | 49 + .../test/robots/TestReverseDirection.java | 50 + .../test/robots/TestRobotDeathEvents.java | 42 + .../sf/robocode/test/robots/TestScoring.java | 83 + .../robocode/test/robots/TestSkippedTurns.java | 53 + .../robocode/test/robots/TestSocketAttack.java | 49 + .../robocode/test/robots/TestThreadAttack.java | 55 + .../test/robots/TestThreadGroupAttack.java | 59 + .../robocode/test/robots/TestUndeadThread.java | 59 + .../robocode/test/robots/TestWatchBullet.java | 50 + .../net/sf/robocode/test/robots/TestWin.java | 88 + .../robocode/test/samples/RobocodeRunner.java | 91 + .../robocode.ui.editor/.classpath | 15 + .../workspace_robo4/robocode.ui.editor/.project | 22 + .../.settings/org.eclipse.jdt.core.prefs | 9 + .../workspace_robo4/robocode.ui.editor/pom.xml | 19 + .../robocode.ui.editor/robocode.ui.editor.iml | 88 + .../ui/editor/CompilerPreferencesDialog.java | 171 + .../robocode/ui/editor/CompilerProperties.java | 138 + .../robocode/ui/editor/CompoundUndoManager.java | 147 + .../net/sf/robocode/ui/editor/EditorPane.java | 374 ++ .../net/sf/robocode/ui/editor/EditorPanel.java | 181 + .../ui/editor/EditorThemeConfigDialog.java | 978 ++++++ .../robocode/ui/editor/FindReplaceDialog.java | 386 +++ .../net/sf/robocode/ui/editor/FontStyle.java | 68 + .../robocode/ui/editor/IEditorProperties.java | 21 + .../net/sf/robocode/ui/editor/JavaDocument.java | 1137 ++++++ .../sf/robocode/ui/editor/LineHighlighter.java | 141 + .../sf/robocode/ui/editor/LineNumberArea.java | 137 + .../java/net/sf/robocode/ui/editor/Module.java | 23 + .../robocode/ui/editor/MoreWindowsDialog.java | 138 + .../sf/robocode/ui/editor/RobocodeCompiler.java | 112 + .../ui/editor/RobocodeCompilerFactory.java | 219 ++ .../sf/robocode/ui/editor/RobocodeEditor.java | 664 ++++ .../ui/editor/RobocodeEditorMenuBar.java | 722 ++++ .../sf/robocode/ui/editor/StyledDocument.java | 64 + .../ui/editor/UndoManagerWithActions.java | 96 + .../robocode/ui/editor/theme/ColorAndStyle.java | 159 + .../ui/editor/theme/ColorAndStyleAdapter.java | 28 + .../robocode/ui/editor/theme/ComboBoxUtil.java | 92 + .../ui/editor/theme/EditorProperties.java | 70 + .../editor/theme/EditorPropertiesManager.java | 74 + .../ui/editor/theme/EditorThemeProperties.java | 541 +++ .../theme/EditorThemePropertiesManager.java | 248 ++ .../theme/EditorThemePropertyChangeAdapter.java | 62 + .../ui/editor/theme/IColorAndStyleListener.java | 25 + .../ui/editor/theme/IEditorThemeProperties.java | 59 + .../IEditorThemePropertyChangeListener.java | 52 + 代码/workspace_robo4/robocode.ui/.classpath | 15 + 代码/workspace_robo4/robocode.ui/.project | 21 + .../.settings/org.eclipse.jdt.core.prefs | 9 + 代码/workspace_robo4/robocode.ui/pom.xml | 35 + .../workspace_robo4/robocode.ui/robocode.ui.iml | 88 + .../java/net/sf/robocode/ui/BrowserManager.java | 71 + .../main/java/net/sf/robocode/ui/CheckList.java | 220 ++ .../java/net/sf/robocode/ui/IImageManager.java | 33 + .../net/sf/robocode/ui/IRobotDialogManager.java | 30 + .../net/sf/robocode/ui/IWindowManagerExt.java | 71 + .../java/net/sf/robocode/ui/ImageManager.java | 236 ++ .../main/java/net/sf/robocode/ui/Module.java | 47 + .../net/sf/robocode/ui/RobotDialogManager.java | 97 + .../sf/robocode/ui/battleview/BattleField.java | 49 + .../sf/robocode/ui/battleview/BattleView.java | 698 ++++ .../ui/battleview/InteractiveHandler.java | 153 + .../ui/battleview/MirroredGraphics.java | 567 +++ .../robocode/ui/battleview/ScreenshotUtil.java | 84 + .../net/sf/robocode/ui/dialog/AboutBox.java | 225 ++ .../ui/dialog/AvailableRobotsPanel.java | 421 +++ .../sf/robocode/ui/dialog/BaseScoreDialog.java | 179 + .../net/sf/robocode/ui/dialog/BattleButton.java | 57 + .../net/sf/robocode/ui/dialog/BattleDialog.java | 244 ++ .../sf/robocode/ui/dialog/ConsoleDialog.java | 163 + .../robocode/ui/dialog/ConsoleScrollPane.java | 170 + .../java/net/sf/robocode/ui/dialog/MenuBar.java | 939 +++++ .../sf/robocode/ui/dialog/NewBattleDialog.java | 204 ++ .../robocode/ui/dialog/NewBattleRulesTab.java | 492 +++ .../ui/dialog/PreferencesCommonOptionsTab.java | 155 + .../PreferencesDevelopmentOptionsTab.java | 198 ++ .../robocode/ui/dialog/PreferencesDialog.java | 149 + .../dialog/PreferencesRenderingOptionsTab.java | 297 ++ .../ui/dialog/PreferencesSoundOptionsTab.java | 397 +++ .../ui/dialog/PreferencesViewOptionsTab.java | 470 +++ .../sf/robocode/ui/dialog/RankingDialog.java | 117 + .../sf/robocode/ui/dialog/RcSplashScreen.java | 114 + .../sf/robocode/ui/dialog/ResultsDialog.java | 140 + .../ui/dialog/ResultsTableCellRenderer.java | 51 + .../sf/robocode/ui/dialog/RobocodeFrame.java | 1011 ++++++ .../net/sf/robocode/ui/dialog/RobotButton.java | 228 ++ .../ui/dialog/RobotDescriptionPanel.java | 230 ++ .../net/sf/robocode/ui/dialog/RobotDialog.java | 450 +++ .../sf/robocode/ui/dialog/RobotExtractor.java | 164 + .../robocode/ui/dialog/RobotSelectionPanel.java | 487 +++ .../net/sf/robocode/ui/dialog/TeamCreator.java | 178 + .../ui/dialog/TeamCreatorOptionsPanel.java | 314 ++ .../ui/dialog/WindowPositionManager.java | 154 + .../net/sf/robocode/ui/dialog/WindowUtil.java | 207 ++ .../java/net/sf/robocode/ui/dialog/Wizard.java | 35 + .../sf/robocode/ui/dialog/WizardCardPanel.java | 116 + .../sf/robocode/ui/dialog/WizardController.java | 195 ++ .../sf/robocode/ui/dialog/WizardListener.java | 18 + .../net/sf/robocode/ui/dialog/WizardPanel.java | 34 + .../sf/robocode/ui/dialog/WizardTabbedPane.java | 106 + .../sf/robocode/ui/editor/IRobocodeEditor.java | 16 + .../java/net/sf/robocode/ui/gfx/ColorUtil.java | 153 + .../net/sf/robocode/ui/gfx/GraphicsState.java | 60 + .../java/net/sf/robocode/ui/gfx/ImageUtil.java | 121 + .../net/sf/robocode/ui/gfx/RenderImage.java | 88 + .../net/sf/robocode/ui/gfx/RenderObject.java | 139 + .../net/sf/robocode/ui/gfx/RobocodeLogo.java | 445 +++ .../sf/robocode/ui/packager/ConfirmPanel.java | 123 + .../sf/robocode/ui/packager/FilenamePanel.java | 269 ++ .../ui/packager/PackagerOptionsPanel.java | 405 +++ .../sf/robocode/ui/packager/RobotPackager.java | 233 ++ .../ui/util/LimitedClassnameDocument.java | 52 + .../sf/robocode/ui/util/LimitedDocument.java | 103 + .../net/sf/robocode/ui/util/ShortcutUtil.java | 62 + .../net/sf/robocode/ui/html/about.html | 135 + .../net/sf/robocode/ui/html/transparent.png | Bin 0 -> 1202 bytes .../net/sf/robocode/ui/icons/robocode-icon.png | Bin 0 -> 2243 bytes .../net/sf/robocode/ui/images/.cvsignore | 1 + .../net/sf/robocode/ui/images/body.png | Bin 0 -> 1702 bytes .../sf/robocode/ui/images/explosion/.cvsignore | 1 + .../ui/images/explosion/explosion1-1.png | Bin 0 -> 1513 bytes .../ui/images/explosion/explosion1-10.png | Bin 0 -> 19762 bytes .../ui/images/explosion/explosion1-11.png | Bin 0 -> 22670 bytes .../ui/images/explosion/explosion1-12.png | Bin 0 -> 25567 bytes .../ui/images/explosion/explosion1-13.png | Bin 0 -> 27867 bytes .../ui/images/explosion/explosion1-14.png | Bin 0 -> 28149 bytes .../ui/images/explosion/explosion1-15.png | Bin 0 -> 16242 bytes .../ui/images/explosion/explosion1-16.png | Bin 0 -> 201 bytes .../ui/images/explosion/explosion1-17.png | Bin 0 -> 201 bytes .../ui/images/explosion/explosion1-2.png | Bin 0 -> 2390 bytes .../ui/images/explosion/explosion1-3.png | Bin 0 -> 3464 bytes .../ui/images/explosion/explosion1-4.png | Bin 0 -> 4771 bytes .../ui/images/explosion/explosion1-5.png | Bin 0 -> 6418 bytes .../ui/images/explosion/explosion1-6.png | Bin 0 -> 8845 bytes .../ui/images/explosion/explosion1-7.png | Bin 0 -> 11331 bytes .../ui/images/explosion/explosion1-8.png | Bin 0 -> 14242 bytes .../ui/images/explosion/explosion1-9.png | Bin 0 -> 16936 bytes .../ui/images/explosion/explosion2-1.png | Bin 0 -> 743 bytes .../ui/images/explosion/explosion2-10.png | Bin 0 -> 2075 bytes .../ui/images/explosion/explosion2-11.png | Bin 0 -> 2307 bytes .../ui/images/explosion/explosion2-12.png | Bin 0 -> 2494 bytes .../ui/images/explosion/explosion2-13.png | Bin 0 -> 2724 bytes .../ui/images/explosion/explosion2-14.png | Bin 0 -> 2939 bytes .../ui/images/explosion/explosion2-15.png | Bin 0 -> 3159 bytes .../ui/images/explosion/explosion2-16.png | Bin 0 -> 3388 bytes .../ui/images/explosion/explosion2-17.png | Bin 0 -> 3669 bytes .../ui/images/explosion/explosion2-18.png | Bin 0 -> 3924 bytes .../ui/images/explosion/explosion2-19.png | Bin 0 -> 4234 bytes .../ui/images/explosion/explosion2-2.png | Bin 0 -> 851 bytes .../ui/images/explosion/explosion2-20.png | Bin 0 -> 4496 bytes .../ui/images/explosion/explosion2-21.png | Bin 0 -> 4817 bytes .../ui/images/explosion/explosion2-22.png | Bin 0 -> 5128 bytes .../ui/images/explosion/explosion2-23.png | Bin 0 -> 5518 bytes .../ui/images/explosion/explosion2-24.png | Bin 0 -> 5840 bytes .../ui/images/explosion/explosion2-25.png | Bin 0 -> 6255 bytes .../ui/images/explosion/explosion2-26.png | Bin 0 -> 6599 bytes .../ui/images/explosion/explosion2-27.png | Bin 0 -> 6974 bytes .../ui/images/explosion/explosion2-28.png | Bin 0 -> 7379 bytes .../ui/images/explosion/explosion2-29.png | Bin 0 -> 7822 bytes .../ui/images/explosion/explosion2-3.png | Bin 0 -> 1138 bytes .../ui/images/explosion/explosion2-30.png | Bin 0 -> 8185 bytes .../ui/images/explosion/explosion2-31.png | Bin 0 -> 8580 bytes .../ui/images/explosion/explosion2-32.png | Bin 0 -> 9082 bytes .../ui/images/explosion/explosion2-33.png | Bin 0 -> 9505 bytes .../ui/images/explosion/explosion2-34.png | Bin 0 -> 9957 bytes .../ui/images/explosion/explosion2-35.png | Bin 0 -> 10475 bytes .../ui/images/explosion/explosion2-36.png | Bin 0 -> 11068 bytes .../ui/images/explosion/explosion2-37.png | Bin 0 -> 11583 bytes .../ui/images/explosion/explosion2-38.png | Bin 0 -> 12170 bytes .../ui/images/explosion/explosion2-39.png | Bin 0 -> 12837 bytes .../ui/images/explosion/explosion2-4.png | Bin 0 -> 1225 bytes .../ui/images/explosion/explosion2-40.png | Bin 0 -> 13464 bytes .../ui/images/explosion/explosion2-41.png | Bin 0 -> 14302 bytes .../ui/images/explosion/explosion2-42.png | Bin 0 -> 15022 bytes .../ui/images/explosion/explosion2-43.png | Bin 0 -> 15790 bytes .../ui/images/explosion/explosion2-44.png | Bin 0 -> 16608 bytes .../ui/images/explosion/explosion2-45.png | Bin 0 -> 17417 bytes .../ui/images/explosion/explosion2-46.png | Bin 0 -> 18282 bytes .../ui/images/explosion/explosion2-47.png | Bin 0 -> 19130 bytes .../ui/images/explosion/explosion2-48.png | Bin 0 -> 20011 bytes .../ui/images/explosion/explosion2-49.png | Bin 0 -> 20823 bytes .../ui/images/explosion/explosion2-5.png | Bin 0 -> 1300 bytes .../ui/images/explosion/explosion2-50.png | Bin 0 -> 21664 bytes .../ui/images/explosion/explosion2-51.png | Bin 0 -> 22594 bytes .../ui/images/explosion/explosion2-52.png | Bin 0 -> 23543 bytes .../ui/images/explosion/explosion2-53.png | Bin 0 -> 24830 bytes .../ui/images/explosion/explosion2-54.png | Bin 0 -> 25827 bytes .../ui/images/explosion/explosion2-55.png | Bin 0 -> 26725 bytes .../ui/images/explosion/explosion2-56.png | Bin 0 -> 27702 bytes .../ui/images/explosion/explosion2-57.png | Bin 0 -> 28608 bytes .../ui/images/explosion/explosion2-58.png | Bin 0 -> 29323 bytes .../ui/images/explosion/explosion2-59.png | Bin 0 -> 30258 bytes .../ui/images/explosion/explosion2-6.png | Bin 0 -> 1418 bytes .../ui/images/explosion/explosion2-60.png | Bin 0 -> 31004 bytes .../ui/images/explosion/explosion2-61.png | Bin 0 -> 32043 bytes .../ui/images/explosion/explosion2-62.png | Bin 0 -> 32889 bytes .../ui/images/explosion/explosion2-63.png | Bin 0 -> 33011 bytes .../ui/images/explosion/explosion2-64.png | Bin 0 -> 31551 bytes .../ui/images/explosion/explosion2-65.png | Bin 0 -> 26477 bytes .../ui/images/explosion/explosion2-66.png | Bin 0 -> 10905 bytes .../ui/images/explosion/explosion2-67.png | Bin 0 -> 6613 bytes .../ui/images/explosion/explosion2-68.png | Bin 0 -> 2047 bytes .../ui/images/explosion/explosion2-69.png | Bin 0 -> 201 bytes .../ui/images/explosion/explosion2-7.png | Bin 0 -> 1598 bytes .../ui/images/explosion/explosion2-70.png | Bin 0 -> 201 bytes .../ui/images/explosion/explosion2-71.png | Bin 0 -> 201 bytes .../ui/images/explosion/explosion2-8.png | Bin 0 -> 1742 bytes .../ui/images/explosion/explosion2-9.png | Bin 0 -> 1925 bytes .../net/sf/robocode/ui/images/ground/.cvsignore | 1 + .../images/ground/blue_metal/blue_metal_0.png | Bin 0 -> 3859 bytes .../images/ground/blue_metal/blue_metal_1.png | Bin 0 -> 1532 bytes .../images/ground/blue_metal/blue_metal_2.png | Bin 0 -> 3513 bytes .../images/ground/blue_metal/blue_metal_3.png | Bin 0 -> 3173 bytes .../images/ground/blue_metal/blue_metal_4.png | Bin 0 -> 4540 bytes .../ui/images/ground/explode_debris.png | Bin 0 -> 3542 bytes .../net/sf/robocode/ui/images/radar.png | Bin 0 -> 833 bytes .../net/sf/robocode/ui/images/turret.png | Bin 0 -> 1188 bytes 代码/workspace_robo4/super-pom/.project | 11 + 代码/workspace_robo4/super-pom/pom.xml | 179 + .../super-pom/robocode-license-header.txt | 5 + 代码/workspace_robo4/tools/.gitignore | 1 + 代码/workspace_robo4/tools/.project | 11 + 代码/workspace_robo4/tools/bin/ant.bat | 226 ++ 代码/workspace_robo4/tools/bin/ant.sh | 94 + 代码/workspace_robo4/tools/bin/m2.conf | 4 + 代码/workspace_robo4/tools/bin/mvn.bat | 191 + 代码/workspace_robo4/tools/bin/mvn.sh | 162 + 代码/workspace_robo4/tools/debugall/all.iml | 33 + 代码/workspace_robo4/tools/jacobe/.gitignore | 1 + 代码/workspace_robo4/tools/jacobe/ReadMe.txt | 57 + .../workspace_robo4/tools/jacobe/robocode.cfg | 301 ++ .../tools/licenses/ant-LICENSE.txt | 272 ++ .../tools/licenses/ant-NOTICE.txt | 26 + .../tools/licenses/mvn-LICENSE.txt | 202 ++ .../tools/licenses/mvn-NOTICE.txt | 11 + 代码/workspace_robo4/tools/loadTools.cmd | 19 + 代码/workspace_robo4/tools/loadTools.sh | 21 + 代码/workspace_robo4/tools/loader/Loader.java | 54 + 代码/workspace_robo4/versions.md | 3082 +++++++++++++++++ 1272 files changed, 145069 insertions(+) create mode 100644 代码/workspace_robo4/.gitignore create mode 100644 代码/workspace_robo4/README.md create mode 100644 代码/workspace_robo4/RemoteSystemsTempFiles/.project create mode 100644 代码/workspace_robo4/jacobe.cmd create mode 100644 代码/workspace_robo4/jacobe.sh create mode 100644 代码/workspace_robo4/mvn.cmd create mode 100644 代码/workspace_robo4/mvn.sh create mode 100644 代码/workspace_robo4/mvnassembly.cmd create mode 100644 代码/workspace_robo4/mvnassembly.sh create mode 100644 代码/workspace_robo4/plugins/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/ReadMe.txt create mode 100644 代码/workspace_robo4/plugins/dotnet/generateProxies.cmd create mode 100644 代码/workspace_robo4/plugins/dotnet/mvn.cmd create mode 100644 代码/workspace_robo4/plugins/dotnet/mvnassembly.cmd create mode 100644 代码/workspace_robo4/plugins/dotnet/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/robocode.dotnet.api.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/robotAPI.shfbproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/.gitignore create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/AssemblyInf.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/io/LoggerN.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/Buffer.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/ByteBuffer.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/HeapByteBuffer.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/InvalidMarkException.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/peer/IRobotStaticsN.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/HiddenAccessN.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenBulletHelper.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenEventHelper.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenRandomHelper.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenRulesHelper.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenStatusHelper.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/RobocodeInternalPermission.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/serialization/ISerializableHelperN.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/serialization/RbSerializerN.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode.dotnet.api.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/AdvancedRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleEndedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleResults.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleRules.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Bullet.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletHitBulletEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletHitEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletMissedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Condition.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/CustomEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/DeathEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Event.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/GunTurnCompleteCondition.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitByBulletEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitRobotEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitWallEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IBorderSentry.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IDroid.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IGraphics.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/JuniorRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyPressedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyReleasedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyTypedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Keys.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MessageEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseClickedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseDraggedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseEnteredEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseExitedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseMovedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MousePressedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseReleasedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseWheelMovedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MoveCompleteCondition.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/PaintEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RadarTurnCompleteCondition.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RateControlRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Robot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RobotDeathEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RobotStatus.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RoundEndedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Rules.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/ScannedRobotEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/SkippedTurnEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/StatusEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/TeamRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Thread.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/TurnCompleteCondition.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/WinEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/exception/EventInterruptedException.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/exception/RobotException.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IAdvancedEvents.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IAdvancedRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents2.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents3.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IInteractiveEvents.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IInteractiveRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IJuniorRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IPaintEvents.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IPaintRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IRunnable.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/ITeamEvents.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/ITeamRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IAdvancedRobotPeer.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IBasicRobotPeer.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IJuniorRobotPeer.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IStandardRobotPeer.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/ITeamRobotPeer.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/util/Utils.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.classpath create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/robocode.dotnet.content.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/.gitignore create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/BattleRunnnerSample.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/BattleRunnnerSample.sln create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/Program.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/robocode.bat create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/robots/SamplesCs.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/Content Layout.content create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/Introduction.aml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/controlAPI.shfbproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/robocode.dotnet.control.api.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/.gitignore create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/java/util/Random.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/BattleSpecification.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/BattlefieldSpecification.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RandomFactory.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobocodeEngine.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotResults.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotSetup.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotSpecification.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleCompletedEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleErrorEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleFinishedEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleMessageEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattlePausedEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleResumedEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleStartedEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/IBattleListener.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/RoundEndedEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/RoundStartedEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/TurnEndedEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/TurnStartedEvent.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/BulletState.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IBulletSnapshot.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IDebugProperty.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IRobotSnapshot.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IScoreSnapshot.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/ITurnSnapshot.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/RobotState.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/glue/robocode/control/RandomFactory.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/glue/robocode/control/RobocodeEngine.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/BattleSpecification.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/BattlefieldSpecification.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/IRobocodeEngine.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobocodeEngine.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobotSetup.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobotSpecification.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleCompletedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleErrorEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleFinishedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleMessageEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattlePausedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleResumedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleStartedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/RoundEndedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/RoundStartedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/TurnEndedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/TurnStartedEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/BulletState.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IBulletSnapshot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IDebugProperty.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IRobotSnapshot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IScoreSnapshot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/ITurnSnapshot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/RobotState.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/robocode.dotnet.control.api.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/robocode.ico create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.classpath create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/dotnet-setup.asm.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/robocode.dotnet.distribution.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.classpath create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/robocode.dotnet.host.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/java_/util/Random_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/core/ContainerBase_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/DotNetHost.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/nhost/ModuleN.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/items/DotNetRobotItem.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/items/handlers/DotNetPropertiesHandler.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/DllRoot.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/DllRootHelper.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/handlers/DllHandler.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/IHostManager_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/IHost_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/RobotStatics_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/proxies/IHostingRobotProxy_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/io/Logger_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/manager/IVersionManagerBase_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/BadBehavior_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/IRobotPeer_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/IRobotStatics_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/IRobotItem_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/IRobotSpecItem_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/RobotType_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/security/HiddenAccess_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/serialization/ISerializableHelper_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/serialization/RbSerializer_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/BattleRules_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/BattleSpecification_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/BattlefieldSpecification_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RandomFactory_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobocodeEngine_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotResults_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotSetup_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotSpecification_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleCompletedEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleErrorEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleFinishedEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleMessageEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattlePausedEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleResumedEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleStartedEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/IBattleListener_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/RoundEndedEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/RoundStartedEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/TurnEndedEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/TurnStartedEvent_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/BulletState_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IBulletSnapshot_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IDebugProperty_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IRobotSnapshot_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IScoreSnapshot_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/ITurnSnapshot_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/RobotState_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/AbortedException_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/DeathException_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/DisabledException_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/WinException_.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/test/java/net/sf/robocode/dotnet/host/TestCLR.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.classpath create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/robocode.dotnet.installer.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ipr create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.iws create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/robocode.dotnet.nhost.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/.gitignore create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/core/ContainerBase.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/host/DotNetHost.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/nhost/ModuleN.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/repository/root/DllRootHelper.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/IHost.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/IHostManager.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/proxies/IHostingRobotProxy.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/io/Logger.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/manager/IVersionManagerBase.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/BadBehavior.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/IRobotPeer.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/IRobotStatics.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/IRobotItem.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/IRobotSpecItem.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/RobotType.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/security/HiddenAccess.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/serialization/ISerializableHelper.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/serialization/RbSerializer.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/AbortedException.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/DeathException.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/DisabledException.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/WinException.generated.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/DotNetHost.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/ModuleN.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/RobotStatics.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/events/EventManager.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/events/EventQueue.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/AdvancedRobotProxy.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/BasicRobotProxy.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/GraphicsProxy.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/HostingRobotProxy.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/JuniorRobotProxy.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/StandardRobotProxy.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/TeamRobotProxy.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/security/QuotaStream.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/security/RobotFileSystemManager.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/AppDomainSeed.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/AppDomainShell.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/HostingSeed.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/HostingShell.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/io/Logger.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/mono/reflection/CILReader.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/BulletCommand.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/BulletStatus.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/DebugProperty.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/ExecCommands.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/ExecResults.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/TeamMessage.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/repository/RobotType.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/repository/root/DllRootHelper.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/robocode.dotnet.nhost.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/serialization/RbSerializer.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/utils/Reflection.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/utils/Reflection.security.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/robocode.dotnet.ntests.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/AssemblyLoadTest.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/SimpleTest.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/TestBase.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/robocode.dotnet.ntests.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/robocode.dotnet.robotscs.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLongerCs.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/NoPackageShortNameCs.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/SampleCs.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/SampleCs.sln create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/robocode.dotnet.robotscs.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/robocode/BadNamespaceCs.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/Ahead.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BadFirePower.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BattleLost.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BattleWin.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BodyTurnRate.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/CustomEvents.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/DieFast.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/EnvAttack.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/EventPriorityFilter.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FairPlay.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FileAttack.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FileWriteSize.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FormsAttack.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/GunHeat.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/GunTurnRate.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/HttpAttack.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/InteruptibleEvent.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/JuniorEvents.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/MaxTurnRate.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/MaxVelocity.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/PrivateConstructor.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RadarTurnRateAndSetAdjust.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/Random.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RateControl.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/ReflectionAttack.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RobotDeathEvents.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/SkipTurns.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/TestTeam.team create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/ThreadAttack.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/TooLongNameThisIsReallyTooLongNameCs.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/UndeadThread.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/WatchBullets.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tooLongNamespaceThisIsReallyTooLongNamespace/TooLongNamespaceCs.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/robocode.dotnet.samples.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs.sln create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Corners.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Crazy.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Fire.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Interactive.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/MyFirstJuniorRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/MyFirstRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/PaintingRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/PointD.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/RamFire.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/RobotColors.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/SittingDuck.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/SpinBot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Target.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/TrackFire.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Tracker.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/VelociRobot.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Walls.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsSentry/BorderGuard.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyCsTeam.team create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyFirstDroid.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyFirstLeader.cs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleFs/MyFirstRobot.fs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleFs/robocode.dotnet.samplesfs.fsproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/robocode.dotnet.samples.csproj create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.sln create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.classpath create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.project create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/config/robocode.properties create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/pom.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/robocode.dotnet.tests.iml create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestCustomEvents.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestDuplicatesAndScore.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestEnvAttack.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestEventPriorityFilter.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileAttack.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileWrite.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileWriteSize.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFormsAttack.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestHttpAttack.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestInteruptibleEvent.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestJunior.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestLost.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxVelocity.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestNames.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestPosition.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestPrivateConstructor.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestRandom.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestReflectionAttack.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestRobotDeathEvents.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestScoring.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestSkippedTurns.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestThreadAttack.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestUndeadThread.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestWatchBullet.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestWin.java create mode 100644 代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/resources/config/robocode.properties create mode 100644 代码/workspace_robo4/plugins/dotnet/tools/.gitignore create mode 100644 代码/workspace_robo4/plugins/dotnet/tools/keys/.gitignore create mode 100644 代码/workspace_robo4/plugins/dotnet/tools/keys/gennetkey.cmd create mode 100644 代码/workspace_robo4/plugins/dotnet/tools/loadTools.cmd create mode 100644 代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.control.proxygen.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.proxygen.net.xml create mode 100644 代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.proxygen.xml create mode 100644 代码/workspace_robo4/plugins/testing/.gitignore create mode 100644 代码/workspace_robo4/plugins/testing/mvn.cmd create mode 100644 代码/workspace_robo4/plugins/testing/mvn.sh create mode 100644 代码/workspace_robo4/plugins/testing/mvnassembly.cmd create mode 100644 代码/workspace_robo4/plugins/testing/mvnassembly.sh create mode 100644 代码/workspace_robo4/plugins/testing/pom.xml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.api/.classpath create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.api/.project create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.api/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.api/pom.xml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.api/robocode.testing.api.iml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/RobotTestBed.java create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/RobotTestBedAssert.java create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/package.html create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.content/.classpath create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.content/.project create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.content/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.content/pom.xml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.content/robocode.testing.content.iml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/Read.Me.txt create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/compile.cmd create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/test.cmd create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.classpath create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.project create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.distribution/pom.xml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.distribution/robocode.testing.distribution.iml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.distribution/testing-setup.asm.xml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.iml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.installer/.classpath create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.installer/.project create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.installer/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.installer/pom.xml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.installer/robocode.testing.installer.iml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.ipr create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.iws create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.samples/.classpath create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.samples/.project create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.samples/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.samples/pom.xml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.samples/robocode.testing.samples.iml create mode 100644 代码/workspace_robo4/plugins/testing/robocode.testing.samples/src/main/java/sample/TestWallBehavior.java create mode 100644 代码/workspace_robo4/pom.xml create mode 100644 代码/workspace_robo4/robocode.api/.classpath create mode 100644 代码/workspace_robo4/robocode.api/.externalToolBuilders/Launch Dir Builder.launch create mode 100644 代码/workspace_robo4/robocode.api/.gitignore create mode 100644 代码/workspace_robo4/robocode.api/.project create mode 100644 代码/workspace_robo4/robocode.api/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.api/Robocode.launch create mode 100644 代码/workspace_robo4/robocode.api/pom.xml create mode 100644 代码/workspace_robo4/robocode.api/robocode.api.iml create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/gl4java/GLFont.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/gl4java/GLFunc.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/api/Module.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/battle/IBattleManagerBase.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/core/ContainerBase.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/core/IModule.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/gui/IWindowManagerBase.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/FileUtil.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/Logger.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/RobocodeProperties.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/manager/IVersionManagerBase.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/peer/IRobotStatics.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/repository/CodeSizeCalculator.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/repository/IRepositoryManagerBase.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenBulletHelper.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenEventHelper.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenRulesHelper.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenSpecificationHelper.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenStatusHelper.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IThreadManagerBase.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/SafeComponent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/serialization/ISerializableHelper.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/serialization/RbSerializer.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/util/StringUtil.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/util/UrlUtil.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/AdvancedRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleEndedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleResults.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleRules.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/BorderSentry.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/Bullet.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletHitBulletEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletHitEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletMissedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/Condition.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/CustomEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/DeathEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/Droid.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/Event.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/GunTurnCompleteCondition.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/HitByBulletEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/HitRobotEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/HitWallEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/JuniorRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyPressedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyReleasedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyTypedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MessageEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseClickedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseDraggedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseEnteredEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseExitedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseMovedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MousePressedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseReleasedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseWheelMovedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/MoveCompleteCondition.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/PaintEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/RadarTurnCompleteCondition.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/RateControlRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/Robocode.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/RobocodeFileOutputStream.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/RobocodeFileWriter.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/Robot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/RobotDeathEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/RobotStatus.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/RoundEndedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/Rules.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/ScannedRobotEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/SkippedTurnEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/StatusEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/TeamRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/TurnCompleteCondition.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/WinEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/_AdvancedRadiansRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/_AdvancedRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/_Robot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/_RobotBase.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/annotation/SafeStatic.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/annotation/package-info.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/BattleSpecification.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/BattlefieldSpecification.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/IRobocodeEngine.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RandomFactory.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobocodeEngine.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobocodeListener.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotResults.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotSetup.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotSpecification.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleAdaptor.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleCompletedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleErrorEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleFinishedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleMessageEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattlePausedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleResumedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleStartedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/IBattleListener.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/RoundEndedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/RoundStartedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/TurnEndedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/TurnStartedEvent.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/package-info.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/package-info.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/BulletState.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IBulletSnapshot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IDebugProperty.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IRobotSnapshot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IScoreSnapshot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/ITurnSnapshot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/RobotState.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/package-info.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/AbortedException.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/DeathException.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/DisabledException.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/EventInterruptedException.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/RobotException.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/WinException.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/package-info.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/package-info.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/EllipseGL.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/LabelGL.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/LineGL.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/PointGL.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/RectangleGL.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/RenderElement.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/system/GLRenderer.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IAdvancedEvents.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IAdvancedRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents2.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents3.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IInteractiveEvents.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IInteractiveRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IJuniorRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IPaintEvents.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IPaintRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/ITeamEvents.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/ITeamRobot.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/package-info.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IAdvancedRobotPeer.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IBasicRobotPeer.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IJuniorRobotPeer.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IStandardRobotPeer.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/ITeamRobotPeer.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/package-info.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/util/Utils.java create mode 100644 代码/workspace_robo4/robocode.api/src/main/java/robocode/util/package-info.java create mode 100644 代码/workspace_robo4/robocode.battle/.classpath create mode 100644 代码/workspace_robo4/robocode.battle/.project create mode 100644 代码/workspace_robo4/robocode.battle/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.battle/pom.xml create mode 100644 代码/workspace_robo4/robocode.battle/robocode.battle.iml create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BaseBattle.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Battle.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BattleManager.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BoundingRectangle.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Command.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/IBattle.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Module.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/BulletPeer.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ContestantPeer.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ContestantStatistics.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ExplosionPeer.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/IRobotPeerBattle.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/RobotPeer.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/RobotStatistics.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/TeamPeer.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/TeamStatistics.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/BulletSnapshot.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/RobotSnapshot.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/ScoreSnapshot.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/TurnSnapshot.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattlePlayer.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattleRecordInfo.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattleRecorder.java create mode 100644 代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/RecordManager.java create mode 100644 代码/workspace_robo4/robocode.content/.classpath create mode 100644 代码/workspace_robo4/robocode.content/.project create mode 100644 代码/workspace_robo4/robocode.content/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.content/pom.xml create mode 100644 代码/workspace_robo4/robocode.content/robocode.content.iml create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/ReadMe.html create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/ReadMe.txt create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/battles/intro.battle create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/battles/sample.battle create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/compilers/CompilerTest.java create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocode.png create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeMeleeRumble.desktop create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeRoboRumble.desktop create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeRobocode.desktop create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeTeamRumble.desktop create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeTwinDuel.desktop create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/desktop/roborumble.png create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/license/epl-v10.html create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.bat create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.command create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.sh create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/robocode.bat create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/robocode.command create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/robocode.ico create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/robocode.sh create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/roborumble.bat create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/roborumble.command create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/roborumble.ico create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/roborumble.sh create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/roborumble/meleerumble.txt create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/roborumble/roborumble.properties create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/roborumble/roborumble.txt create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/roborumble/teamrumble.txt create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/roborumble/twinduel.txt create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.bat create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.command create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.sh create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/templates/newjavafile.tpt create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/templates/newjuniorrobot.tpt create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/templates/newrobot.tpt create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/theme/editor/Robocode Black Theme.properties create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/theme/editor/Robocode White Theme.properties create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/twinduel.bat create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/twinduel.command create mode 100644 代码/workspace_robo4/robocode.content/src/main/resources/twinduel.sh create mode 100644 代码/workspace_robo4/robocode.core/.classpath create mode 100644 代码/workspace_robo4/robocode.core/.project create mode 100644 代码/workspace_robo4/robocode.core/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.core/pom.xml create mode 100644 代码/workspace_robo4/robocode.core/robocode.core.iml create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleProperties.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleRankingTableModel.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleResultsTableModel.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/IBattleManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/cachecleaner/CacheCleaner.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/BaseModule.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/Container.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/EngineClassLoader.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/Module.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMainBase.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/ICpuManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/IHostManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/IRobotClassLoader.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/RobotStatics.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/io/JarJar.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/io/URLJarCollector.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BadBehavior.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BulletCommand.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BulletStatus.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/DebugProperty.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/ExecCommands.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/ExecResults.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/IRobotPeer.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/TeamMessage.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/recording/BattleRecordFormat.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/recording/IRecordManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/CodeSizeCalculator.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRepositoryManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRobotItem.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRobotSpecItem.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/RobotProperties.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/RobotType.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/TeamProperties.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/robotpaint/Graphics2DSerialized.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/robotpaint/IGraphicsProxy.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/IXmlSerializable.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/SerializableOptions.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/XmlReader.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/XmlWriter.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/ISettingsListener.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/ISettingsManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/SettingsManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/sound/ISoundManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/ui/IWindowManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/util/AlphanumericComparator.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/IVersionManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/Version.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/VersionManager.java create mode 100644 代码/workspace_robo4/robocode.core/src/main/resources/battleRecord.xsd create mode 100644 代码/workspace_robo4/robocode.core/src/main/resources/battleRecordS.xsd create mode 100644 代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/serialization/ObjectCloner.java create mode 100644 代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/serialization/RbSerializerTest.java create mode 100644 代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/version/VersionTest.java create mode 100644 代码/workspace_robo4/robocode.distribution/.classpath create mode 100644 代码/workspace_robo4/robocode.distribution/.project create mode 100644 代码/workspace_robo4/robocode.distribution/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.distribution/pom.xml create mode 100644 代码/workspace_robo4/robocode.distribution/robocode.distribution.iml create mode 100644 代码/workspace_robo4/robocode.distribution/setup.asm.xml create mode 100644 代码/workspace_robo4/robocode.distribution/src.asm.xml create mode 100644 代码/workspace_robo4/robocode.dummy.zip create mode 100644 代码/workspace_robo4/robocode.host/.classpath create mode 100644 代码/workspace_robo4/robocode.host/.project create mode 100644 代码/workspace_robo4/robocode.host/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.host/pom.xml create mode 100644 代码/workspace_robo4/robocode.host/robocode.host.iml create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/CpuManager.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/HostManager.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IHost.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IHostedThread.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IThreadManager.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/Module.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventQueue.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/IEventManager.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/BufferedPipedInputStream.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/BufferedPipedOutputStream.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotFileOutputStream.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotFileSystemManager.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotOutputStream.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/jarjar/JarJarURLConnection.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/AdvancedRobotProxy.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/BasicRobotProxy.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/IHostingRobotProxy.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/JuniorRobotProxy.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/StandardRobotProxy.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/TeamRobotProxy.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/ClassAnalyzer.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodePermission.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodeSecurityManager.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodeSecurityPolicy.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotThreadManager.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/SecureInputStream.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/SecurePrintStream.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/ThreadManager.java create mode 100644 代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/serialization/RobocodeObjectInputStream.java create mode 100644 代码/workspace_robo4/robocode.host/src/test/java/net/sf/robocode/host/jarjar/JarJarTest.java create mode 100644 代码/workspace_robo4/robocode.host/src/test/resources/Outer.jar create mode 100644 代码/workspace_robo4/robocode.iml create mode 100644 代码/workspace_robo4/robocode.installer/.classpath create mode 100644 代码/workspace_robo4/robocode.installer/.project create mode 100644 代码/workspace_robo4/robocode.installer/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.installer/pom.xml create mode 100644 代码/workspace_robo4/robocode.installer/robocode.installer.iml create mode 100644 代码/workspace_robo4/robocode.ipr create mode 100644 代码/workspace_robo4/robocode.iws create mode 100644 代码/workspace_robo4/robocode.repository/.classpath create mode 100644 代码/workspace_robo4/robocode.repository/.project create mode 100644 代码/workspace_robo4/robocode.repository/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.repository/pom.xml create mode 100644 代码/workspace_robo4/robocode.repository/robocode.repository.iml create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/IRepository.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/Module.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/Repository.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/RepositoryManager.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/IRepositoryItem.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RepositoryItem.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RobotItem.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RobotSpecItem.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/TeamItem.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/ClassHandler.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/ItemHandler.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/PropertiesHandler.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/SourceHandler.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/TeamHandler.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/packager/JarCreator.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/packager/JarExtractor.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/parsers/ClasspathFileParser.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/BaseRoot.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/ClasspathRoot.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/IRepositoryRoot.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/JarRoot.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/ClassPathHandler.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/JarHandler.java create mode 100644 代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/RootHandler.java create mode 100644 代码/workspace_robo4/robocode.roborumble/.classpath create mode 100644 代码/workspace_robo4/robocode.roborumble/.project create mode 100644 代码/workspace_robo4/robocode.roborumble/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.roborumble/MeleeRumble.launch create mode 100644 代码/workspace_robo4/robocode.roborumble/RoboRumble.launch create mode 100644 代码/workspace_robo4/robocode.roborumble/TeamRumble.launch create mode 100644 代码/workspace_robo4/robocode.roborumble/pom.xml create mode 100644 代码/workspace_robo4/robocode.roborumble/robocode.roborumble.iml create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/BattlesRunner.java create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/CompetitionsSelector.java create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/PrepareBattles.java create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/BotsDownload.java create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/ResultsUpload.java create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/UpdateRatingFiles.java create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/util/ExcludesUtil.java create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/util/PropertiesUtil.java create mode 100644 代码/workspace_robo4/robocode.roborumble/src/main/java/roborumble/RoboRumbleAtHome.java create mode 100644 代码/workspace_robo4/robocode.samples/.classpath create mode 100644 代码/workspace_robo4/robocode.samples/.project create mode 100644 代码/workspace_robo4/robocode.samples/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.samples/pom.xml create mode 100644 代码/workspace_robo4/robocode.samples/robocode.samples.iml create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/Corners.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/Crazy.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/Fire.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/Interactive.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/Interactive_v2.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/MyFirstJuniorRobot.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/MyFirstRobot.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/PaintingRobot.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/RamFire.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/SittingDuck.html create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/SittingDuck.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/SpinBot.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/Target.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/TrackFire.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/Tracker.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/VelociRobot.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sample/Walls.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleex/Alien.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleex/AlienComposition.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleex/MasterAndSlave.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleex/ProxyOfGreyEminence.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleex/RegullarMonk.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleex/Slave.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/samplesentry/BorderGuard.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/MyFirstDroid.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/MyFirstLeader.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/Point.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/RobotColors.java create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/Corners.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/Crazy.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/Fire.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/Interactive.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/Interactive_v2.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/MyFirstJuniorRobot.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/MyFirstRobot.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/PaintingRobot.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/RamFire.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/SittingDuck.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/SpinBot.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/Target.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/TrackFire.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/Tracker.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/VelociRobot.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sample/Walls.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/Alien.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/MasterAndSlave.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/ProxyOfGreyEminence.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/samplesentry/BorderGuard.properties create mode 100644 代码/workspace_robo4/robocode.samples/src/main/resources/sampleteam/MyFirstTeam.team create mode 100644 代码/workspace_robo4/robocode.sound/.classpath create mode 100644 代码/workspace_robo4/robocode.sound/.project create mode 100644 代码/workspace_robo4/robocode.sound/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.sound/pom.xml create mode 100644 代码/workspace_robo4/robocode.sound/robocode.sound.iml create mode 100644 代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/Module.java create mode 100644 代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/SoundCache.java create mode 100644 代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/SoundManager.java create mode 100644 代码/workspace_robo4/robocode.sound/src/main/resources/net/sf/robocode/sound/sounds/13831_adcbicycle_22.wav create mode 100644 代码/workspace_robo4/robocode.sound/src/main/resources/net/sf/robocode/sound/sounds/explode.wav create mode 100644 代码/workspace_robo4/robocode.sound/src/main/resources/net/sf/robocode/sound/sounds/shellhit.wav create mode 100644 代码/workspace_robo4/robocode.sound/src/main/resources/net/sf/robocode/sound/sounds/zap.wav create mode 100644 代码/workspace_robo4/robocode.tests.robots/.classpath create mode 100644 代码/workspace_robo4/robocode.tests.robots/.project create mode 100644 代码/workspace_robo4/robocode.tests.robots/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.tests.robots/pom.xml create mode 100644 代码/workspace_robo4/robocode.tests.robots/robocode.tests.robots.iml create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLonger.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/NoPackageShortName.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/robocode/BadNamespace.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/Ahead.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BadFirePower.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BattleLost.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BattleWin.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BodyTurnRate.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorHttpAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorReflectionAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorSocketAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/CustomEvents.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat1.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat2.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat3.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DieFast.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/EnvAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/EventPriorityFilter.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FairPlay.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileOutputStreamAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileWriteSize.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/GunHeat.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/GunTurnRate.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/HttpAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/InteruptibleEvent.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/JuniorEvents.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/MaxTurnRate.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/MaxVelocity.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/PrivateConstructor.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RadarTurnRateAndSetAdjust.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/Random.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RateControl.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ReflectionAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ReverseDirection.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RobotDeathEvents.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/SkipTurns.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/SocketAttack.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/TooLongNameThisIsReallyTooLongName.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/WatchBullets.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/java/tooLongNamespaceThisIsReallyTooLongNamespace/TooLongNamespace.java create mode 100644 代码/workspace_robo4/robocode.tests.robots/src/main/resources/tested/robots/TestTeam.team create mode 100644 代码/workspace_robo4/robocode.tests/.classpath create mode 100644 代码/workspace_robo4/robocode.tests/.project create mode 100644 代码/workspace_robo4/robocode.tests/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.tests/config/robocode.properties create mode 100644 代码/workspace_robo4/robocode.tests/pom.xml create mode 100644 代码/workspace_robo4/robocode.tests/robocode.tests.iml create mode 100644 代码/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/RobocodeTestBed.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/core/util/AlphanumericComparatorTest.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/host/security/RobotClassLoaderTest.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestAcceleration.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestAwtAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestBodyTurnRate.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestBulletPower.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorAwtAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorHttpAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorReflectionAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorSocketAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorThreadAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestCustomEvents.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestDuplicatesAndScore.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestEnvAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestEventPriorityFilter.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFairPlay.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileOutputStreamAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileWrite.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileWriteSize.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestGunHeat.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestGunTurnRate.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestHttpAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestIncludeNamespaceAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestInteruptibleEvent.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestJunior.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestLost.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestMaxTurnRate.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestMaxVelocity.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestNames.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestPosition.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestPrivateConstructor.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRadarTurnRateAndSetAdjust.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRandom.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRankingsWithTargetRobots.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRateControl.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestReflectionAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestReverseDirection.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRobotDeathEvents.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestScoring.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestSkippedTurns.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestSocketAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestThreadAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestThreadGroupAttack.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestUndeadThread.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestWatchBullet.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestWin.java create mode 100644 代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/samples/RobocodeRunner.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/.classpath create mode 100644 代码/workspace_robo4/robocode.ui.editor/.project create mode 100644 代码/workspace_robo4/robocode.ui.editor/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.ui.editor/pom.xml create mode 100644 代码/workspace_robo4/robocode.ui.editor/robocode.ui.editor.iml create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompilerPreferencesDialog.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompilerProperties.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompoundUndoManager.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorPane.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorPanel.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorThemeConfigDialog.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/FindReplaceDialog.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/FontStyle.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/IEditorProperties.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/JavaDocument.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/LineHighlighter.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/LineNumberArea.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/Module.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/MoreWindowsDialog.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeCompiler.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeCompilerFactory.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeEditor.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeEditorMenuBar.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/StyledDocument.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/UndoManagerWithActions.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ColorAndStyle.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ColorAndStyleAdapter.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ComboBoxUtil.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorProperties.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorPropertiesManager.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemeProperties.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemePropertiesManager.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemePropertyChangeAdapter.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IColorAndStyleListener.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IEditorThemeProperties.java create mode 100644 代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IEditorThemePropertyChangeListener.java create mode 100644 代码/workspace_robo4/robocode.ui/.classpath create mode 100644 代码/workspace_robo4/robocode.ui/.project create mode 100644 代码/workspace_robo4/robocode.ui/.settings/org.eclipse.jdt.core.prefs create mode 100644 代码/workspace_robo4/robocode.ui/pom.xml create mode 100644 代码/workspace_robo4/robocode.ui/robocode.ui.iml create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/BrowserManager.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/CheckList.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IImageManager.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IRobotDialogManager.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IWindowManagerExt.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/ImageManager.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/Module.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/RobotDialogManager.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/BattleField.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/BattleView.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/InteractiveHandler.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/MirroredGraphics.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/ScreenshotUtil.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/AboutBox.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/AvailableRobotsPanel.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BaseScoreDialog.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BattleButton.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BattleDialog.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ConsoleDialog.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ConsoleScrollPane.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/MenuBar.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/NewBattleDialog.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/NewBattleRulesTab.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesCommonOptionsTab.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesDevelopmentOptionsTab.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesDialog.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesRenderingOptionsTab.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesSoundOptionsTab.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesViewOptionsTab.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RankingDialog.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RcSplashScreen.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ResultsDialog.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ResultsTableCellRenderer.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobocodeFrame.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotButton.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotDescriptionPanel.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotDialog.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotExtractor.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotSelectionPanel.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/TeamCreator.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/TeamCreatorOptionsPanel.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WindowPositionManager.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WindowUtil.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/Wizard.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardCardPanel.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardController.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardListener.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardPanel.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardTabbedPane.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/editor/IRobocodeEditor.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/ColorUtil.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/GraphicsState.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/ImageUtil.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RenderImage.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RenderObject.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RobocodeLogo.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/ConfirmPanel.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/FilenamePanel.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/PackagerOptionsPanel.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/RobotPackager.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/LimitedClassnameDocument.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/LimitedDocument.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/ShortcutUtil.java create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/html/about.html create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/html/transparent.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/icons/robocode-icon.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/.cvsignore create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/body.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/.cvsignore create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-1.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-10.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-11.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-12.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-13.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-14.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-15.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-16.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-17.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-2.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-3.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-4.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-5.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-6.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-7.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-8.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-9.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-1.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-10.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-11.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-12.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-13.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-14.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-15.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-16.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-17.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-18.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-19.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-2.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-20.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-21.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-22.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-23.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-24.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-25.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-26.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-27.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-28.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-29.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-3.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-30.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-31.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-32.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-33.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-34.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-35.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-36.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-37.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-38.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-39.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-4.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-40.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-41.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-42.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-43.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-44.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-45.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-46.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-47.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-48.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-49.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-5.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-50.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-51.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-52.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-53.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-54.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-55.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-56.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-57.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-58.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-59.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-6.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-60.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-61.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-62.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-63.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-64.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-65.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-66.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-67.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-68.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-69.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-7.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-70.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-71.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-8.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-9.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/.cvsignore create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_0.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_1.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_2.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_3.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_4.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/explode_debris.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/radar.png create mode 100644 代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/turret.png create mode 100644 代码/workspace_robo4/super-pom/.project create mode 100644 代码/workspace_robo4/super-pom/pom.xml create mode 100644 代码/workspace_robo4/super-pom/robocode-license-header.txt create mode 100644 代码/workspace_robo4/tools/.gitignore create mode 100644 代码/workspace_robo4/tools/.project create mode 100644 代码/workspace_robo4/tools/bin/ant.bat create mode 100644 代码/workspace_robo4/tools/bin/ant.sh create mode 100644 代码/workspace_robo4/tools/bin/m2.conf create mode 100644 代码/workspace_robo4/tools/bin/mvn.bat create mode 100644 代码/workspace_robo4/tools/bin/mvn.sh create mode 100644 代码/workspace_robo4/tools/debugall/all.iml create mode 100644 代码/workspace_robo4/tools/jacobe/.gitignore create mode 100644 代码/workspace_robo4/tools/jacobe/ReadMe.txt create mode 100644 代码/workspace_robo4/tools/jacobe/robocode.cfg create mode 100644 代码/workspace_robo4/tools/licenses/ant-LICENSE.txt create mode 100644 代码/workspace_robo4/tools/licenses/ant-NOTICE.txt create mode 100644 代码/workspace_robo4/tools/licenses/mvn-LICENSE.txt create mode 100644 代码/workspace_robo4/tools/licenses/mvn-NOTICE.txt create mode 100644 代码/workspace_robo4/tools/loadTools.cmd create mode 100644 代码/workspace_robo4/tools/loadTools.sh create mode 100644 代码/workspace_robo4/tools/loader/Loader.java create mode 100644 代码/workspace_robo4/versions.md diff --git a/代码/workspace_robo4/.gitignore b/代码/workspace_robo4/.gitignore new file mode 100644 index 0000000..4a87a74 --- /dev/null +++ b/代码/workspace_robo4/.gitignore @@ -0,0 +1,11 @@ +.metadata +target +build.xml +maven-build.xml +maven-build.properties +/plugins/dotnet/robocode.dotnet.samples/src/robocode.dotnet.samples.sln +/plugins/dotnet/robocode.dotnet.samples/src/robocode.dotnet.samples.suo +ucdetector_reports +/plugins/dotnet/*.suo +*.class +.recommenders diff --git a/代码/workspace_robo4/README.md b/代码/workspace_robo4/README.md new file mode 100644 index 0000000..02440aa --- /dev/null +++ b/代码/workspace_robo4/README.md @@ -0,0 +1,12 @@ +Robocode +=================== +*Build the best - destroy the rest!* + +Robocode is a programming game, where the goal is to develop a robot battle tank to battle against other tanks in Java or .NET. The robot battles are running in real-time and on-screen. + +Read [Introduction] (http://robocode.sourceforge.net/docs/ReadMe.html) +Continue reading on [Robocode home page] (http://robocode.sourceforge.net/) +Learn from community at [RoboWiki] (http://robowiki.net/) +Talk to developers at [robocode-developers] (http://groups.google.com/group/robocode-developers) + +Enjoy! \ No newline at end of file diff --git a/代码/workspace_robo4/RemoteSystemsTempFiles/.project b/代码/workspace_robo4/RemoteSystemsTempFiles/.project new file mode 100644 index 0000000..5447a64 --- /dev/null +++ b/代码/workspace_robo4/RemoteSystemsTempFiles/.project @@ -0,0 +1,12 @@ + + + RemoteSystemsTempFiles + + + + + + + org.eclipse.rse.ui.remoteSystemsTempNature + + diff --git a/代码/workspace_robo4/jacobe.cmd b/代码/workspace_robo4/jacobe.cmd new file mode 100644 index 0000000..6c4a0e8 --- /dev/null +++ b/代码/workspace_robo4/jacobe.cmd @@ -0,0 +1,17 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + + +@rem NOTE: Here we expect jacobe.exe to be installed on system PATH + +@echo off +if exist "%~dp0\tools\lib\jacobe.jar" goto jacobe +call "%~dp0\tools\loadTools.cmd" + +:jacobe +call "%~dp0\tools\bin\ant.bat" -buildfile "%~dp0\tools\jacobe\build.xml" \ No newline at end of file diff --git a/代码/workspace_robo4/jacobe.sh b/代码/workspace_robo4/jacobe.sh new file mode 100644 index 0000000..4450e4e --- /dev/null +++ b/代码/workspace_robo4/jacobe.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +# NOTE: Here we expect the jacobe tools to be installed on PATH + +dp0=${0%/*} + +if [ ! -f $dp0/tools/lib/ant-launcher.jar ]; then + $dp0/tools/loadTools.sh +elif [ ! -f $dp0/tools/lib/ant.jar ]; then + $dp0/tools/loadTools.sh +elif [ ! -f $dp0/tools/lib/jacobe.jar ]; then + $dp0/tools/loadTools.sh +fi + +export CLASSPATH=$CLASSPATH:$dp0/tools/lib/ant-launcher.jar:$dp0/tools/lib/ant.jar:$dp0/tools/lib/jacobe.jar +$dp0/tools/bin/ant.sh -buildfile $dp0/tools/jacobe/build.xml + diff --git a/代码/workspace_robo4/mvn.cmd b/代码/workspace_robo4/mvn.cmd new file mode 100644 index 0000000..133774c --- /dev/null +++ b/代码/workspace_robo4/mvn.cmd @@ -0,0 +1,15 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off + +if not exist "%~dp0\tools\lib\maven-*-uber.jar" ( + call "%~dp0\tools\loadTools.cmd" +) + +call "%~dp0\tools\bin\mvn.bat" %* \ No newline at end of file diff --git a/代码/workspace_robo4/mvn.sh b/代码/workspace_robo4/mvn.sh new file mode 100644 index 0000000..2ea9c12 --- /dev/null +++ b/代码/workspace_robo4/mvn.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +dp0=${0%/*} + +if [ ! -f $dp0/tools/lib/maven-*-uber.jar ]; then + $dp0/tools/loadTools.sh +fi + +$dp0/tools/bin/mvn.sh $* \ No newline at end of file diff --git a/代码/workspace_robo4/mvnassembly.cmd b/代码/workspace_robo4/mvnassembly.cmd new file mode 100644 index 0000000..fb10c4c --- /dev/null +++ b/代码/workspace_robo4/mvnassembly.cmd @@ -0,0 +1,12 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off + +mvn clean install ant:ant -DskipTests=false %* +rem mvn eclipse:eclipse \ No newline at end of file diff --git a/代码/workspace_robo4/mvnassembly.sh b/代码/workspace_robo4/mvnassembly.sh new file mode 100644 index 0000000..a498a71 --- /dev/null +++ b/代码/workspace_robo4/mvnassembly.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +./mvn.sh clean install ant:ant -DskipTests=false $* +#./mvn.sh eclipse:eclipse \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/.project b/代码/workspace_robo4/plugins/.project new file mode 100644 index 0000000..0ab6892 --- /dev/null +++ b/代码/workspace_robo4/plugins/.project @@ -0,0 +1,11 @@ + + + plugins + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/ReadMe.txt b/代码/workspace_robo4/plugins/dotnet/ReadMe.txt new file mode 100644 index 0000000..7466121 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/ReadMe.txt @@ -0,0 +1,88 @@ +==== + Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://robocode.sourceforge.net/license/epl-v10.html +==== + +This is guide to build Robocode for .NET + +REQUIRED TOOLS FOR BUILDING THE ROBOCODE .NET PLUG-IN +===================================================== + +Microsoft C# Compiler and .NET SDK +---------------------------------- +- You need C# compiler and .NET SDK at least 4.0: + http://www.microsoft.com/en-us/download/details.aspx?id=17851 + +- Best option is to install Visual Studio C# Express 2010 or newer. + +- NOTE: Make sure you have csc.exe on PATH. + +Microsoft HTML Help 1 Compiler and Sandcastle Help File Builder +--------------------------------------------------------------- +- 'HTML Help 1 compiler' must be installed on the system - required by the + Sandcastle Help File Builder (SHFB) + + HTML Help 1 compiler: + http://msdn.microsoft.com/en-us/library/ms669985(VS.85).aspx + +- Sandcastle Help File Builder (SHFB) must be installed on the system. + http://shfb.codeplex.com/ + + NOTE: When installing the SHFB, you don't need to install HTML Help 2 as + only version 1 is used for Robocode. + +Java Development Kit (JDK) and JAVA_HOME path +--------------------------------------------- +- Oracle JDK 6 or newer must be installed on the system: + http://www.oracle.com/technetwork/java/javase/downloads + +- NOTE: Make sure to install the proper version (32 or 64-bit) depending on the + system. + + +HOW TO BUILD THE ROBOCODE .NET PLUG-IN +====================================== + +1) Build the regular part of Robocode first with 'mvn install' + (or mvnassembly.cmd) from source code root directory of Robocode. + +2) CD (change directory) to \plugins\dotnet + +3) Run: tools\loadTools.cmd + +4) Run: tools\keys\gennetkey.cmd + +5) Run: mvnassembly.cmd (standing in the \plugins\dotnet directory) + +9) Find the resulting distribution file for the Robocode .NET plug-in named + robocode.dotnet-x.x.x.x-setup.jar within this directory: + \plugins\dotnet\robocode.dotnet.distribution\target\ + + +HOW TO BUILD NEW PROXY CLASSES USING JNI4NET +============================================ +Robocode uses Jni4net (http://jni4net.com/) to bridge the .NET and Java parts +of Robocode. Only the .NET plug-in is written for the Microsoft .NET platform. +The rest of Robocode is build for the Java platform. + +When changing the public APIs or internal classes of Robocode it is important +that the corresponding .NET classes are updated as well. Some classes for the +.NET are handwritten. Other parts are auto-generated using the Jni4Net proxygen +tool (details are provided here: http://jni4net.com/). + +In order to update all the auto-generated source files for the .NET plugin you +must: + +1) CD (change directory) to \plugins\dotnet + +2) Run: generateProxies.cmd + +NOTE: You might need to remove the 'rem' and change the following lines inside + the generateProxies.cmd in order to force the JAVA_HOME and PATH to the + correct Java version: + +rem set JAVA_HOME=%JDK6_HOME% +rem set PATH=%JAVA_HOME%\bin;%PATH% \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/generateProxies.cmd b/代码/workspace_robo4/plugins/dotnet/generateProxies.cmd new file mode 100644 index 0000000..4b0c808 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/generateProxies.cmd @@ -0,0 +1,41 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off + +rem set JAVA_HOME=%JDK6_HOME% +rem set PATH=%JAVA_HOME%\bin;%PATH% + +set NET_FRAMEWORK_HOME=C:\Windows\Microsoft.NET\Framework\v3.5 +set PATH=%NET_FRAMEWORK_HOME%;%PATH% + +if exist "%~dp0\tools\lib\proxygen.exe" goto gen +call "%~dp0\tools\loadTools.cmd" + +:gen +"%~dp0\tools\lib\proxygen.exe" tools\proxygen\robocode.control.proxygen.xml +"%~dp0\tools\lib\proxygen.exe" tools\proxygen\robocode.proxygen.xml + +if exist "%~dp0\robocode.dotnet.nhost\target\robocode.dotnet.nhost.dll" goto gen1 +echo cat't find robocode.dotnet.nhost\target\robocode.dotnet.nhost.dll, please compile it +goto end + +:gen1 +if exist "%~dp0\tools\lib\robocode.dll" goto gen3 +if exist "%~dp0\robocode.dotnet.api\target\robocode.dll" goto gen2 +echo cat't find \robocode.dotnet.api\target\robocode.dll, please compile it +goto end + +:gen2 + +copy "%~dp0\robocode.dotnet.api\target\robocode.dll" "%~dp0\tools\lib" + +:gen3 +"%~dp0\tools\lib\proxygen.exe" tools\proxygen\robocode.proxygen.net.xml + +:end \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/mvn.cmd b/代码/workspace_robo4/plugins/dotnet/mvn.cmd new file mode 100644 index 0000000..17e6ed1 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/mvn.cmd @@ -0,0 +1,20 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off + +if not exist "%~dp0\tools\lib" ( + mkdir "%~dp0\tools\lib" + call "%~dp0\tools\loadTools.cmd" +) + +if not exist "%~dp0\..\..\tools\lib\maven-*-uber.jar" ( + call "%~dp0\..\..\tools\loadTools.cmd" +) + +call "%~dp0\..\..\mvn" %* \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/mvnassembly.cmd b/代码/workspace_robo4/plugins/dotnet/mvnassembly.cmd new file mode 100644 index 0000000..fb10c4c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/mvnassembly.cmd @@ -0,0 +1,12 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off + +mvn clean install ant:ant -DskipTests=false %* +rem mvn eclipse:eclipse \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/pom.xml b/代码/workspace_robo4/plugins/dotnet/pom.xml new file mode 100644 index 0000000..c063b01 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + robocode.dotnet + .NET Robocode + ${robocode.dotnet.version} + pom + + net.sf.robocode + robocode + ${robocode.version} + ../.. + + + + jni4net.repo + jni4net Repository + http://jni4net.googlecode.com/svn/mvnrepo + + + aduna.repo + Aduna Repository + http://repository.aduna-software.org/maven2/ + + + + robocode.dotnet.api + robocode.dotnet.control.api + robocode.dotnet.content + robocode.dotnet.distribution + robocode.dotnet.host + robocode.dotnet.nhost + robocode.dotnet.ntests + robocode.dotnet.robotscs + robocode.dotnet.installer + robocode.dotnet.samples + robocode.dotnet.tests + + + + + + org.sonatype.nmaven.plugins + maven-dotnet-compiler-plugin + true + 0.17robocode + + + org.sonatype.nmaven.plugins + maven-dotnet-test-plugin + 0.17robocode + + + org.jvnet.maven-antrun-extended-plugin + maven-antrun-extended-plugin + 1.43 + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/.project new file mode 100644 index 0000000..3b435ab --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/.project @@ -0,0 +1,8 @@ + + + robocode.dotnet.api + .NET Robot API for Robocode. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..070758f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +#Tue Nov 27 22:34:10 CET 2012 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 +encoding/src/main/resources=8859_1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/test/resources=8859_1 +encoding/src=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/pom.xml new file mode 100644 index 0000000..cc1a6fc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + robocode.dotnet.api + Robocode .NET Robot API + .NET Robot API for Robocode + dotnet:library + + robocode.dotnet + net.sf.robocode + ${robocode.dotnet.version} + + + robocode + src + + + org.sonatype.nmaven.plugins + maven-dotnet-compiler-plugin + + /unsafe /warn:0 /nowarn:1591 /keyfile:"${basedir}/../tools/keys/robocode.snk" + robocode.dll + + + + org.jvnet.maven-antrun-extended-plugin + maven-antrun-extended-plugin + + + process-classes + + + + + + + + + + + run + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/robocode.dotnet.api.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/robocode.dotnet.api.iml new file mode 100644 index 0000000..284265c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/robocode.dotnet.api.iml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/robotAPI.shfbproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/robotAPI.shfbproj new file mode 100644 index 0000000..b0d9b8a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/robotAPI.shfbproj @@ -0,0 +1,87 @@ + + + + + Debug + AnyCPU + 2.0 + {90f0d09b-f58d-4f2e-ac8a-164d89979ef1} + 1.9.5.0 + + Documentation + Documentation + Documentation + + .\target\Help\ + RobotAPI + + + + + AutoDocumentCtors, AutoDocumentDispose + Robocode Robot API for .NET + .NET Framework 3.5 + HtmlHelp1, Website + + + + + + + + + + + + + + + + + + + + + + + + + + InheritedMembers, Protected, SealedProtected + + Robot API used for writing robots for Robocode + Robot Interfaces used for creating new robot types, e.g. with other programming languages. + Robot peers available for implementing new robot types based on the Robot Interfaces. + Utility classes that can be used when writing robots. Kept for compatibility with legacy robots. + + Robocode Robot API for .NET + Copyright %28c%29 2001-2016 Mathew A. Nelson and Robocode contributors + fnl%40users.sourceforge.net + administator and maintainer of Robocode + vs2010 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/.gitignore b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/.gitignore new file mode 100644 index 0000000..880d47a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/.gitignore @@ -0,0 +1,3 @@ +/obj +/robocode.dotnet.api.sln +/robocode.dotnet.api.suo diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/AssemblyInf.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/AssemblyInf.cs new file mode 100644 index 0000000..e7376c7 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/AssemblyInf.cs @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System.Security; + +[assembly: AllowPartiallyTrustedCallers] \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/io/LoggerN.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/io/LoggerN.cs new file mode 100644 index 0000000..aeea87e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/io/LoggerN.cs @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.IO; +using System.Security.Permissions; +using System.Text; +using net.sf.robocode.security; + +namespace net.sf.robocode.io +{ +#pragma warning disable 1591 + ///

+ /// This is a class used for logging. + /// + /// + [RobocodeInternalPermission(SecurityAction.LinkDemand)] + public class LoggerN + { + public static TextWriter realOut = Console.Out; + public static TextWriter realErr = Console.Error; + public static TextWriter robotOut = Console.Out; + + private static ILoggerN logListener; + private static readonly StringBuilder logBuffer = new StringBuilder(); + [ThreadStatic] public static bool IsSafeThread; + + public static void setLogListener(ILoggerN logListener) + { + LoggerN.logListener = logListener; + } + + public static void logMessage(string s) + { + logMessage(s, true); + } + + public static void logMessage(Exception e) + { + logMessage(e.StackTrace); + } + + public static void logMessage(string message, Exception t) + { + logMessage(message + ":\n" + t.StackTrace); + } + + public static void logError(string message, Exception t) + { + logError(message + ":\n" + t.StackTrace); + } + + public static void logError(Exception t) + { + logError(t.StackTrace); + } + + public static void logMessage(string s, bool newline) + { + if (logListener == null) + { + if (newline) + { + realOut.WriteLine(s); + } + else + { + realOut.Write(s); + realOut.Flush(); + } + } + else + { + lock (logBuffer) + { + if (!IsSafeThread) + { + // we just queue it, to not let unsafe thread travel thru system + logBuffer.Append(s); + logBuffer.Append("\n"); + } + else if (newline) + { + logMessage(logBuffer + s, true); + logBuffer.Length = 0; + } + else + { + logBuffer.Append(s); + } + } + } + } + + public static void logError(string s) + { + if (logListener == null) + { + realErr.WriteLine(s); + } + else + { + logListener.logError(s); + } + } + + public static void WriteLineToRobotsConsole(string s) + { + if (robotOut != null) + { + robotOut.WriteLine(s); + } + else + { + logMessage(s); + } + } + } + + /// + public interface ILoggerN + { + void logMessage(string s, bool newline); + void logError(string s); + } +} + +//happy \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/Buffer.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/Buffer.cs new file mode 100644 index 0000000..f1e3056 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/Buffer.cs @@ -0,0 +1,508 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +// This class is based on the source code from Sun's Java 1.5.0 API for java.nio.Buffer, but +// rewritten for C# and .NET with the purpose to bridge the .NET and Java internals of Robocode. + +using System; +using System.Security.Permissions; +using net.sf.robocode.security; + +// ReSharper disable InconsistentNaming + +namespace net.sf.robocode.nio +{ +#pragma warning disable 1591 +#pragma warning disable 1570 + + /* + * A container for data of a specific primitive type. + * + *

A buffer is a linear, finite sequence of elements of a specific + * primitive type. Aside from its content, the essential properties of a + * buffer are its capacity, limit, and position:

+ * + *
+ * + *

A buffer's capacity is the number of elements it contains. The + * capacity of a buffer is never negative and never changes.

+ * + *

A buffer's limit is the index of the first element that should + * not be read or written. A buffer's limit is never negative and is never + * greater than its capacity.

+ * + *

A buffer's position is the index of the next element to be + * read or written. A buffer's position is never negative and is never + * greater than its limit.

+ * + *
+ * + *

There is one subclass of this class for each non-boolean primitive type. + * + * + *

Transferring data

+ * + *

Each subclass of this class defines two categories of get and + * put operations:

+ * + *
+ * + *

Relative operations read or write one or more elements starting + * at the current position and then increment the position by the number of + * elements transferred. If the requested transfer exceeds the limit then a + * relative get operation throws a {@link BufferUnderflowException} + * and a relative put operation throws a {@link + * BufferOverflowException}; in either case, no data is transferred.

+ * + *

Absolute operations take an explicit element index and do not + * affect the position. Absolute get and put operations throw + * an {@link IndexOutOfBoundsException} if the index argument exceeds the + * limit.

+ * + *
+ * + *

Data may also, of course, be transferred in to or out of a buffer by the + * I/O operations of an appropriate channel, which are always relative to the + * current position. + * + * + *

Marking and resetting

+ * + *

A buffer's mark is the index to which its position will be reset + * when the {@link #reset reset} method is invoked. The mark is not always + * defined, but when it is defined it is never negative and is never greater + * than the position. If the mark is defined then it is discarded when the + * position or the limit is adjusted to a value smaller than the mark. If the + * mark is not defined then invoking the {@link #reset reset} method causes an + * {@link InvalidMarkException} to be thrown. + * + * + *

Invariants

+ * + *

The following invariant holds for the mark, position, limit, and + * capacity values: + * + *

+ * 0 <= + * mark <= + * position <= + * limit <= + * capacity + *
+ * + *

A newly-created buffer always has a position of zero and a mark that is + * undefined. The initial limit may be zero, or it may be some other value + * that depends upon the type of the buffer and the manner in which it is + * constructed. The initial content of a buffer is, in general, + * undefined. + * + * + *

Clearing, flipping, and rewinding

+ * + *

In addition to methods for accessing the position, limit, and capacity + * values and for marking and resetting, this class also defines the following + * operations upon buffers: + * + *

    + * + *
  • {@link #clear} makes a buffer ready for a new sequence of + * channel-read or relative put operations: It sets the limit to the + * capacity and the position to zero.

  • + * + *
  • {@link #flip} makes a buffer ready for a new sequence of + * channel-write or relative get operations: It sets the limit to the + * current position and then sets the position to zero.

  • + * + *
  • {@link #rewind} makes a buffer ready for re-reading the data that + * it already contains: It leaves the limit unchanged and sets the position + * to zero.

  • + * + *
+ * + * + *

Read-only buffers

+ * + *

Every buffer is readable, but not every buffer is writable. The + * mutation methods of each buffer class are specified as optional + * operations that will throw a {@link ReadOnlyBufferException} when + * invoked upon a read-only buffer. A read-only buffer does not allow its + * content to be changed, but its mark, position, and limit values are mutable. + * Whether or not a buffer is read-only may be determined by invoking its + * {@link #isReadOnly isReadOnly} method. + * + * + *

Thread safety

+ * + *

Buffers are not safe for use by multiple concurrent threads. If a + * buffer is to be used by more than one thread then access to the buffer + * should be controlled by appropriate synchronization. + * + * + *

Invocation chaining

+ * + *

Methods in this class that do not otherwise have a value to return are + * specified to return the buffer upon which they are invoked. This allows + * method invocations to be chained; for example, the sequence of statements + * + *

+     * b.flip();
+     * b.position(23);
+     * b.limit(42);
+ * + * can be replaced by the single, more compact statement + * + *
+     * b.flip().position(23).limit(42);
+ * + * + * @author Mark Reinhold + * @author JSR-51 Expert Group + * @version 1.35, 06/08/11 + * @since 1.4 + */ + + /// + [RobocodeInternalPermission(SecurityAction.LinkDemand)] + public abstract class Buffer + { + // Invariants: mark <= position <= limit <= capacity + private readonly int _capacity; + private int _limit; + private int _mark = -1; + private int _position; + + // Creates a new buffer with the given mark, position, limit, and capacity, + // after checking invariants. + // + protected Buffer(int mark, int pos, int lim, int cap) + { + // package-private + if (cap < 0) + throw new ArgumentException(); + _capacity = cap; + limit(lim); + position(pos); + if (mark >= 0) + { + if (mark > pos) + throw new ArgumentException(); + _mark = mark; + } + } + + /* + * Returns this buffer's capacity.

+ * + * @return The capacity of this buffer + */ + public int capacity() + { + return _capacity; + } + + /* + * Returns this buffer's position.

+ * + * @return The position of this buffer + */ + public int position() + { + return _position; + } + + /* + * Sets this buffer's position. If the mark is defined and larger than the + * new position then it is discarded.

+ * + * @param newPosition + * The new position value; must be non-negative + * and no larger than the current limit + * + * @return This buffer + * + * @throws ArgumentException + * If the preconditions on newPosition do not hold + */ + public Buffer position(int newPosition) + { + if ((newPosition > _limit) || (newPosition < 0)) + throw new ArgumentException(); + _position = newPosition; + if (_mark > _position) _mark = -1; + return this; + } + + /* + * Returns this buffer's limit.

+ * + * @return The limit of this buffer + */ + public int limit() + { + return _limit; + } + + /* + * Sets this buffer's limit. If the position is larger than the new limit + * then it is set to the new limit. If the mark is defined and larger than + * the new limit then it is discarded.

+ * + * @param newLimit + * The new limit value; must be non-negative + * and no larger than this buffer's capacity + * + * @return This buffer + * + * @throws ArgumentException + * If the preconditions on newLimit do not hold + */ + public Buffer limit(int newLimit) + { + if ((newLimit > _capacity) || (newLimit < 0)) + throw new ArgumentException(); + _limit = newLimit; + if (_position > _limit) _position = _limit; + if (_mark > _limit) _mark = -1; + return this; + } + + /* + * Sets this buffer's mark at its position.

+ * + * @return This buffer + */ + public Buffer mark() + { + _mark = _position; + return this; + } + + /* + * Resets this buffer's position to the previously-marked position. + * + *

Invoking this method neither changes nor discards the mark's + * value.

+ * + * @return This buffer + * + * @throws InvalidMarkException + * If the mark has not been set + */ + public Buffer reset() + { + int m = _mark; + if (m < 0) + throw new InvalidMarkException(); + _position = m; + return this; + } + + /* + * Clears this buffer. The position is set to zero, the limit is set to + * the capacity, and the mark is discarded. + * + *

Invoke this method before using a sequence of channel-read or + * put operations to fill this buffer. For example: + * + *

+         * buf.clear();     // Prepare buffer for reading
+         * in.read(buf);    // Read data
+ * + *

This method does not actually erase the data in the buffer, but it + * is named as if it did because it will most often be used in situations + * in which that might as well be the case.

+ * + * @return This buffer + */ + public Buffer clear() + { + _position = 0; + _limit = _capacity; + _mark = -1; + return this; + } + + /* + * Flips this buffer. The limit is set to the current position and then + * the position is set to zero. If the mark is defined then it is + * discarded. + * + *

After a sequence of channel-read or put operations, invoke + * this method to prepare for a sequence of channel-write or relative + * get operations. For example: + * + *

+         * buf.put(magic);    // Prepend header
+         * in.read(buf);      // Read data into rest of buffer
+         * buf.flip();        // Flip buffer
+         * out.write(buf);    // Write header + data to channel
+ * + *

This method is often used in conjunction with the {@link + * java.nio.ByteBuffer#compact compact} method when transferring data from + * one place to another.

+ * + * @return This buffer + */ + public Buffer flip() + { + _limit = _position; + _position = 0; + _mark = -1; + return this; + } + + /* + * Rewinds this buffer. The position is set to zero and the mark is + * discarded. + * + *

Invoke this method before a sequence of channel-write or get + * operations, assuming that the limit has already been set + * appropriately. For example: + * + *

+         * out.write(buf);    // Write remaining data
+         * buf.rewind();      // Rewind buffer
+         * buf.get(array);    // Copy data into array
+ * + * @return This buffer + */ + public Buffer rewind() + { + _position = 0; + _mark = -1; + return this; + } + + /* + * Returns the number of elements between the current position and the + * limit.

+ * + * @return The number of elements remaining in this buffer + */ + public int remaining() + { + return _limit - _position; + } + + /* + * Tells whether there are any elements between the current position and + * the limit.

+ * + * @return true if, and only if, there is at least one element + * remaining in this buffer + */ + public bool hasRemaining() + { + return _position < _limit; + } + + /* + * Tells whether or not this buffer is read-only.

+ * + * @return true if, and only if, this buffer is read-only + */ + public abstract bool isReadOnly(); + + + // -- Package-private methods for bounds checking, etc. -- + + /* + * Checks the current position against the limit, throwing a {@link + * BufferUnderflowException} if it is not smaller than the limit, and then + * increments the position.

+ * + * @return The current position value, before it is incremented + */ + internal int nextGetIndex() + { + // package-private + if (_position >= _limit) + throw new BufferUnderflowException(); + return _position++; + } + + internal int nextGetIndex(int nb) + { + // package-private + if (_limit - _position < nb) + throw new BufferUnderflowException(); + int p = _position; + _position += nb; + return p; + } + + /* + * Checks the current position against the limit, throwing a {@link + * BufferOverflowException} if it is not smaller than the limit, and then + * increments the position.

+ * + * @return The current position value, before it is incremented + */ + internal int nextPutIndex() + { + // package-private + if (_position >= _limit) + throw new BufferOverflowException(); + return _position++; + } + + internal int nextPutIndex(int nb) + { + // package-private + if (_limit - _position < nb) + throw new BufferOverflowException(); + int p = _position; + _position += nb; + return p; + } + + /* + * Checks the given index against the limit, throwing an {@link + * IndexOutOfBoundsException} if it is not smaller than the limit + * or is smaller than zero. + */ + internal int checkIndex(int i) + { + // package-private + if ((i < 0) || (i >= _limit)) + throw new IndexOutOfRangeException(); + return i; + } + + internal int checkIndex(int i, int nb) + { + // package-private + if ((i < 0) || (nb > _limit - i)) + throw new IndexOutOfRangeException(); + return i; + } + + internal int markValue() + { + // package-private + return _mark; + } + + internal void discardMark() + { + // package-private + _mark = -1; + } + + internal static void checkBounds(int off, int len, int size) + { + // package-private + if ((off | len | (off + len) | (size - (off + len))) < 0) + throw new IndexOutOfRangeException(); + } + } +#pragma warning restore 1591 +} + +// ReSharper restore InconsistentNaming \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/ByteBuffer.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/ByteBuffer.cs new file mode 100644 index 0000000..761a59f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/ByteBuffer.cs @@ -0,0 +1,1604 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +// This class is based on the source code from Sun's Java 1.5.0 API for java.nio.ByteBuffer, but +// rewritten for C# and .NET with the purpose to bridge the .NET and Java internals of Robocode. + +using System; +using System.Security.Permissions; +using System.Text; +using net.sf.robocode.security; + +// ReSharper disable InconsistentNaming + +namespace net.sf.robocode.nio +{ +#pragma warning disable 1591 +#pragma warning disable 1570 + /// + public enum ByteOrder + { + BIG_ENDIAN, + LITTLE_ENDIAN, + } + + /* + * A byte buffer. + * + *

This class defines six categories of operations upon + * byte buffers: + * + *

    + * + *
  • Absolute and relative {@link #get() get} and + * {@link #put(byte) put} methods that read and write + * single bytes;

  • + * + *
  • Relative {@link #get(byte[]) bulk get} + * methods that transfer contiguous sequences of bytes from this buffer + * into an array;

  • + * + *
  • Relative {@link #put(byte[]) bulk put} + * methods that transfer contiguous sequences of bytes from a + * byte array or some other byte + * buffer into this buffer;

  • + * + * + *
  • Absolute and relative {@link #getChar() get} + * and {@link #putChar(char) put} methods that read and + * write values of other primitive types, translating them to and from + * sequences of bytes in a particular byte order;

  • + * + *
  • Methods for creating view buffers, + * which allow a byte buffer to be viewed as a buffer containing values of + * some other primitive type; and

  • + * + * + *
  • Methods for {@link #compact compacting}, {@link + * #duplicate duplicating}, and {@link #slice + * slicing} a byte buffer.

  • + * + *
+ * + *

Byte buffers can be created either by {@link #allocate + * allocation}, which allocates space for the buffer's + * + * + * content, or by {@link #wrap(byte[]) wrapping} an + * existing byte array into a buffer. + * + * + * + * + *

Direct vs. non-direct buffers

+ * + *

A byte buffer is either direct or non-direct. Given a + * direct byte buffer, the Java virtual machine will make a best effort to + * perform native I/O operations directly upon it. That is, it will attempt to + * avoid copying the buffer's content to (or from) an intermediate buffer + * before (or after) each invocation of one of the underlying operating + * system's native I/O operations. + * + *

A direct byte buffer may be created by invoking the {@link + * #allocateDirect(int) allocateDirect} factory method of this class. The + * buffers returned by this method typically have somewhat higher allocation + * and deallocation costs than non-direct buffers. The contents of direct + * buffers may reside outside of the normal garbage-collected heap, and so + * their impact upon the memory footprint of an application might not be + * obvious. It is therefore recommended that direct buffers be allocated + * primarily for large, long-lived buffers that are subject to the underlying + * system's native I/O operations. In general it is best to allocate direct + * buffers only when they yield a measureable gain in program performance. + * + *

A direct byte buffer may also be created by {@link + * java.nio.channels.FileChannel#map mapping} a region of a file + * directly into memory. An implementation of the Java platform may optionally + * support the creation of direct byte buffers from native code via JNI. If an + * instance of one of these kinds of buffers refers to an inaccessible region + * of memory then an attempt to access that region will not change the buffer's + * content and will cause an unspecified exception to be thrown either at the + * time of the access or at some later time. + * + *

Whether a byte buffer is direct or non-direct may be determined by + * invoking its {@link #isDirect isDirect} method. This method is provided so + * that explicit buffer management can be done in performance-critical code. + * + * + * + *

Access to binary data

+ * + *

This class defines methods for reading and writing values of all other + * primitive types, except boolean. Primitive values are translated + * to (or from) sequences of bytes according to the buffer's current byte + * order, which may be retrieved and modified via the {@link #order order} + * methods. Specific byte orders are represented by instances of the {@link + * ByteOrder} class. The initial order of a byte buffer is always {@link + * ByteOrder#BIG_ENDIAN BIG_ENDIAN}. + * + *

For access to heterogeneous binary data, that is, sequences of values of + * different types, this class defines a family of absolute and relative + * get and put methods for each type. For 32-bit floating-point + * values, for example, this class defines: + * + *

+     * float  {@link #getFloat()}
+     * float  {@link #getFloat(int) getFloat(int index)}
+     *  void  {@link #putFloat(float) putFloat(float f)}
+     *  void  {@link #putFloat(int,float) putFloat(int index, float f)}
+ * + *

Corresponding methods are defined for the types char, + * short, int, long, and double. The index + * parameters of the absolute get and put methods are in terms of + * bytes rather than of the type being read or written. + * + * + * + *

For access to homogeneous binary data, that is, sequences of values of + * the same type, this class defines methods that can create views of a + * given byte buffer. A view buffer is simply another buffer whose + * content is backed by the byte buffer. Changes to the byte buffer's content + * will be visible in the view buffer, and vice versa; the two buffers' + * position, limit, and mark values are independent. The {@link + * #asFloatBuffer() asFloatBuffer} method, for example, creates an instance of + * the {@link FloatBuffer} class that is backed by the byte buffer upon which + * the method is invoked. Corresponding view-creation methods are defined for + * the types char, short, int, long, and + * double. + * + *

View buffers have three important advantages over the families of + * type-specific get and put methods described above: + * + *

+ * + *

The byte order of a view buffer is fixed to be that of its byte buffer + * at the time that the view is created.

+ * + * + *

Invocation chaining

+ * + *

Methods in this class that do not otherwise have a value to return are + * specified to return the buffer upon which they are invoked. This allows + * method invocations to be chained. + * + * + * The sequence of statements + * + *

+     * bb.putInt(0xCAFEBABE);
+     * bb.putShort(3);
+     * bb.putShort(45);
+ * + * can, for example, be replaced by the single statement + * + *
+     * bb.putInt(0xCAFEBABE).putShort(3).putShort(45);
+ * + * + * + * @author Mark Reinhold + * @author JSR-51 Expert Group + * @version 1.56, 04/07/16 + * @since 1.4 + */ + + /// + [RobocodeInternalPermission(SecurityAction.LinkDemand)] + public abstract class ByteBuffer : Buffer //, Comparable + { + // These fields are declared here rather than in Heap-X-Buffer in order to + // reduce the number of virtual method invocations needed to access these + // values, which is especially costly when coding small buffers. + // + internal int _offset; + + internal bool bigEndian // package-private + = true; + + internal byte[] hb; // Non-null only for heap buffers + + internal bool nativeByteOrder // package-private + = true; + + // Creates a new buffer with the given mark, position, limit, capacity, + // backing array, and array offset + // + internal ByteBuffer(int mark, int pos, int lim, int cap, // package-private + byte[] hb, int offset) + : base(mark, pos, lim, cap) + { + this.hb = hb; + _offset = offset; + } + + // Creates a new buffer with the given mark, position, limit, and capacity + // + internal ByteBuffer(int mark, int pos, int lim, int cap) + : this(mark, pos, lim, cap, null, 0) + { + // package-private + } + + + /* + * Allocates a new direct byte buffer. + * + *

The new buffer's position will be zero, its limit will be its + * capacity, and its mark will be undefined. Whether or not it has a + * {@link #hasArray backing array} is unspecified.

+ * + * @param capacity + * The new buffer's capacity, in bytes + * + * @return The new byte buffer + * + * @throws ArgumentException + * If the capacity is a negative integer + */ + + public static ByteBuffer allocateDirect(int capacity) + { + if (capacity < 0) + throw new ArgumentException(); + return new HeapByteBuffer(capacity, capacity); + } + + + /* + * Allocates a new byte buffer. + * + *

The new buffer's position will be zero, its limit will be its + * capacity, and its mark will be undefined. It will have a {@link #array + * backing array}, and its {@link #arrayOffset array + * offset} will be zero. + * + * @param capacity + * The new buffer's capacity, in bytes + * + * @return The new byte buffer + * + * @throws ArgumentException + * If the capacity is a negative integer + */ + + public static ByteBuffer allocate(int capacity) + { + if (capacity < 0) + throw new ArgumentException(); + return new HeapByteBuffer(capacity, capacity); + } + + /* + * Wraps a byte array into a buffer. + * + *

The new buffer will be backed by the given byte array; + * that is, modifications to the buffer will cause the array to be modified + * and vice versa. The new buffer's capacity will be + * array.length, its position will be offset, its limit + * will be offset + length, and its mark will be undefined. Its + * {@link #array backing array} will be the given array, and + * its {@link #arrayOffset array offset} will be zero.

+ * + * @param array + * The array that will back the new buffer + * + * @param offset + * The offset of the subarray to be used; must be non-negative and + * no larger than array.length. The new buffer's position + * will be set to this value. + * + * @param length + * The length of the subarray to be used; + * must be non-negative and no larger than + * array.length - offset. + * The new buffer's limit will be set to offset + length. + * + * @return The new byte buffer + * + * @throws IndexOutOfBoundsException + * If the preconditions on the offset and length + * parameters do not hold + */ + + public static ByteBuffer wrap(byte[] array, + int offset, int length) + { + try + { + return new HeapByteBuffer(array, offset, length); + } + catch (ArgumentException) + { + throw new IndexOutOfRangeException(); + } + } + + /* + * Wraps a byte array into a buffer. + * + *

The new buffer will be backed by the given byte array; + * that is, modifications to the buffer will cause the array to be modified + * and vice versa. The new buffer's capacity and limit will be + * array.length, its position will be zero, and its mark will be + * undefined. Its {@link #array backing array} will be the + * given array, and its {@link #arrayOffset array offset} will + * be zero.

+ * + * @param array + * The array that will back this buffer + * + * @return The new byte buffer + */ + + public static ByteBuffer wrap(byte[] array) + { + return wrap(array, 0, array.Length); + } + + + /* + * Creates a new byte buffer whose content is a shared subsequence of + * this buffer's content. + * + *

The content of the new buffer will start at this buffer's current + * position. Changes to this buffer's content will be visible in the new + * buffer, and vice versa; the two buffers' position, limit, and mark + * values will be independent. + * + *

The new buffer's position will be zero, its capacity and its limit + * will be the number of bytes remaining in this buffer, and its mark + * will be undefined. The new buffer will be direct if, and only if, this + * buffer is direct, and it will be read-only if, and only if, this buffer + * is read-only.

+ * + * @return The new byte buffer + */ + public abstract ByteBuffer slice(); + + /* + * Creates a new byte buffer that shares this buffer's content. + * + *

The content of the new buffer will be that of this buffer. Changes + * to this buffer's content will be visible in the new buffer, and vice + * versa; the two buffers' position, limit, and mark values will be + * independent. + * + *

The new buffer's capacity, limit, position, and mark values will be + * identical to those of this buffer. The new buffer will be direct if, + * and only if, this buffer is direct, and it will be read-only if, and + * only if, this buffer is read-only.

+ * + * @return The new byte buffer + */ + public abstract ByteBuffer duplicate(); + + /* + * Creates a new, read-only byte buffer that shares this buffer's + * content. + * + *

The content of the new buffer will be that of this buffer. Changes + * to this buffer's content will be visible in the new buffer; the new + * buffer itself, however, will be read-only and will not allow the shared + * content to be modified. The two buffers' position, limit, and mark + * values will be independent. + * + *

The new buffer's capacity, limit, position, and mark values will be + * identical to those of this buffer. + * + *

If this buffer is itself read-only then this method behaves in + * exactly the same way as the {@link #duplicate duplicate} method.

+ * + * @return The new, read-only byte buffer + */ + public abstract ByteBuffer asReadOnlyBuffer(); + + + // -- Singleton get/put methods -- + + /* + * Relative get method. Reads the byte at this buffer's + * current position, and then increments the position.

+ * + * @return The byte at the buffer's current position + * + * @throws BufferUnderflowException + * If the buffer's current position is not smaller than its limit + */ + public abstract byte get(); + + /* + * Relative put method  (optional operation). + * + *

Writes the given byte into this buffer at the current + * position, and then increments the position.

+ * + * @param b + * The byte to be written + * + * @return This buffer + * + * @throws BufferOverflowException + * If this buffer's current position is not smaller than its limit + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer put(byte b); + + /* + * Absolute get method. Reads the byte at the given + * index.

+ * + * @param index + * The index from which the byte will be read + * + * @return The byte at the given index + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit + */ + public abstract byte get(int index); + + /* + * Absolute put method  (optional operation). + * + *

Writes the given byte into this buffer at the given + * index.

+ * + * @param index + * The index at which the byte will be written + * + * @param b + * The byte value to be written + * + * @return This buffer + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer put(int index, byte b); + + + // -- Bulk get operations -- + + /* + * Relative bulk get method. + * + *

This method transfers bytes from this buffer into the given + * destination array. If there are fewer bytes remaining in the + * buffer than are required to satisfy the request, that is, if + * length > remaining(), then no + * bytes are transferred and a {@link BufferUnderflowException} is + * thrown. + * + *

Otherwise, this method copies length bytes from this + * buffer into the given array, starting at the current position of this + * buffer and at the given offset in the array. The position of this + * buffer is then incremented by length. + * + *

In other words, an invocation of this method of the form + * src.get(dst, off, len) has exactly the same effect as + * the loop + * + *

+     *     for (int i = off; i < off + len; i++)
+     *         dst[i] = src.get(); 
+ * + * except that it first checks that there are sufficient bytes in + * this buffer and it is potentially much more efficient.

+ * + * @param dst + * The array into which bytes are to be written + * + * @param offset + * The offset within the array of the first byte to be + * written; must be non-negative and no larger than + * dst.length + * + * @param length + * The maximum number of bytes to be written to the given + * array; must be non-negative and no larger than + * dst.length - offset + * + * @return This buffer + * + * @throws BufferUnderflowException + * If there are fewer than length bytes + * remaining in this buffer + * + * @throws IndexOutOfBoundsException + * If the preconditions on the offset and length + * parameters do not hold + */ + + public virtual ByteBuffer get(byte[] dst, int offset, int length) + { + checkBounds(offset, length, dst.Length); + if (length > remaining()) + throw new BufferUnderflowException(); + int end = offset + length; + for (int i = offset; i < end; i++) + dst[i] = get(); + return this; + } + + /* + * Relative bulk get method. + * + *

This method transfers bytes from this buffer into the given + * destination array. An invocation of this method of the form + * src.get(a) behaves in exactly the same way as the invocation + * + *

+     *     src.get(a, 0, a.length) 
+ * + * @return This buffer + * + * @throws BufferUnderflowException + * If there are fewer than length bytes + * remaining in this buffer + */ + + public ByteBuffer get(byte[] dst) + { + return get(dst, 0, dst.Length); + } + + + // -- Bulk put operations -- + + /* + * Relative bulk put method  (optional operation). + * + *

This method transfers the bytes remaining in the given source + * buffer into this buffer. If there are more bytes remaining in the + * source buffer than in this buffer, that is, if + * src.remaining() > remaining(), + * then no bytes are transferred and a {@link + * BufferOverflowException} is thrown. + * + *

Otherwise, this method copies + * n = src.remaining() bytes from the given + * buffer into this buffer, starting at each buffer's current position. + * The positions of both buffers are then incremented by n. + * + *

In other words, an invocation of this method of the form + * dst.put(src) has exactly the same effect as the loop + * + *

+     *     while (src.hasRemaining())
+     *         dst.put(src.get()); 
+ * + * except that it first checks that there is sufficient space in this + * buffer and it is potentially much more efficient.

+ * + * @param src + * The source buffer from which bytes are to be read; + * must not be this buffer + * + * @return This buffer + * + * @throws BufferOverflowException + * If there is insufficient space in this buffer + * for the remaining bytes in the source buffer + * + * @throws ArgumentException + * If the source buffer is this buffer + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + + public virtual ByteBuffer put(ByteBuffer src) + { + if (src == this) + throw new ArgumentException(); + int n = src.remaining(); + if (n > remaining()) + throw new BufferOverflowException(); + for (int i = 0; i < n; i++) + put(src.get()); + return this; + } + + /* + * Relative bulk put method  (optional operation). + * + *

This method transfers bytes into this buffer from the given + * source array. If there are more bytes to be copied from the array + * than remain in this buffer, that is, if + * length > remaining(), then no + * bytes are transferred and a {@link BufferOverflowException} is + * thrown. + * + *

Otherwise, this method copies length bytes from the + * given array into this buffer, starting at the given offset in the array + * and at the current position of this buffer. The position of this buffer + * is then incremented by length. + * + *

In other words, an invocation of this method of the form + * dst.put(src, off, len) has exactly the same effect as + * the loop + * + *

+     *     for (int i = off; i < off + len; i++)
+     *         dst.put(a[i]); 
+ * + * except that it first checks that there is sufficient space in this + * buffer and it is potentially much more efficient.

+ * + * @param src + * The array from which bytes are to be read + * + * @param offset + * The offset within the array of the first byte to be read; + * must be non-negative and no larger than array.length + * + * @param length + * The number of bytes to be read from the given array; + * must be non-negative and no larger than + * array.length - offset + * + * @return This buffer + * + * @throws BufferOverflowException + * If there is insufficient space in this buffer + * + * @throws IndexOutOfBoundsException + * If the preconditions on the offset and length + * parameters do not hold + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + + public virtual ByteBuffer put(byte[] src, int offset, int length) + { + checkBounds(offset, length, src.Length); + if (length > remaining()) + throw new BufferOverflowException(); + int end = offset + length; + for (int i = offset; i < end; i++) + put(src[i]); + return this; + } + + /* + * Relative bulk put method  (optional operation). + * + *

This method transfers the entire content of the given source + * byte array into this buffer. An invocation of this method of the + * form dst.put(a) behaves in exactly the same way as the + * invocation + * + *

+     *     dst.put(a, 0, a.length) 
+ * + * @return This buffer + * + * @throws BufferOverflowException + * If there is insufficient space in this buffer + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + + public ByteBuffer put(byte[] src) + { + return put(src, 0, src.Length); + } + + + // -- Other stuff -- + + /* + * Tells whether or not this buffer is backed by an accessible byte + * array. + * + *

If this method returns true then the {@link #array() array} + * and {@link #arrayOffset() arrayOffset} methods may safely be invoked. + *

+ * + * @return true if, and only if, this buffer + * is backed by an array and is not read-only + */ + + public bool hasArray() + { + return (hb != null); + } + + /* + * Returns the byte array that backs this + * buffer  (optional operation). + * + *

Modifications to this buffer's content will cause the returned + * array's content to be modified, and vice versa. + * + *

Invoke the {@link #hasArray hasArray} method before invoking this + * method in order to ensure that this buffer has an accessible backing + * array.

+ * + * @return The array that backs this buffer + * + * @throws ReadOnlyBufferException + * If this buffer is backed by an array but is read-only + * + * @throws UnsupportedOperationException + * If this buffer is not backed by an accessible array + */ + + public byte[] array() + { + if (hb == null) + throw new NotSupportedException(); + return hb; + } + + /* + * Returns the offset within this buffer's backing array of the first + * element of the buffer  (optional operation). + * + *

If this buffer is backed by an array then buffer position p + * corresponds to array index p + arrayOffset(). + * + *

Invoke the {@link #hasArray hasArray} method before invoking this + * method in order to ensure that this buffer has an accessible backing + * array.

+ * + * @return The offset within this buffer's array + * of the first element of the buffer + * + * @throws ReadOnlyBufferException + * If this buffer is backed by an array but is read-only + * + * @throws UnsupportedOperationException + * If this buffer is not backed by an accessible array + */ + + public int arrayOffset() + { + if (hb == null) + throw new NotSupportedException(); + return _offset; + } + + /* + * Compacts this buffer  (optional operation). + * + *

The bytes between the buffer's current position and its limit, + * if any, are copied to the beginning of the buffer. That is, the + * byte at index p = position() is copied + * to index zero, the byte at index p + 1 is copied + * to index one, and so forth until the byte at index + * limit() - 1 is copied to index + * n = limit() - 1 - p. + * The buffer's position is then set to n+1 and its limit is set to + * its capacity. The mark, if defined, is discarded. + * + *

The buffer's position is set to the number of bytes copied, + * rather than to zero, so that an invocation of this method can be + * followed immediately by an invocation of another relative put + * method.

+ * + + * + *

Invoke this method after writing data from a buffer in case the + * write was incomplete. The following loop, for example, copies bytes + * from one channel to another via the buffer buf: + * + *

+     * buf.clear();          // Prepare buffer for use
+     * for (;;) {
+     *     if (in.read(buf) < 0 && !buf.hasRemaining())
+     *         break;        // No more bytes to transfer
+     *     buf.flip();
+     *     out.write(buf);
+     *     buf.compact();    // In case of partial write
+     * }
+ * + + * + * @return This buffer + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer compact(); + + /* + * Tells whether or not this byte buffer is direct.

+ * + * @return true if, and only if, this buffer is direct + */ + public abstract bool isDirect(); + + + /* + * Returns a string summarizing the state of this buffer.

+ * + * @return A summary string + */ + + public String toString() + { + var sb = new StringBuilder(); + sb.Append(GetType().Name); + sb.Append("[pos="); + sb.Append(position()); + sb.Append(" lim="); + sb.Append(limit()); + sb.Append(" cap="); + sb.Append(capacity()); + sb.Append("]"); + return sb.ToString(); + } + + + /* + * Returns the current hash code of this buffer. + * + *

The hash code of a byte buffer depends only upon its remaining + * elements; that is, upon the elements from position() up to, and + * including, the element at limit() - 1. + * + *

Because buffer hash codes are content-dependent, it is inadvisable + * to use buffers as keys in hash maps or similar data structures unless it + * is known that their contents will not change.

+ * + * @return The current hash code of this buffer + */ + + public int hashCode() + { + int h = 1; + int p = position(); + for (int i = limit() - 1; i >= p; i--) + h = 31*h + get(i); + return h; + } + + /* + * Tells whether or not this buffer is equal to another object. + * + *

Two byte buffers are equal if, and only if, + * + *

    + * + *
  1. They have the same element type,

  2. + * + *
  3. They have the same number of remaining elements, and + *

  4. + * + *
  5. The two sequences of remaining elements, considered + * independently of their starting positions, are pointwise equal. + *

  6. + * + *
+ * + *

A byte buffer is not equal to any other type of object.

+ * + * @param ob The object to which this buffer is to be compared + * + * @return true if, and only if, this buffer is equal to the + * given object + */ + + public bool equals(object ob) + { + if (!(ob is ByteBuffer)) + return false; + var that = (ByteBuffer) ob; + if (remaining() != that.remaining()) + return false; + int p = position(); + for (int i = limit() - 1, j = that.limit() - 1; i >= p; i--, j--) + { + byte v1 = get(i); + byte v2 = that.get(j); + if (v1 != v2) + { + return false; + } + } + return true; + } + + /* + * Compares this buffer to another. + * + *

Two byte buffers are compared by comparing their sequences of + * remaining elements lexicographically, without regard to the starting + * position of each sequence within its corresponding buffer. + * + *

A byte buffer is not comparable to any other type of object. + * + * @return A negative integer, zero, or a positive integer as this buffer + * is less than, equal to, or greater than the given buffer + */ + + public int compareTo(ByteBuffer that) + { + int n = position() + Math.Min(remaining(), that.remaining()); + for (int i = position(), j = that.position(); i < n; i++, j++) + { + byte v1 = get(i); + byte v2 = that.get(j); + if (v1 == v2) + continue; + if (v1 < v2) + return -1; + return +1; + } + return remaining() - that.remaining(); + } + + + // -- Other char stuff -- + + + // -- Other byte stuff: Access to binary data -- + + + //= (Bits.byteOrder() == ByteOrder.BIG_ENDIAN); + + /* + * Retrieves this buffer's byte order. + * + *

The byte order is used when reading or writing multibyte values, and + * when creating buffers that are views of this byte buffer. The order of + * a newly-created byte buffer is always {@link ByteOrder#BIG_ENDIAN + * BIG_ENDIAN}.

+ * + * @return This buffer's byte order + */ + + public ByteOrder order() + { + return bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN; + } + + /* + * Modifies this buffer's byte order.

+ * + * @param bo + * The new byte order, + * either {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN} + * or {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN} + * + * @return This buffer + */ + + public ByteBuffer order(ByteOrder bo) + { + bigEndian = (bo == ByteOrder.BIG_ENDIAN); + nativeByteOrder = + (bigEndian == (!BitConverter.IsLittleEndian)); + return this; + } + + // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes + // + internal abstract byte _get(int i); // package-private + internal abstract void _put(int i, byte b); // package-private + + + /* + * Relative get method for reading a char value. + * + *

Reads the next two bytes at this buffer's current position, + * composing them into a char value according to the current byte order, + * and then increments the position by two.

+ * + * @return The char value at the buffer's current position + * + * @throws BufferUnderflowException + * If there are fewer than two bytes + * remaining in this buffer + */ + public abstract char getChar(); + + /* + * Relative put method for writing a char + * value  (optional operation). + * + *

Writes two bytes containing the given char value, in the + * current byte order, into this buffer at the current position, and then + * increments the position by two.

+ * + * @param value + * The char value to be written + * + * @return This buffer + * + * @throws BufferOverflowException + * If there are fewer than two bytes + * remaining in this buffer + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putChar(char value); + + /* + * Absolute get method for reading a char value. + * + *

Reads two bytes at the given index, composing them into a + * char value according to the current byte order.

+ * + * @param index + * The index from which the bytes will be read + * + * @return The char value at the given index + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus one + */ + public abstract char getChar(int index); + + /* + * Absolute put method for writing a char + * value  (optional operation). + * + *

Writes two bytes containing the given char value, in the + * current byte order, into this buffer at the given index.

+ * + * @param index + * The index at which the bytes will be written + * + * @param value + * The char value to be written + * + * @return This buffer + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus one + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putChar(int index, char value); + + /* + * Creates a view of this byte buffer as a char buffer. + * + *

The content of the new buffer will start at this buffer's current + * position. Changes to this buffer's content will be visible in the new + * buffer, and vice versa; the two buffers' position, limit, and mark + * values will be independent. + * + *

The new buffer's position will be zero, its capacity and its limit + * will be the number of bytes remaining in this buffer divided by + * two, and its mark will be undefined. The new buffer will be direct + * if, and only if, this buffer is direct, and it will be read-only if, and + * only if, this buffer is read-only.

+ * + * @return A new char buffer + */ + public abstract Buffer asCharBuffer(); + + + /* + * Relative get method for reading a short value. + * + *

Reads the next two bytes at this buffer's current position, + * composing them into a short value according to the current byte order, + * and then increments the position by two.

+ * + * @return The short value at the buffer's current position + * + * @throws BufferUnderflowException + * If there are fewer than two bytes + * remaining in this buffer + */ + public abstract short getShort(); + + /* + * Relative put method for writing a short + * value  (optional operation). + * + *

Writes two bytes containing the given short value, in the + * current byte order, into this buffer at the current position, and then + * increments the position by two.

+ * + * @param value + * The short value to be written + * + * @return This buffer + * + * @throws BufferOverflowException + * If there are fewer than two bytes + * remaining in this buffer + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putShort(short value); + + /* + * Absolute get method for reading a short value. + * + *

Reads two bytes at the given index, composing them into a + * short value according to the current byte order.

+ * + * @param index + * The index from which the bytes will be read + * + * @return The short value at the given index + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus one + */ + public abstract short getShort(int index); + + /* + * Absolute put method for writing a short + * value  (optional operation). + * + *

Writes two bytes containing the given short value, in the + * current byte order, into this buffer at the given index.

+ * + * @param index + * The index at which the bytes will be written + * + * @param value + * The short value to be written + * + * @return This buffer + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus one + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putShort(int index, short value); + + /* + * Creates a view of this byte buffer as a short buffer. + * + *

The content of the new buffer will start at this buffer's current + * position. Changes to this buffer's content will be visible in the new + * buffer, and vice versa; the two buffers' position, limit, and mark + * values will be independent. + * + *

The new buffer's position will be zero, its capacity and its limit + * will be the number of bytes remaining in this buffer divided by + * two, and its mark will be undefined. The new buffer will be direct + * if, and only if, this buffer is direct, and it will be read-only if, and + * only if, this buffer is read-only.

+ * + * @return A new short buffer + */ + public abstract Buffer asShortBuffer(); + + + /* + * Relative get method for reading an int value. + * + *

Reads the next four bytes at this buffer's current position, + * composing them into an int value according to the current byte order, + * and then increments the position by four.

+ * + * @return The int value at the buffer's current position + * + * @throws BufferUnderflowException + * If there are fewer than four bytes + * remaining in this buffer + */ + public abstract int getInt(); + + /* + * Relative put method for writing an int + * value  (optional operation). + * + *

Writes four bytes containing the given int value, in the + * current byte order, into this buffer at the current position, and then + * increments the position by four.

+ * + * @param value + * The int value to be written + * + * @return This buffer + * + * @throws BufferOverflowException + * If there are fewer than four bytes + * remaining in this buffer + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putInt(int value); + + /* + * Absolute get method for reading an int value. + * + *

Reads four bytes at the given index, composing them into a + * int value according to the current byte order.

+ * + * @param index + * The index from which the bytes will be read + * + * @return The int value at the given index + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus three + */ + public abstract int getInt(int index); + + /* + * Absolute put method for writing an int + * value  (optional operation). + * + *

Writes four bytes containing the given int value, in the + * current byte order, into this buffer at the given index.

+ * + * @param index + * The index at which the bytes will be written + * + * @param value + * The int value to be written + * + * @return This buffer + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus three + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putInt(int index, int value); + + /* + * Creates a view of this byte buffer as an int buffer. + * + *

The content of the new buffer will start at this buffer's current + * position. Changes to this buffer's content will be visible in the new + * buffer, and vice versa; the two buffers' position, limit, and mark + * values will be independent. + * + *

The new buffer's position will be zero, its capacity and its limit + * will be the number of bytes remaining in this buffer divided by + * four, and its mark will be undefined. The new buffer will be direct + * if, and only if, this buffer is direct, and it will be read-only if, and + * only if, this buffer is read-only.

+ * + * @return A new int buffer + */ + public abstract Buffer asIntBuffer(); + + + /* + * Relative get method for reading a long value. + * + *

Reads the next eight bytes at this buffer's current position, + * composing them into a long value according to the current byte order, + * and then increments the position by eight.

+ * + * @return The long value at the buffer's current position + * + * @throws BufferUnderflowException + * If there are fewer than eight bytes + * remaining in this buffer + */ + public abstract long getLong(); + + /* + * Relative put method for writing a long + * value  (optional operation). + * + *

Writes eight bytes containing the given long value, in the + * current byte order, into this buffer at the current position, and then + * increments the position by eight.

+ * + * @param value + * The long value to be written + * + * @return This buffer + * + * @throws BufferOverflowException + * If there are fewer than eight bytes + * remaining in this buffer + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putLong(long value); + + /* + * Absolute get method for reading a long value. + * + *

Reads eight bytes at the given index, composing them into a + * long value according to the current byte order.

+ * + * @param index + * The index from which the bytes will be read + * + * @return The long value at the given index + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus seven + */ + public abstract long getLong(int index); + + /* + * Absolute put method for writing a long + * value  (optional operation). + * + *

Writes eight bytes containing the given long value, in the + * current byte order, into this buffer at the given index.

+ * + * @param index + * The index at which the bytes will be written + * + * @param value + * The long value to be written + * + * @return This buffer + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus seven + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putLong(int index, long value); + + /* + * Creates a view of this byte buffer as a long buffer. + * + *

The content of the new buffer will start at this buffer's current + * position. Changes to this buffer's content will be visible in the new + * buffer, and vice versa; the two buffers' position, limit, and mark + * values will be independent. + * + *

The new buffer's position will be zero, its capacity and its limit + * will be the number of bytes remaining in this buffer divided by + * eight, and its mark will be undefined. The new buffer will be direct + * if, and only if, this buffer is direct, and it will be read-only if, and + * only if, this buffer is read-only.

+ * + * @return A new long buffer + */ + public abstract Buffer asLongBuffer(); + + + /* + * Relative get method for reading a float value. + * + *

Reads the next four bytes at this buffer's current position, + * composing them into a float value according to the current byte order, + * and then increments the position by four.

+ * + * @return The float value at the buffer's current position + * + * @throws BufferUnderflowException + * If there are fewer than four bytes + * remaining in this buffer + */ + public abstract float getFloat(); + + /* + * Relative put method for writing a float + * value  (optional operation). + * + *

Writes four bytes containing the given float value, in the + * current byte order, into this buffer at the current position, and then + * increments the position by four.

+ * + * @param value + * The float value to be written + * + * @return This buffer + * + * @throws BufferOverflowException + * If there are fewer than four bytes + * remaining in this buffer + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putFloat(float value); + + /* + * Absolute get method for reading a float value. + * + *

Reads four bytes at the given index, composing them into a + * float value according to the current byte order.

+ * + * @param index + * The index from which the bytes will be read + * + * @return The float value at the given index + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus three + */ + public abstract float getFloat(int index); + + /* + * Absolute put method for writing a float + * value  (optional operation). + * + *

Writes four bytes containing the given float value, in the + * current byte order, into this buffer at the given index.

+ * + * @param index + * The index at which the bytes will be written + * + * @param value + * The float value to be written + * + * @return This buffer + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus three + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putFloat(int index, float value); + + /* + * Creates a view of this byte buffer as a float buffer. + * + *

The content of the new buffer will start at this buffer's current + * position. Changes to this buffer's content will be visible in the new + * buffer, and vice versa; the two buffers' position, limit, and mark + * values will be independent. + * + *

The new buffer's position will be zero, its capacity and its limit + * will be the number of bytes remaining in this buffer divided by + * four, and its mark will be undefined. The new buffer will be direct + * if, and only if, this buffer is direct, and it will be read-only if, and + * only if, this buffer is read-only.

+ * + * @return A new float buffer + */ + public abstract Buffer asFloatBuffer(); + + + /* + * Relative get method for reading a double value. + * + *

Reads the next eight bytes at this buffer's current position, + * composing them into a double value according to the current byte order, + * and then increments the position by eight.

+ * + * @return The double value at the buffer's current position + * + * @throws BufferUnderflowException + * If there are fewer than eight bytes + * remaining in this buffer + */ + public abstract double getDouble(); + + /* + * Relative put method for writing a double + * value  (optional operation). + * + *

Writes eight bytes containing the given double value, in the + * current byte order, into this buffer at the current position, and then + * increments the position by eight.

+ * + * @param value + * The double value to be written + * + * @return This buffer + * + * @throws BufferOverflowException + * If there are fewer than eight bytes + * remaining in this buffer + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putDouble(double value); + + /* + * Absolute get method for reading a double value. + * + *

Reads eight bytes at the given index, composing them into a + * double value according to the current byte order.

+ * + * @param index + * The index from which the bytes will be read + * + * @return The double value at the given index + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus seven + */ + public abstract double getDouble(int index); + + /* + * Absolute put method for writing a double + * value  (optional operation). + * + *

Writes eight bytes containing the given double value, in the + * current byte order, into this buffer at the given index.

+ * + * @param index + * The index at which the bytes will be written + * + * @param value + * The double value to be written + * + * @return This buffer + * + * @throws IndexOutOfBoundsException + * If index is negative + * or not smaller than the buffer's limit, + * minus seven + * + * @throws ReadOnlyBufferException + * If this buffer is read-only + */ + public abstract ByteBuffer putDouble(int index, double value); + + /* + * Creates a view of this byte buffer as a double buffer. + * + *

The content of the new buffer will start at this buffer's current + * position. Changes to this buffer's content will be visible in the new + * buffer, and vice versa; the two buffers' position, limit, and mark + * values will be independent. + * + *

The new buffer's position will be zero, its capacity and its limit + * will be the number of bytes remaining in this buffer divided by + * eight, and its mark will be undefined. The new buffer will be direct + * if, and only if, this buffer is direct, and it will be read-only if, and + * only if, this buffer is read-only.

+ * + * @return A new double buffer + */ + public abstract Buffer asDoubleBuffer(); + } +#pragma warning restore 1591 +} + +// ReSharper restore InconsistentNaming \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/HeapByteBuffer.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/HeapByteBuffer.cs new file mode 100644 index 0000000..ce2ce1d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/HeapByteBuffer.cs @@ -0,0 +1,380 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +// This class is based on the source code from Sun's Java 1.5.0 API for java.nio.HeapByteBuffer, but +// rewritten for C# and .NET with the purpose to bridge the .NET and Java internals of Robocode. + +using System; + +// ReSharper disable InconsistentNaming + +namespace net.sf.robocode.nio +{ + /// + /// A read/write HeapByteBuffer. + /// + /// + internal class HeapByteBuffer : ByteBuffer + { + internal HeapByteBuffer(int cap, int lim) + : base(-1, 0, lim, cap, new byte[cap], 0) + { + } + + internal HeapByteBuffer(byte[] buf, int off, int len) + : base(-1, off, off + len, buf.Length, buf, 0) + { + } + + protected HeapByteBuffer(byte[] buf, + int mark, int pos, int lim, int cap, + int off) + : base(mark, pos, lim, cap, buf, off) + { + } + + public override ByteBuffer slice() + { + return new HeapByteBuffer(hb, + -1, + 0, + remaining(), + remaining(), + position() + _offset); + } + + public override ByteBuffer duplicate() + { + return new HeapByteBuffer(hb, + markValue(), + position(), + limit(), + capacity(), + _offset); + } + + public override ByteBuffer asReadOnlyBuffer() + { + throw new NotImplementedException(); + } + + + protected int ix(int i) + { + return i + _offset; + } + + public override byte get() + { + return hb[ix(nextGetIndex())]; + } + + public override byte get(int i) + { + return hb[ix(checkIndex(i))]; + } + + public override ByteBuffer get(byte[] dst, int offset, int length) + { + checkBounds(offset, length, dst.Length); + if (length > remaining()) + throw new BufferUnderflowException(); + Array.Copy(hb, ix(position()), dst, offset, length); + position(position() + length); + return this; + } + + public override bool isDirect() + { + return false; + } + + + public override bool isReadOnly() + { + return false; + } + + public override ByteBuffer put(byte x) + { + hb[ix(nextPutIndex())] = x; + return this; + } + + public override ByteBuffer put(int i, byte x) + { + hb[ix(checkIndex(i))] = x; + return this; + } + + public override ByteBuffer put(byte[] src, int offset, int length) + { + checkBounds(offset, length, src.Length); + if (length > remaining()) + throw new BufferOverflowException(); + Array.Copy(src, offset, hb, ix(position()), length); + position(position() + length); + return this; + } + + public override ByteBuffer put(ByteBuffer src) + { + if (src is HeapByteBuffer) + { + if (src == this) + throw new ArgumentException(); + var sb = (HeapByteBuffer) src; + int n = sb.remaining(); + if (n > remaining()) + throw new BufferOverflowException(); + Array.Copy(sb.hb, sb.ix(sb.position()), + hb, ix(position()), n); + sb.position(sb.position() + n); + position(position() + n); + } + else if (src.isDirect()) + { + int n = src.remaining(); + if (n > remaining()) + throw new BufferOverflowException(); + src.get(hb, ix(position()), n); + position(position() + n); + } + else + { + base.put(src); + } + return this; + } + + public override ByteBuffer compact() + { + Array.Copy(hb, ix(position()), hb, ix(0), remaining()); + position(remaining()); + limit(capacity()); + discardMark(); + return this; + } + + + internal override byte _get(int i) + { + return hb[i]; + } + + internal override void _put(int i, byte b) + { + hb[i] = b; + } + + public override char getChar() + { + return BitConverter.ToChar(hb, ix(nextGetIndex(2))); + } + + public override char getChar(int i) + { + return BitConverter.ToChar(hb, ix(checkIndex(i, 2))); + } + + + public override ByteBuffer putChar(char x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(nextPutIndex(2)); + Array.Copy(bytes, 0, hb, index, 2); + return this; + } + + public override ByteBuffer putChar(int i, char x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(checkIndex(i, 2)); + Array.Copy(bytes, 0, hb, index, 2); + return this; + } + + public override Buffer asCharBuffer() + { + throw new NotImplementedException(); + } + + public override short getShort() + { + return BitConverter.ToInt16(hb, ix(nextGetIndex(2))); + } + + public override short getShort(int i) + { + return BitConverter.ToInt16(hb, ix(checkIndex(i, 2))); + } + + + public override ByteBuffer putShort(short x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(nextPutIndex(2)); + Array.Copy(bytes, 0, hb, index, 2); + return this; + } + + public override ByteBuffer putShort(int i, short x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(checkIndex(i, 2)); + Array.Copy(bytes, 0, hb, index, 2); + return this; + } + + public override Buffer asShortBuffer() + { + throw new NotImplementedException(); + } + + public override int getInt() + { + return BitConverter.ToInt32(hb, ix(nextGetIndex(4))); + } + + public override int getInt(int i) + { + return BitConverter.ToInt32(hb, ix(checkIndex(i, 4))); + } + + + public override ByteBuffer putInt(int x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(nextPutIndex(4)); + Array.Copy(bytes, 0, hb, index, 4); + return this; + } + + public override ByteBuffer putInt(int i, int x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(checkIndex(i, 4)); + Array.Copy(bytes, 0, hb, index, 4); + return this; + } + + public override Buffer asIntBuffer() + { + throw new NotImplementedException(); + } + + + // long + + + public override long getLong() + { + return BitConverter.ToInt64(hb, ix(nextGetIndex(8))); + } + + public override long getLong(int i) + { + return BitConverter.ToInt64(hb, ix(checkIndex(i, 8))); + } + + + public override ByteBuffer putLong(long x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(nextPutIndex(8)); + Array.Copy(bytes, 0, hb, index, 8); + return this; + } + + public override ByteBuffer putLong(int i, long x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(checkIndex(i, 8)); + Array.Copy(bytes, 0, hb, index, 8); + return this; + } + + public override Buffer asLongBuffer() + { + throw new NotImplementedException(); + } + + + // float + + + public override float getFloat() + { + return BitConverter.ToSingle(hb, ix(nextGetIndex(4))); + } + + public override float getFloat(int i) + { + return BitConverter.ToSingle(hb, ix(checkIndex(i, 4))); + } + + + public override ByteBuffer putFloat(float x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(nextPutIndex(4)); + Array.Copy(bytes, 0, hb, index, 4); + return this; + } + + public override ByteBuffer putFloat(int i, float x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(checkIndex(i, 4)); + Array.Copy(bytes, 0, hb, index, 4); + return this; + } + + public override Buffer asFloatBuffer() + { + throw new NotImplementedException(); + } + + + // double + + + public override double getDouble() + { + return BitConverter.ToDouble(hb, ix(nextGetIndex(8))); + } + + public override double getDouble(int i) + { + return BitConverter.ToDouble(hb, ix(checkIndex(i, 8))); + } + + + public override ByteBuffer putDouble(double x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(nextPutIndex(8)); + Array.Copy(bytes, 0, hb, index, 8); + return this; + } + + public override ByteBuffer putDouble(int i, double x) + { + byte[] bytes = BitConverter.GetBytes(x); + int index = ix(checkIndex(i, 8)); + Array.Copy(bytes, 0, hb, index, 8); + return this; + } + + public override Buffer asDoubleBuffer() + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/InvalidMarkException.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/InvalidMarkException.cs new file mode 100644 index 0000000..080851e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/nio/InvalidMarkException.cs @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Runtime.Serialization; + +namespace net.sf.robocode.nio +{ +#pragma warning disable 1591 + + /// + [Serializable] + public class InvalidMarkException : Exception + { + public InvalidMarkException() + { + } + + public InvalidMarkException(string message) + : base(message) + { + } + + public InvalidMarkException(string message, Exception inner) + : base(message, inner) + { + } + + protected InvalidMarkException(SerializationInfo info, + StreamingContext context) + : base(info, context) + { + } + } + + /// + [Serializable] + public class BufferUnderflowException : Exception + { + public BufferUnderflowException() + { + } + + public BufferUnderflowException(string message) + : base(message) + { + } + + public BufferUnderflowException(string message, Exception inner) + : base(message, inner) + { + } + + protected BufferUnderflowException(SerializationInfo info, + StreamingContext context) + : base(info, context) + { + } + } + + /// + [Serializable] + public class BufferOverflowException : Exception + { + public BufferOverflowException() + { + } + + public BufferOverflowException(string message) + : base(message) + { + } + + public BufferOverflowException(string message, Exception inner) + : base(message, inner) + { + } + + protected BufferOverflowException(SerializationInfo info, + StreamingContext context) + : base(info, context) + { + } + } + + /// + [Serializable] + public class ReadOnlyBufferException : Exception + { + public ReadOnlyBufferException() + { + } + + public ReadOnlyBufferException(string message) + : base(message) + { + } + + public ReadOnlyBufferException(string message, Exception inner) + : base(message, inner) + { + } + + protected ReadOnlyBufferException(SerializationInfo info, + StreamingContext context) + : base(info, context) + { + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/peer/IRobotStaticsN.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/peer/IRobotStaticsN.cs new file mode 100644 index 0000000..b84b044 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/peer/IRobotStaticsN.cs @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace net.sf.robocode.peer +{ +#pragma warning disable 1591 + + /// + public interface IRobotStaticsN + { + bool IsInteractiveRobot(); + + bool IsPaintRobot(); + + bool IsAdvancedRobot(); + + bool IsTeamRobot(); + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/HiddenAccessN.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/HiddenAccessN.cs new file mode 100644 index 0000000..9dd414e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/HiddenAccessN.cs @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Security.Permissions; +using net.sf.robocode.io; +using net.sf.robocode.peer; +using Robocode; +using Robocode.RobotInterfaces; + +namespace net.sf.robocode.security +{ +#pragma warning disable 1591 + /// + [RobocodeInternalPermission(SecurityAction.LinkDemand)] + public class HiddenAccessN + { + private static IHiddenEventHelper eventHelper; + private static IHiddenBulletHelper bulletHelper; + private static IHiddenStatusHelper statusHelper; + private static IHiddenRulesHelper rulesHelper; + private static bool initialized; + public static IHiddenRandomHelper randomHelper; + + public static void init() + { + if (initialized) + { + return; + } + MethodInfo method; + + try + { + method = typeof (Event).GetMethod("createHiddenHelper", BindingFlags.Static | BindingFlags.NonPublic); + eventHelper = (IHiddenEventHelper) method.Invoke(null, null); + + method = typeof (Bullet).GetMethod("createHiddenHelper", BindingFlags.Static | BindingFlags.NonPublic); + bulletHelper = (IHiddenBulletHelper) method.Invoke(null, null); + + method = typeof (RobotStatus).GetMethod("createHiddenSerializer", + BindingFlags.Static | BindingFlags.NonPublic); + statusHelper = (IHiddenStatusHelper) method.Invoke(null, null); + + method = typeof (BattleRules).GetMethod("createHiddenHelper", + BindingFlags.Static | BindingFlags.NonPublic); + rulesHelper = (IHiddenRulesHelper) method.Invoke(null, null); + + initialized = true; + } + catch (Exception e) + { + LoggerN.logError(e); + Environment.Exit(-1); + } + } + + public static bool IsCriticalEvent(Event e) + { + return eventHelper.IsCriticalEvent(e); + } + + public static void SetEventTime(Event e, long newTime) + { + eventHelper.SetTime(e, newTime); + } + + public static void SetEventPriority(Event e, int newPriority) + { + eventHelper.SetPriority(e, newPriority); + } + + public static void Dispatch(Event evnt, IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + eventHelper.Dispatch(evnt, robot, statics, graphics); + } + + public static void SetDefaultPriority(Event e) + { + eventHelper.SetDefaultPriority(e); + } + + public static byte GetSerializationType(Event e) + { + return eventHelper.GetSerializationType(e); + } + + // Needed for .NET version + public static void UpdateBullets(Event e, Dictionary bullets) + { + eventHelper.UpdateBullets(e, bullets); + } + + public static void Update(Bullet bullet, double x, double y, string victimName, bool isActive) + { + bulletHelper.update(bullet, x, y, victimName, isActive); + } + + public static RobotStatus createStatus(double energy, double x, double y, double bodyHeading, double gunHeading, + double radarHeading, double velocity, double bodyTurnRemaining, + double radarTurnRemaining, double gunTurnRemaining, + double distanceRemaining, double gunHeat, int others, int numSentries, + int roundNum, int numRounds, long time) + { + return statusHelper.createStatus(energy, x, y, bodyHeading, gunHeading, radarHeading, velocity, + bodyTurnRemaining, radarTurnRemaining, gunTurnRemaining, distanceRemaining, + gunHeat, others, numSentries, roundNum, numRounds, time); + } + + public static BattleRules createRules(int battlefieldWidth, int battlefieldHeight, int numRounds, double gunCoolingRate, long inactivityTime, + bool hideEnemyNames, int borderSentryRobotAttackRange) + { + return rulesHelper.createRules(battlefieldWidth, battlefieldHeight, numRounds, gunCoolingRate, inactivityTime, hideEnemyNames, borderSentryRobotAttackRange); + } + + public static string GetRobotName() + { + string name = (string)AppDomain.CurrentDomain.GetData("robotName"); + return name ?? ""; + } + } +#pragma warning restore 1591 +} + +//happy diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenBulletHelper.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenBulletHelper.cs new file mode 100644 index 0000000..d1eb3cf --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenBulletHelper.cs @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace net.sf.robocode.security +{ +#pragma warning disable 1591 + /// + public interface IHiddenBulletHelper + { + void update(Bullet bullet, double x, double y, string victimName, bool isActive); + } +} + +//happy \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenEventHelper.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenEventHelper.cs new file mode 100644 index 0000000..b485e5b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenEventHelper.cs @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Collections.Generic; +using net.sf.robocode.peer; +using Robocode; +using Robocode.RobotInterfaces; + +namespace net.sf.robocode.security +{ +#pragma warning disable 1591 + /// + public interface IHiddenEventHelper + { + void SetDefaultPriority(Event evnt); + void SetPriority(Event evnt, int newPriority); + void SetTime(Event evnt, long newTime); + bool IsCriticalEvent(Event evnt); + void Dispatch(Event evnt, IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics); + byte GetSerializationType(Event evnt); + void UpdateBullets(Event evnt, Dictionary bullets); // Needed for .NET version + } +} + +//happy diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenRandomHelper.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenRandomHelper.cs new file mode 100644 index 0000000..27e8963 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenRandomHelper.cs @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; + +namespace net.sf.robocode.security +{ +#pragma warning disable 1591 + /// + public interface IHiddenRandomHelper + { + Random GetRandom(); + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenRulesHelper.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenRulesHelper.cs new file mode 100644 index 0000000..447d1db --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenRulesHelper.cs @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace net.sf.robocode.security +{ +#pragma warning disable 1591 + /// + public interface IHiddenRulesHelper + { + BattleRules createRules(int battlefieldWidth, int battlefieldHeight, int numRounds, double gunCoolingRate, long inactivityTime, + bool hideEnemyNames, int borderSentryRobotAttackRange); + } +} + +//happy \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenStatusHelper.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenStatusHelper.cs new file mode 100644 index 0000000..db401f3 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/IHiddenStatusHelper.cs @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace net.sf.robocode.security +{ +#pragma warning disable 1591 + /// + public interface IHiddenStatusHelper + { + RobotStatus createStatus(double energy, double x, double y, double bodyHeading, double gunHeading, + double radarHeading, + double velocity, double bodyTurnRemaining, double radarTurnRemaining, + double gunTurnRemaining, + double distanceRemaining, double gunHeat, int others, int numSentries, + int roundNum, int numRounds, long time); + } +} + +//happy \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/RobocodeInternalPermission.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/RobocodeInternalPermission.cs new file mode 100644 index 0000000..94a8e50 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/security/RobocodeInternalPermission.cs @@ -0,0 +1,151 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Security; +using System.Security.Permissions; +using System.Text; + +namespace net.sf.robocode.security +{ +#pragma warning disable 1591 + /// + [Serializable] + public sealed class RobocodeInternalPermission : CodeAccessPermission, IUnrestrictedPermission + { + private bool unrestricted; + + public RobocodeInternalPermission(PermissionState state) + { + unrestricted = state == PermissionState.Unrestricted; + } + + #region IUnrestrictedPermission Members + + public bool IsUnrestricted() + { + return unrestricted; + } + + #endregion + + public override IPermission Copy() + { + //Create a new instance of RobocodeInternalPermission with the current + //value of unrestricted. + var copy = new RobocodeInternalPermission(PermissionState.None); + + copy.unrestricted = IsUnrestricted(); + //Return the copy. + return copy; + } + + public override IPermission Intersect(IPermission target) + { + //If nothing was passed, return null. + if (null == target) + { + return null; + } + try + { + //Create a new instance of RobocodeInternalPermission from the passed object. + var PassedPermission = (RobocodeInternalPermission) target; + + //If one class has an unrestricted value of false, then the + //intersection will have an unrestricted value of false. + //Return the passed class with the unrestricted value of false. + if (!PassedPermission.unrestricted) + { + return target; + } + //Return a copy of the current class if the passed one has + //an unrestricted value of true. + return Copy(); + } + //Catch an InvalidCastException. + //Throw ArgumentException to notify the user. + catch (InvalidCastException) + { + throw new ArgumentException("Argument_WrongType", GetType().FullName); + } + } + + public override bool IsSubsetOf(IPermission target) + { + //If nothing was passed and unrestricted is false, + //then return true. + if (null == target) + { + return !unrestricted; + } + try + { + //Create a new instance of RobocodeInternalPermission from the passed object. + var passedpermission = (RobocodeInternalPermission) target; + + //If unrestricted has the same value in both objects, then + //one is the subset of the other. + return unrestricted == passedpermission.unrestricted; + } + //Catch an InvalidCastException. + //Throw ArgumentException to notify the user. + catch (InvalidCastException) + { + throw new ArgumentException("Argument_WrongType", GetType().FullName); + } + } + + public override void FromXml(SecurityElement PassedElement) + { + //Get the unrestricted value from the XML and initialize + //the current instance of unrestricted to that value. + string element = PassedElement.Attribute("Unrestricted"); + + if (null != element) + { + unrestricted = Convert.ToBoolean(element); + } + } + + public override SecurityElement ToXml() + { + //Encode the current permission to XML using the + //SecurityElement class. + var element = new SecurityElement("IPermission"); + Type type = GetType(); + var AssemblyName = new StringBuilder(type.Assembly.ToString()); + AssemblyName.Replace('\"', '\''); + element.AddAttribute("class", type.FullName + ", " + AssemblyName); + element.AddAttribute("version", "1"); + element.AddAttribute("Unrestricted", unrestricted.ToString()); + return element; + } + } + + + /// + [AttributeUsageAttribute(AttributeTargets.All, AllowMultiple = true)] + public class RobocodeInternalPermissionAttribute : CodeAccessSecurityAttribute + { + public RobocodeInternalPermissionAttribute(SecurityAction action) + : base(action) + { + Unrestricted = false; + } + + public override IPermission CreatePermission() + { + return Unrestricted + ? new RobocodeInternalPermission(PermissionState.Unrestricted) + : new RobocodeInternalPermission(PermissionState.None); + } + } +#pragma warning restore 1591 +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/serialization/ISerializableHelperN.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/serialization/ISerializableHelperN.cs new file mode 100644 index 0000000..139d0e9 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/serialization/ISerializableHelperN.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using net.sf.robocode.nio; + +namespace net.sf.robocode.serialization +{ +#pragma warning disable 1591 + /// + public interface ISerializableHelperN + { + int sizeOf(RbSerializerN serializer, object obj); + void serialize(RbSerializerN serializer, ByteBuffer buffer, object obj); + object deserialize(RbSerializerN serializer, ByteBuffer buffer); + } +} + +//happy \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/serialization/RbSerializerN.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/serialization/RbSerializerN.cs new file mode 100644 index 0000000..28226d1 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/net/sf/robocode/serialization/RbSerializerN.cs @@ -0,0 +1,524 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Security.Permissions; +using System.Text; +using net.sf.robocode.io; +using net.sf.robocode.nio; +using net.sf.robocode.security; +using Robocode; + +namespace net.sf.robocode.serialization +{ +#pragma warning disable 1591 + /// + [RobocodeInternalPermission(SecurityAction.LinkDemand)] + public sealed class RbSerializerN + { + private const int byteOrder = -1059135839; //0xC0DEDEA1 + public static readonly int SIZEOF_TYPEINFO = 1; + public static readonly int SIZEOF_BYTE = 1; + public static readonly int SIZEOF_BOOL = 1; + public static readonly int SIZEOF_CHAR = 2; + public static readonly int SIZEOF_INT = 4; + public static readonly int SIZEOF_LONG = 8; + public static readonly int SIZEOF_DOUBLE = 8; + + public static readonly byte TERMINATOR_TYPE = 0xff; + public static readonly byte ExecCommands_TYPE = 1; + public static readonly byte BulletCommand_TYPE = 2; + public static readonly byte TeamMessage_TYPE = 3; + public static readonly byte DebugProperty_TYPE = 4; + public static readonly byte ExecResults_TYPE = 5; + public static readonly byte RobotStatus_TYPE = 6; + public static readonly byte BulletStatus_TYPE = 7; + public static readonly byte BattleResults_TYPE = 8; + public static readonly byte Bullet_TYPE = 9; + public static readonly byte RobotStatics_TYPE = 10; + + public static readonly byte BattleEndedEvent_TYPE = 32; + public static readonly byte BulletHitBulletEvent_TYPE = 33; + public static readonly byte BulletHitEvent_TYPE = 34; + public static readonly byte BulletMissedEvent_TYPE = 35; + public static readonly byte DeathEvent_TYPE = 36; + public static readonly byte WinEvent_TYPE = 37; + public static readonly byte HitWallEvent_TYPE = 38; + public static readonly byte RobotDeathEvent_TYPE = 39; + public static readonly byte SkippedTurnEvent_TYPE = 40; + public static readonly byte ScannedRobotEvent_TYPE = 41; + public static readonly byte HitByBulletEvent_TYPE = 42; + public static readonly byte HitRobotEvent_TYPE = 43; + public static readonly byte KeyPressedEvent_TYPE = 44; + public static readonly byte KeyReleasedEvent_TYPE = 45; + public static readonly byte KeyTypedEvent_TYPE = 46; + public static readonly byte MouseClickedEvent_TYPE = 47; + public static readonly byte MouseDraggedEvent_TYPE = 48; + public static readonly byte MouseEnteredEvent_TYPE = 49; + public static readonly byte MouseExitedEvent_TYPE = 50; + public static readonly byte MouseMovedEvent_TYPE = 51; + public static readonly byte MousePressedEvent_TYPE = 52; + public static readonly byte MouseReleasedEvent_TYPE = 53; + public static readonly byte MouseWheelMovedEvent_TYPE = 54; + public static readonly byte RoundEndedEvent_TYPE = 55; + + private static readonly ISerializableHelperN[] typeToHelper = new ISerializableHelperN[256]; + private static readonly Dictionary classToType = new Dictionary(); + private static readonly Encoding charset; + + private static int currentVersion; + + static RbSerializerN() + { + charset = Encoding.UTF8; // we will use it as UCS-2 + register(null, TERMINATOR_TYPE); // reserved for end of (list) element + } + + public static void Init(int version) + { + if (currentVersion == 0) + { + currentVersion = version; + } + } + + public ByteBuffer serialize(byte type, object obj) + { + int length = sizeOf(type, obj); + + // header + ByteBuffer buffer = ByteBuffer.allocate(SIZEOF_INT + SIZEOF_INT + SIZEOF_INT + length); + + buffer.putInt(byteOrder); + buffer.putInt(currentVersion); + buffer.putInt(length); + + // body + serialize(buffer, type, obj); + if (buffer.remaining() != 0) + { + throw new IOException("Serialization failed: bad size"); + } + return buffer; + } + + public ByteBuffer serializeToBuffer(ByteBuffer buffer, byte type, object obj) + { + int length = sizeOf(type, obj); + buffer.limit(SIZEOF_INT + SIZEOF_INT + SIZEOF_INT + length); + + buffer.putInt(byteOrder); + buffer.putInt(currentVersion); + buffer.putInt(length); + + // body + serialize(buffer, type, obj); + if (buffer.remaining() != 0) + { + throw new IOException("Serialization failed: bad size"); + } + return buffer; + } + + public Object deserialize(ByteBuffer buffer) + { + int bo = buffer.getInt(); + + if (bo != byteOrder) + { + throw new IOException("Different byte order is not supported"); + } + + int version = buffer.getInt(); + + if (version != currentVersion) + { + throw new IOException("Version of data is not supported. We support only strong match"); + } + int length = buffer.getInt(); + + if (length != buffer.remaining()) + { + throw new IOException("Wrong buffer size, " + length + "expected but got " + buffer.remaining()); + } + + // body + Object res = deserializeAny(buffer); + + if (buffer.remaining() != 0) + { + throw new IOException("Serialization failed"); + } + return res; + } + + public void serialize(ByteBuffer buffer, byte type, object obj) + { + ISerializableHelperN helper = getHelper(type); + + // FOR-DEBUG int expect = sizeOf(type, object) + buffer.position(); + + if (obj != null) + { + buffer.put(type); + helper.serialize(this, buffer, obj); + } + else + { + buffer.put(TERMINATOR_TYPE); + } + // FOR-DEBUG if (expect != buffer.position()) { + // FOR-DEBUG throw new Exception("Bad size"); + // FOR-DEBUG } + } + + public void serialize(ByteBuffer buffer, string data) + { + if (data == null) + { + buffer.putInt(-1); + } + else + { + int bytes = charset.GetBytes(data, 0, data.Length, buffer.array(), buffer.position() + 4); + buffer.putInt(bytes); + buffer.position(buffer.position() + bytes); + } + } + + public void serialize(ByteBuffer buffer, byte[] data) + { + if (data == null) + { + buffer.putInt(-1); + } + else + { + buffer.putInt(data.Length); + buffer.put(data); + } + } + + public void serialize(ByteBuffer buffer, int[] data) + { + if (data == null) + { + buffer.putInt(-1); + } + else + { + buffer.putInt(data.Length); + foreach (int aData in data) + { + buffer.putInt(aData); + } + } + } + + public void serialize(ByteBuffer buffer, char[] data) + { + if (data == null) + { + buffer.putInt(-1); + } + else + { + buffer.putInt(data.Length); + foreach (char aData in data) + { + buffer.putChar(aData); + } + } + } + + public void serialize(ByteBuffer buffer, double[] data) + { + if (data == null) + { + buffer.putInt(-1); + } + else + { + buffer.putInt(data.Length); + foreach (double aData in data) + { + buffer.putDouble(aData); + } + } + } + + public void serialize(ByteBuffer buffer, float[] data) + { + if (data == null) + { + buffer.putInt(-1); + } + else + { + buffer.putInt(data.Length); + foreach (float aData in data) + { + buffer.putFloat(aData); + } + } + } + + public void serialize(ByteBuffer buffer, bool value) + { + buffer.put((byte) (value ? 1 : 0)); + } + + public void serialize(ByteBuffer buffer, double value) + { + buffer.putDouble(value); + } + + public void serialize(ByteBuffer buffer, char value) + { + buffer.putChar(value); + } + + public void serialize(ByteBuffer buffer, long value) + { + buffer.putLong(value); + } + + public void serialize(ByteBuffer buffer, int value) + { + buffer.putInt(value); + } + + public void serialize(ByteBuffer buffer, Event evnt) + { + byte type = HiddenAccessN.GetSerializationType(evnt); + + serialize(buffer, type, evnt); + } + + public Object deserializeAny(ByteBuffer buffer) + { + byte type = buffer.get(); + + if (type == TERMINATOR_TYPE) + { + return null; + } + return getHelper(type).deserialize(this, buffer); + } + + public string deserializeString(ByteBuffer buffer) + { + int bytes = buffer.getInt(); + + if (bytes == -1) + { + return null; + } + ByteBuffer slice = buffer.slice(); + + slice.limit(bytes); + string res; + + try + { + byte[] array = buffer.array(); + char[] chars = charset.GetChars(array, buffer.position(), bytes); + res = new string(chars); + } + catch (Exception e) + { + throw new Exception("Bad character", e); + } + buffer.position(buffer.position() + bytes); + return res; + } + + public byte[] deserializeBytes(ByteBuffer buffer) + { + int len = buffer.getInt(); + + if (len == -1) + { + return null; + } + var res = new byte[len]; + + buffer.get(res); + return res; + } + + public int[] deserializeints(ByteBuffer buffer) + { + int len = buffer.getInt(); + + if (len == -1) + { + return null; + } + var res = new int[len]; + + for (int i = 0; i < len; i++) + { + res[i] = buffer.getInt(); + } + return res; + } + + public float[] deserializeFloats(ByteBuffer buffer) + { + int len = buffer.getInt(); + + if (len == -1) + { + return null; + } + var res = new float[len]; + + for (int i = 0; i < len; i++) + { + res[i] = buffer.getFloat(); + } + return res; + } + + public char[] deserializeChars(ByteBuffer buffer) + { + int len = buffer.getInt(); + + if (len == -1) + { + return null; + } + var res = new char[len]; + + for (int i = 0; i < len; i++) + { + res[i] = buffer.getChar(); + } + return res; + } + + public double[] deserializeDoubles(ByteBuffer buffer) + { + int len = buffer.getInt(); + + if (len == -1) + { + return null; + } + var res = new double[len]; + + for (int i = 0; i < len; i++) + { + res[i] = buffer.getDouble(); + } + return res; + } + + public bool deserializeBoolean(ByteBuffer buffer) + { + return buffer.get() != 0; + } + + public char deserializeChar(ByteBuffer buffer) + { + return buffer.getChar(); + } + + public int deserializeInt(ByteBuffer buffer) + { + return buffer.getInt(); + } + + public long deserializeLong(ByteBuffer buffer) + { + return buffer.getLong(); + } + + public float deserializeFloat(ByteBuffer buffer) + { + return buffer.getFloat(); + } + + public double deserializeDouble(ByteBuffer buffer) + { + return buffer.getDouble(); + } + + public int sizeOf(string data) + { + return (data == null) ? SIZEOF_INT : SIZEOF_INT + charset.GetByteCount(data); + } + + public int sizeOf(byte[] data) + { + return (data == null) ? SIZEOF_INT : SIZEOF_INT + data.Length; + } + + public int sizeOf(byte type, object obj) + { + return getHelper(type).sizeOf(this, obj); + } + + public int sizeOf(Event evnt) + { + return sizeOf(HiddenAccessN.GetSerializationType(evnt), evnt); + } + + private static ISerializableHelperN getHelper(byte type) + { + ISerializableHelperN helper = typeToHelper[type]; + + if (helper == null) + { + throw new Exception("Unknownd or unsupported data type"); + } + return helper; + } + + public static void register(Type realClass, byte type) + { + try + { + if (realClass != null) + { + MethodInfo method = realClass.GetMethod("createHiddenSerializer", + BindingFlags.NonPublic | BindingFlags.Static); + var helper = (ISerializableHelperN) method.Invoke(null, null); + + typeToHelper[type] = helper; + classToType.Add(realClass, type); + } + } + catch (Exception e) + { + LoggerN.logError(e); + } + } + + public static ByteBuffer serializeToBuffer(Object src) + { + var rbs = new RbSerializerN(); + Byte type = classToType[src.GetType()]; + + return rbs.serialize(type, src); + } + + public static T deserializeFromBuffer(ByteBuffer buffer) + { + var rbs = new RbSerializerN(); + Object res = rbs.deserialize(buffer); + + return (T) res; + } + } +} + +//happy diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode.dotnet.api.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode.dotnet.api.csproj new file mode 100644 index 0000000..c23f971 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode.dotnet.api.csproj @@ -0,0 +1,164 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {7E0900D3-6E8F-48EB-86DB-AA767AA90B84} + Library + Properties + robocode + robocode + v3.5 + 512 + true + ..\..\tools\keys\robocode.snk + + + 3.5 + + + + true + full + false + ..\target\ + ..\target\obj\ + DEBUG;TRACE + prompt + 4 + ..\target\robocode.xml + + + pdbonly + true + ..\target\ + ..\target\obj\ + TRACE + prompt + 4 + + + + + + + + + + + + + + AssemblyInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + copy "$(TargetPath)" "$(SolutionDir)\robocode.dotnet.host\target" + if not exist $(OutDir)\build-sources\generated-sources\META-INF mkdir $(OutDir)\build-sources\generated-sources\META-INF\ +echo [assembly: System.Reflection.AssemblyVersion("1.9.2.4")] > $(OutDir)\build-sources\generated-sources\META-INF\AssemblyInfo.cs + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/AdvancedRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/AdvancedRobot.cs new file mode 100644 index 0000000..b92ce97 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/AdvancedRobot.cs @@ -0,0 +1,2226 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using System.IO; +using Robocode.RobotInterfaces; +using Robocode.RobotInterfaces.Peer; +using Robocode.Util; + +namespace Robocode +{ + /// + /// A more advanced type of robot than Robot that allows non-blocking calls, + /// custom events, and writes to the filesystem. + ///

+ /// If you have not already, you should create a first. + ///
+ ///
+ /// Building your first robot + /// + /// + /// + /// + /// + /// + /// + ///

+ public abstract class AdvancedRobot : Robot, IAdvancedRobot, IAdvancedEvents + { + /// + /// Returns the distance remaining in the robot's current move measured in + /// pixels. + ///

+ /// This call returns both positive and negative values. Positive values + /// means that the robot is currently moving forwards. Negative values means + /// that the robot is currently moving backwards. If the returned value is 0, + /// the robot currently stands still. + /// + /// + /// + /// + /// + /// + ///

+ public double DistanceRemaining + { + get + { + if (peer != null) + { + return peer.GetDistanceRemaining(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the angle remaining in the robots's turn, in degrees. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the robot is currently turning to the right. + /// Negative values means that the robot is currently turning to the left. + /// If the returned value is 0, the robot is currently not turning. + /// + /// + /// + /// + /// + /// + ///

+ public double TurnRemaining + { + get + { + if (peer != null) + { + return Utils.ToDegrees(peer.GetBodyTurnRemaining()); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the angle remaining in the gun's turn, in degrees. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the gun is currently turning to the right. + /// Negative values means that the gun is currently turning to the left. + /// If the returned value is 0, the gun is currently not turning. + /// + /// + /// + /// + /// + /// + ///

+ public double GunTurnRemaining + { + get + { + if (peer != null) + { + return Utils.ToDegrees(peer.GetGunTurnRemaining()); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the angle remaining in the radar's turn, in degrees. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the radar is currently turning to the right. + /// Negative values means that the radar is currently turning to the left. + /// If the returned value is 0, the radar is currently not turning. + /// + /// + /// + /// + /// + /// + ///

+ public double RadarTurnRemaining + { + get + { + if (peer != null) + { + return Utils.ToDegrees(peer.GetRadarTurnRemaining()); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Sets the robot to move ahead (forward) by distance measured in + /// pixels when the next execution takes place. + ///

+ /// This call returns immediately, and will not execute until you + /// call or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where positive values means that the robot is set to move ahead, and negative + /// values means that the robot is set to move back. If 0 is given as input, the + /// robot will stop its movement, but will have to decelerate till it stands still, + /// and will thus not be able to stop its movement immediately, but eventually. + ///

+ /// + /// The distance to move measured in pixels. + /// If distance > 0 the robot is set to move ahead. + /// If distance < 0 the robot is set to move back. + /// If distance = 0 the robot is set to stop its movement. + /// + /// + /// + /// // Set the robot to move 50 pixels ahead + /// SetAhead(50); + /// + /// // Set the robot to move 100 pixels back + /// // (overrides the previous order) + /// SetAhead(-100); + /// + /// ... + /// // Executes the last SetAhead() + /// Execute(); + /// + /// + /// + /// + /// + public void SetAhead(double distance) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetMove(distance); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot to move back by distance measured in pixels when the next + /// execution takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, where + /// positive values means that the robot is set to move back, and negative + /// values means that the robot is set to move ahead. If 0 is given as input, + /// the robot will stop its movement, but will have to decelerate + /// till it stands still, and will thus not be able to stop its movement + /// immediately, but eventually. + ///

+ /// + /// + /// // Set the robot to move 50 pixels back + /// SetBack(50); + /// + /// // Set the robot to move 100 pixels ahead + /// // (overrides the previous order) + /// SetBack(-100); + /// + /// ... + /// // Executes the last SetBack() + /// Execute(); + /// + /// + /// + /// + /// + ///

+ /// + /// The distance to move measured in pixels. + /// If distance > 0 the robot is set to move back. + /// If distance < 0 the robot is set to move ahead. + /// If distance = 0 the robot is set to stop its movement. + /// + public void SetBack(double distance) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetMove(-distance); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's body to turn left by degrees when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's body is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Set the robot to turn 180 degrees to the left + /// SetTurnLeft(180); + /// + /// // Set the robot to turn 90 degrees to the right instead of left + /// // (overrides the previous order) + /// SetTurnLeft(-90); + /// + /// ... + /// // Executes the last SetTurnLeft() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's body to the left. + /// If degrees > 0 the robot is set to turn left. + /// If degrees < 0 the robot is set to turn right. + /// If degrees = 0 the robot is set to stop turning. + /// + public void SetTurnLeft(double degrees) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnBody(-Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's body to turn right by degrees when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's body is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Set the robot to turn 180 degrees to the right + /// SetTurnRight(180); + /// + /// // Set the robot to turn 90 degrees to the left instead of right + /// // (overrides the previous order) + /// SetTurnRight(-90); + /// + /// ... + /// // Executes the last SetTurnRight() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's body to the right. + /// If degrees > 0 the robot is set to turn right. + /// If degrees < 0 the robot is set to turn left. + /// If degrees = 0 the robot is set to stop turning. + /// + public void SetTurnRight(double degrees) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnBody(Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the gun to Fire a bullet when the next execution takes place. + /// The bullet will travel in the direction the gun is pointing. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// The specified bullet power is an amount of energy that will be taken from + /// the robot's energy. Hence, the more power you want to spend on the + /// bullet, the more energy is taken from your robot. + ///

+ /// The bullet will do (4 * power) damage if it hits another robot. If power + /// is greater than 1, it will do an additional 2 * (power - 1) damage. + /// You will get (3 * power) back if you hit the other robot. You can call + /// Rules.GetBulletDamage(double)} for getting the damage that a + /// bullet with a specific bullet power will do. + ///

+ /// The specified bullet power should be between + /// and . + ///

+ /// Note that the gun cannot Fire if the gun is overheated, meaning that + /// returns a value > 0. + ///

+ /// An event is generated when the bullet hits a robot, wall, or another + /// bullet. + ///

+ /// + /// + /// // Fire a bullet with maximum power if the gun is ready + /// if (GunGeat == 0) + /// { + /// SetFire(Rules.MAX_BULLET_POWER); + /// } + /// ... + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of energy given to the bullet, and subtracted from the robot's energy. + /// + public void SetFire(double power) + { + if (peer != null) + { + peer.SetFire(power); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the gun to Fire a bullet when the next execution takes place. + /// The bullet will travel in the direction the gun is pointing. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// The specified bullet power is an amount of energy that will be taken from + /// the robot's energy. Hence, the more power you want to spend on the + /// bullet, the more energy is taken from your robot. + ///

+ /// The bullet will do (4 * power) damage if it hits another robot. If power + /// is greater than 1, it will do an additional 2 * (power - 1) damage. + /// You will get (3 * power) back if you hit the other robot. You can call + /// for getting the damage that a + /// bullet with a specific bullet power will do. + ///

+ /// The specified bullet power should be between + /// and . + ///

+ /// Note that the gun cannot Fire if the gun is overheated, meaning that + /// returns a value > 0. + ///

+ /// An event is generated when the bullet hits a robot + /// (), wall (), or another + /// bullet (). + ///

+ /// + /// + /// Bullet bullet = null; + /// + /// // Fire a bullet with maximum power if the gun is ready + /// if (GunHeat == 0) + /// { + /// bullet = SetFireBullet(Rules.MAX_BULLET_POWER); + /// } + /// ... + /// Execute(); + /// ... + /// // Get the velocity of the bullet + /// if (bullet != null) + /// { + /// double bulletVelocity = bullet.Velocity; + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of energy given to the bullet, and subtracted from the robot's + /// energy. + /// + /// Returns a that contains information about the bullet if it + /// was actually fired, which can be used for tracking the bullet after it + /// has been fired. If the bullet was not fired, null is returned. + public Bullet SetFireBullet(double power) + { + if (peer != null) + { + return peer.SetFire(power); + } + UninitializedException(); + return null; + } + + /// + /// Registers a custom event to be called when a condition is met. + /// When you are finished with your condition or just want to remove it you + /// must call . + ///

+ /// + /// + /// // Create the condition for our custom event + /// Condition triggerHitCondition = new Condition("triggerhit") + /// { + /// public bool Test() + /// { + /// return (Energy <= trigger); + /// } + /// } + /// + /// // Add our custom event based on our condition + /// AddCustomEvent(triggerHitCondition); + /// + /// + /// + /// + ///

+ /// + /// The condition that must be met. + /// Throws ArgumentException if the condition parameter has been set to null. + /// + public void AddCustomEvent(Condition condition) + { + if (condition == null) + { + throw new ArgumentException("the condition cannot be null"); + } + if (peer != null) + { + ((IAdvancedRobotPeer) peer).AddCustomEvent(condition); + } + else + { + UninitializedException(); + } + } + + /// + /// Same as , but alows to define condition as anonymous method. + /// + public void AddCustomEvent(string name, int priority, ConditionTest test) + { + AddCustomEvent(new Condition(name, priority, test)); + } + + /// + /// Removes a custom event that was previously added by calling + /// . + ///

+ /// + /// + /// // Create the condition for our custom event + /// Condition triggerHitCondition = new Condition("triggerhit") + /// { + /// public bool Test() + /// { + /// return (Energy <= trigger); + /// } + /// } + /// + /// // Add our custom event based on our condition + /// AddCustomEvent(triggerHitCondition); + /// ... + /// // do something with your robot + /// ... + /// // Remove the custom event based on our condition + /// RemoveCustomEvent(triggerHitCondition); + /// + /// + /// + /// + ///

+ /// + /// The condition that was previous added and that must be removed now. + /// + public void RemoveCustomEvent(Condition condition) + { + if (condition == null) + { + throw new ArgumentException("the condition cannot be null"); + } + if (peer != null) + { + ((IAdvancedRobotPeer) peer).RemoveCustomEvent(condition); + } + else + { + UninitializedException(); + } + } + + /// + /// Clears Out any pending events in the robot's event queue immediately. + /// + /// + /// + public void ClearAllEvents() + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).clearAllEvents(); + } + else + { + UninitializedException(); + } + } + + /// + /// Executes any pending actions, or continues executing actions that are + /// in process. This call returns after the actions have been started. + ///

+ /// Note that advanced robots must call this function in order to + /// Execute pending set* calls like e.g. , + /// , etc. + /// Otherwise, these calls will never get executed. + ///

+ /// In this example the robot will move while turning: + /// + /// + /// SetTurnRight(90); + /// SetAhead(100); + /// Execute(); + /// + /// while (DistanceRemaining > 0 && TurnRemaining > 0) + /// { + /// Execute(); + /// } + /// + /// + ///

+ public virtual void Execute() + { + if (peer != null) + { + peer.Execute(); + } + else + { + UninitializedException(); + } + } + + /// + /// Returns a list containing all events currently in the robot's queue. + /// You might, for example, call this while processing another event. + ///

+ /// + /// + /// for (Event evnt : GetAllEvents()) { + /// if (evnt is HitRobotEvent) { + /// // do something with the event + /// } else if (evnt is HitByBulletEvent) { + /// // do something with the event + /// } + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public IList GetAllEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetAllEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a list containing all BulletHitBulletEvents currently in the + /// robot's queue. You might, for example, call this while processing another + /// event. + ///

+ /// + /// + /// for (BulletHitBulletEvent evnt : GetBulletHitBulletEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ public IList GetBulletHitBulletEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetBulletHitBulletEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a list containing all BulletHitEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// for (BulletHitEvent event: GetBulletHitEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ public IList GetBulletHitEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetBulletHitEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a list containing all BulletMissedEvents currently in the + /// robot's queue. You might, for example, call this while processing another + /// event. + ///

+ /// + /// + /// for (BulletMissedEvent evnt : GetBulletMissedEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ public IList GetBulletMissedEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetBulletMissedEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a file representing a data directory for the robot. + ///

+ /// The system will automatically create the directory for you, so you do not + /// need to create it by yourself. + /// + ///

+ public string GetDataDirectory() + { + if (peer != null) + { + return ((IAdvancedRobotPeer) peer).GetDataDirectory(); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a file in your data directory that you can write to. + ///

+ /// The system will automatically create the directory for you, so you do not + /// need to create it by yourself. + ///

+ /// Please notice that the max. size of your data file is set to 200000 bytes + /// (~195 KB). + ///

+ /// See the Sample.SittingDuck to see an example of how to use this + /// method. + /// + ///

+ /// + /// The file name of the data file for your robot + /// + public Stream GetDataFile(string filename) + { + if (peer != null) + { + return ((IAdvancedRobotPeer) peer).GetDataFile(filename); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns the data quota available in your data directory, i.e. the amount + /// of bytes left in the data directory for the robot. + /// + /// + /// + public long DataQuotaAvailable + { + get + { + if (peer != null) + { + return ((IAdvancedRobotPeer) peer).GetDataQuotaAvailable(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the current priority of a class of events. + /// An event priority is a value from 0 - 99. The higher value, the higher priority. + ///

+ /// + /// + /// int myHitRobotPriority = GetEventPriority("HitRobotEvent"); + /// + /// + ///

+ /// The default priorities are, from highest to lowest: + ///

    :     100 (reserved)
+        ///    :             100 (reserved)
+        ///    :     100 (reserved)
+        ///    :           99
+        ///    Key and mouse events:  98
+        ///    :           80 (default value)
+        ///    :          75
+        ///    :       70
+        ///    :     60
+        ///    :  55
+        ///    :        50
+        ///    :      40
+        ///    :          30
+        ///    :         20
+        ///    :     10
+        ///    :             5
+        ///    :            -1 (reserved)
+        ///  
+ /// + ///
+ /// + /// the name of the event class (string) + /// + public int GetEventPriority(string eventClass) + { + if (peer != null) + { + return ((IAdvancedRobotPeer) peer).GetEventPriority(eventClass); + } + UninitializedException(); + return 0; // never called + } + + /// + /// Returns a list containing all HitByBulletEvents currently in the + /// robot's queue. You might, for example, call this while processing + /// another event. + ///

+ /// + /// + /// for (HitByBulletEvent evnt : GetHitByBulletEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ public IList GetHitByBulletEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetHitByBulletEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a list containing all HitRobotEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// for (HitRobotEvent evnt : GetHitRobotEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ public IList GetHitRobotEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetHitRobotEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a list containing all HitWallEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// for (HitWallEvent evnt : GetHitWallEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ public IList GetHitWallEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetHitWallEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a list containing all RobotDeathEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// for (RobotDeathEvent evnt : GetRobotDeathEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ public IList GetRobotDeathEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetRobotDeathEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a list containing all ScannedRobotEvents currently in the robot's queue. + /// You might, for example, call this while processing another event. + ///

+ /// + /// + /// for (ScannedRobotEvent evnt : GetScannedRobotEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ public IList GetScannedRobotEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetScannedRobotEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + /// Returns a list containing all StatusEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// for (StatusEvent evnt : GetStatusEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ public IList GetStatusEvents() + { + if (peer != null) + { + return new List(((IAdvancedRobotPeer) peer).GetStatusEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + public virtual void OnCustomEvent(CustomEvent evnt) + { + } + + /// + /// Sets the priority of a class of events. + ///

+ /// Events are sent to the onXXX handlers in order of priority. + /// Higher priority events can interrupt lower priority events. + /// For events with the same priority, newer events are always sent first. + /// Valid priorities are 0 - 99, where 100 is reserved and 80 is the default + /// priority. + ///

+ /// + /// + /// SetEventPriority("RobotDeathEvent", 15); + /// + /// + ///

+ /// The default priorities are, from highest to lowest: + ///

    :             100 (reserved)
+        ///    :     100 (reserved)
+        ///    :           99
+        ///    :           80
+        ///    :          75
+        ///    :       70
+        ///    :     60
+        ///    :  55
+        ///    :        50
+        ///    :      40
+        ///    :          30
+        ///    :         20
+        ///    :     10
+        ///    :             5
+        ///    :            -1 (reserved)
+        ///  
+ ///

+ /// Note that you cannot change the priority for events with the special + /// priority value -1 or 100 (reserved) as these events are system events. + /// Also note that you cannot change the priority of CustomEvent. + /// Instead you must change the priority of the condition(s) for your custom + /// event(s). + /// + ///

+ /// + /// The name of the event class (string) to set the priority for + /// + /// + /// The new priority for that event class + /// + public void SetEventPriority(string eventClass, int priority) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetEventPriority(eventClass, priority); + } + else + { + UninitializedException(); + } + } + + /// + /// Call this during an event handler to allow new events of the same + /// priority to restart the event handler. + ///

+ /// + /// + /// public override void OnScannedRobot(ScannedRobotEvent e) + /// { + /// Fire(1); + /// IsInterruptible = true; + /// Ahead(100); // If you see a robot while moving ahead, + /// // this handler will start from the top + /// // Without IsInterruptible (true), we wouldn't + /// // receive scan events at all! + /// // We'll only get here if we don't see a robot during the move. + /// Out.WriteLine("Ok, I can't see anyone"); + /// } + /// + /// + /// + /// + ///

+ public bool IsInterruptible + { + set + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetInterruptible(value); + } + else + { + UninitializedException(); + } + } + } + + /// + /// Sets the maximum turn rate of the robot measured in degrees if the robot + /// should turn slower than (10 degress/turn). + /// + /// + /// + /// + /// + /// + public double MaxTurnRate + { + set + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetMaxTurnRate(Utils.ToRadians(value)); + } + else + { + UninitializedException(); + } + } + } + + /// + /// Sets the maximum velocity of the robot measured in pixels/turn if the + /// robot should move slower than (8 pixels/turn). + /// + /// + /// + /// + /// + /// + public double MaxVelocity + { + set + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetMaxVelocity(value); + } + else + { + UninitializedException(); + } + } + } + + /// + /// Sets the robot to resume the movement stopped by + /// or , if any. + ///

+ /// This call returns immediately, and will not execute until you call + /// or take an action that executes. + /// + /// + /// + /// + /// + /// + /// + ///

+ public void SetResume() + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetResume(); + } + else + { + UninitializedException(); + } + } + + /// + /// This call is identical to , but returns immediately, and + /// will not execute until you call or take an action that + /// executes. + ///

+ /// If there is already movement saved from a previous stop, this will have + /// no effect. + ///

+ /// This call is equivalent to calling SetStop(false); + /// + /// + /// + /// + /// + /// + /// + ///

+ public void SetStop() + { + SetStop(false); + } + + /// + /// This call is identical to , but + /// returns immediately, and will not execute until you call + /// or take an action that executes. + ///

+ /// If there is already movement saved from a previous stop, you can + /// overwrite it by calling SetStop(true). + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// true if the movement saved from a previous stop + /// should be overwritten; false otherwise. + /// + public void SetStop(bool overwrite) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetStop(overwrite); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's gun to turn left by degrees when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's gun is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Set the gun to turn 180 degrees to the left + /// SetTurnGunLeft(180); + /// + /// // Set the gun to turn 90 degrees to the right instead of left + /// // (overrides the previous order) + /// SetTurnGunLeft(-90); + /// + /// ... + /// // Executes the last SetTurnGunLeft() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's gun to the left. + /// If degrees > 0 the robot's gun is set to turn left. + /// If degrees < 0 the robot's gun is set to turn right. + /// If degrees = 0 the robot's gun is set to stop turning. + /// + public void SetTurnGunLeft(double degrees) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnGun(-Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's gun to turn right by degrees when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's gun is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Set the gun to turn 180 degrees to the right + /// SetTurnGunRight(180); + /// + /// // Set the gun to turn 90 degrees to the left instead of right + /// // (overrides the previous order) + /// SetTurnGunRight(-90); + /// + /// ... + /// // Executes the last SetTurnGunRight() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// + /// The amount of degrees to turn the robot's gun to the right. + /// If degrees > 0 the robot's gun is set to turn right. + /// If degrees < 0 the robot's gun is set to turn left. + /// If degrees = 0 the robot's gun is set to stop turning. + /// + public void SetTurnGunRight(double degrees) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnGun(Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's radar to turn left by degrees when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's radar is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Set the radar to turn 180 degrees to the left + /// SetTurnRadarLeft(180); + /// + /// // Set the radar to turn 90 degrees to the right instead of left + /// // (overrides the previous order) + /// SetTurnRadarLeft(-90); + /// + /// ... + /// // Executes the last SetTurnRadarLeft() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's radar to the left. + /// If degrees > 0 the robot's radar is set to turn left. + /// If degrees < 0 the robot's radar is set to turn right. + /// If degrees = 0 the robot's radar is set to stop turning. + /// + public void SetTurnRadarLeft(double degrees) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnRadar(-Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's radar to turn right by degrees when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's radar is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Set the radar to turn 180 degrees to the right + /// SetTurnRadarRight(180); + /// + /// // Set the radar to turn 90 degrees to the right instead of right + /// // (overrides the previous order) + /// SetTurnRadarRight(-90); + /// + /// ... + /// // Executes the last SetTurnRadarRight() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's radar to the rright. + /// If degrees > 0 the robot's radar is set to turn right. + /// If degrees < 0 the robot's radar is set to turn left. + /// If degrees = 0 the robot's radar is set to stop turning. + /// + public void SetTurnRadarRight(double degrees) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnRadar(Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Does not return until a condition is met, i.e. when a + /// returns true. + ///

+ /// This call executes immediately. + ///

+ /// See the Sample.Crazy robot for how this method can be used. + /// + /// + ///

+ /// + /// the condition that must be met before this call returns + /// + public void WaitFor(Condition condition) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).WaitFor(condition); + } + else + { + UninitializedException(); + } + } + + /// + /// This method is called if your robot dies. + ///

+ /// You should override it in your robot if you want to be informed of this + /// event. Actions will have no effect if called from this section. The + /// intent is to allow you to perform calculations or print something out + /// when the robot is killed. + /// + /// + ///

+ /// the death event set by the game + public override void OnDeath(DeathEvent evnt) + { + } + + /// + public virtual void OnSkippedTurn(SkippedTurnEvent evnt) + { + } + + /// + /// Returns the direction that the robot's body is facing, in radians. + /// The value returned will be between 0 and 2 * PI (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// PI / 2 means East, PI means South, and 3 * PI / 2 means West. + /// + /// + /// + ///

+ public double HeadingRadians + { + get + { + if (peer != null) + { + return peer.GetBodyHeading(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Sets the robot's body to turn left by radians when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's body is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Set the robot to turn 180 degrees to the left + /// SetTurnLeftRadians(Math.PI); + /// + /// // Set the robot to turn 90 degrees to the right instead of left + /// // (overrides the previous order) + /// SetTurnLeftRadians(-Math.PI / 2); + /// + /// ... + /// // Executes the last SetTurnLeftRadians() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's body to the left. + /// If radians > 0 the robot is set to turn left. + /// If radians < 0 the robot is set to turn right. + /// If radians = 0 the robot is set to stop turning. + public void SetTurnLeftRadians(double radians) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnBody(-radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's body to turn right by radians when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's body is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Set the robot to turn 180 degrees to the right + /// SetTurnRightRadians(Math.PI); + /// + /// // Set the robot to turn 90 degrees to the left instead of right + /// // (overrides the previous order) + /// SetTurnRightRadians(-Math.PI / 2); + /// + /// ... + /// // Executes the last SetTurnRightRadians() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's body to the right. + /// If radians > 0 the robot is set to turn right. + /// If radians < 0 the robot is set to turn left. + /// If radians = 0 the robot is set to stop turning. + public void SetTurnRightRadians(double radians) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnBody(radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately turns the robot's body to the left by radians. + ///

+ /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the robot's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's body is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Turn the robot 180 degrees to the left + /// TurnLeftRadians(Math.PI); + /// + /// // Afterwards, turn the robot 90 degrees to the right + /// TurnLeftRadians(-Math.PI / 2); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's body to the left. + /// If radians > 0 the robot will turn right. + /// If radians < 0 the robot will turn left. + /// If radians = 0 the robot will not turn, but execute. + public void TurnLeftRadians(double radians) + { + if (peer != null) + { + peer.TurnBody(-radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately turns the robot's body to the right by radians. + /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the robot's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's body is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Turn the robot 180 degrees to the right + /// TurnRightRadians(Math.PI); + /// + /// // Afterwards, turn the robot 90 degrees to the left + /// TurnRightRadians(-Math.PI / 2); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's body to the right. + /// If radians > 0 the robot will turn right. + /// If radians < 0 the robot will turn left. + /// If radians = 0 the robot will not turn, but execute. + public void TurnRightRadians(double radians) + { + if (peer != null) + { + peer.TurnBody(radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Returns the direction that the robot's gun is facing, in radians. + /// The value returned will be between 0 and 2 * PI (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// PI / 2 means East, PI means South, and 3 * PI / 2 means West. + /// + /// + /// + ///

+ public double GunHeadingRadians + { + get + { + if (peer != null) + { + return peer.GetGunHeading(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the direction that the robot's radar is facing, in radians. + /// The value returned will be between 0 and 2 * PI (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// PI / 2 means East, PI means South, and 3 * PI / 2 means West. + /// + /// + /// + ///

+ public double RadarHeadingRadians + { + get + { + if (peer != null) + { + return peer.GetRadarHeading(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Sets the robot's gun to turn left by radians when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's gun is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Set the gun to turn 180 degrees to the left + /// SetTurnGunLeftRadians(Math.PI); + /// + /// // Set the gun to turn 90 degrees to the right instead of left + /// // (overrides the previous order) + /// SetTurnGunLeftRadians(-Math.PI / 2); + /// + /// ... + /// // Executes the last SetTurnGunLeftRadians() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's gun to the left. + /// If radians > 0 the robot's gun is set to turn left. + /// If radians < 0 the robot's gun is set to turn right. + /// If radians = 0 the robot's gun is set to stop turning. + public void SetTurnGunLeftRadians(double radians) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnGun(-radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's gun to turn right by radians when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's gun is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Set the gun to turn 180 degrees to the right + /// SetTurnGunRightRadians(Math.PI); + /// + /// // Set the gun to turn 90 degrees to the left instead of right + /// // (overrides the previous order) + /// SetTurnGunRightRadians(-Math.PI / 2); + /// + /// ... + /// // Executes the last SetTurnGunRightRadians() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's gun to the right. + /// If radians > 0 the robot's gun is set to turn left. + /// If radians < 0 the robot's gun is set to turn right. + /// If radians = 0 the robot's gun is set to stop turning. + public void SetTurnGunRightRadians(double radians) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnGun(radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's radar to turn left by radians when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's radar is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Set the radar to turn 180 degrees to the left + /// SetTurnRadarLeftRadians(Math.PI); + /// + /// // Set the radar to turn 90 degrees to the right instead of left + /// // (overrides the previous order) + /// SetTurnRadarLeftRadians(-Math.PI / 2); + /// + /// ... + /// // Executes the last SetTurnRadarLeftRadians() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's radar to the left. + /// If radians > 0 the robot's radar is set to turn left. + /// If radians < 0 the robot's radar is set to turn right. + /// If radians = 0 the robot's radar is set to stop turning. + public void SetTurnRadarLeftRadians(double radians) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnRadar(-radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the robot's radar to turn right by radians when the next execution + /// takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's radar is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Set the radar to turn 180 degrees to the right + /// SetTurnRadarRightRadians(Math.PI); + /// + /// // Set the radar to turn 90 degrees to the right instead of right + /// // (overrides the previous order) + /// SetTurnRadarRightRadians(-Math.PI / 2); + /// + /// ... + /// // Executes the last SetTurnRadarRightRadians() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's radar to the right. + /// If radians > 0 the robot's radar is set to turn left. + /// If radians < 0 the robot's radar is set to turn right. + /// If radians = 0 the robot's radar is set to stop turning. + public void SetTurnRadarRightRadians(double radians) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).SetTurnRadar(radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately turns the robot's gun to the left by radians. + ///

+ /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the gun's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's gun is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Turn the robot's gun 180 degrees to the left + /// TurnGunLeftRadians(Math.PI); + /// + /// // Afterwards, turn the robot's gun 90 degrees to the right + /// TurnGunLeftRadians(-Math.PI / 2); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's gun to the left. + /// If radians > 0 the robot's gun will turn left. + /// If radians < 0 the robot's gun will turn right. + /// If radians = 0 the robot's gun will not turn, but execute. + public void TurnGunLeftRadians(double radians) + { + if (peer != null) + { + peer.TurnGun(-radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately turns the robot's gun to the right by radians. + /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the gun's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's gun is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Turn the robot's gun 180 degrees to the right + /// TurnGunRightRadians(Math.PI); + /// + /// // Afterwards, turn the robot's gun 90 degrees to the left + /// TurnGunRightRadians(-Math.PI / 2); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's gun to the right. + /// If radians > 0 the robot's gun will turn right. + /// If radians < 0 the robot's gun will turn left. + /// If radians = 0 the robot's gun will not turn, but execute. + public void TurnGunRightRadians(double radians) + { + if (peer != null) + { + peer.TurnGun(radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately turns the robot's radar to the left by radians. + ///

+ /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the radar's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's radar is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Turn the robot's radar 180 degrees to the left + /// TurnRadarLeftRadians(Math.PI); + /// + /// // Afterwards, turn the robot's radar 90 degrees to the right + /// TurnRadarLeftRadians(-Math.PI / 2); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's radar to the left. + /// If radians > 0 the robot's radar will turn left. + /// If radians < 0 the robot's radar will turn right. + /// If radians = 0 the robot's radar will not turn, but execute. + public void TurnRadarLeftRadians(double radians) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).TurnRadar(-radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately turns the robot's radar to the right by radians. + /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the radar's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's radar is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Turn the robot's radar 180 degrees to the right + /// TurnRadarRightRadians(Math.PI); + /// + /// // Afterwards, turn the robot's radar 90 degrees to the left + /// TurnRadarRightRadians(-Math.PI / 2); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the amount of radians to turn the robot's radar to the right. + /// If radians > 0 the robot's radar will turn right. + /// If radians < 0 the robot's radar will turn left. + /// If radians = 0 the robot's radar will not turn, but execute. + public void TurnRadarRightRadians(double radians) + { + if (peer != null) + { + ((IAdvancedRobotPeer) peer).TurnRadar(radians); + } + else + { + UninitializedException(); + } + } + + /// + /// Returns the angle remaining in the gun's turn, in radians. + ///

+ /// This call returns both positive and negative values. Positive values + /// means that the gun is currently turning to the right. Negative values + /// means that the gun is currently turning to the left. + /// + /// + /// + /// + /// + ///

+ public double GunTurnRemainingRadians + { + get + { + if (peer != null) + { + return peer.GetGunTurnRemaining(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the angle remaining in the radar's turn, in radians. + ///

+ /// This call returns both positive and negative values. Positive values + /// means that the radar is currently turning to the right. Negative values + /// means that the radar is currently turning to the left. + /// + /// + /// + /// + /// + ///

+ public double RadarTurnRemainingRadians + { + get + { + if (peer != null) + { + return peer.GetRadarTurnRemaining(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the angle remaining in the robot's turn, in radians. + ///

+ /// This call returns both positive and negative values. Positive values + /// means that the robot is currently turning to the right. Negative values + /// means that the robot is currently turning to the left. + /// + /// + /// + /// + /// + ///

+ public double TurnRemainingRadians + { + get + { + if (peer != null) + { + return peer.GetBodyTurnRemaining(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + IAdvancedEvents IAdvancedRobot.GetAdvancedEventListener() + { + return this; // this robot is listening + } + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleEndedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleEndedEvent.cs new file mode 100644 index 0000000..7c877c1 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleEndedEvent.cs @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A BattleEndedEvent is sent to + /// when the battle is ended. + /// You can use the information contained in this event to determine if the + /// battle was aborted and also get the results of the battle. + /// + /// + /// + [Serializable] + public sealed class BattleEndedEvent : Event + { + private const int DEFAULT_PRIORITY = 100; // System event -> cannot be changed!; + + private readonly bool aborted; + private readonly BattleResults results; + + /// + /// + /// Called by the game to create a new BattleEndedEvent. + /// + public BattleEndedEvent(bool aborted, BattleResults results) + { + this.aborted = aborted; + this.results = results; + } + + /// + /// Checks if this battle was aborted. + /// Returns true if the battle was aborted + /// + public bool IsAborted + { + get { return aborted; } + } + + /// + /// Returns the battle results. + /// + public BattleResults Results + { + get { return results; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + /// + public override int Priority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (robot != null) + { + var listener = robot.GetBasicEventListener() as IBasicEvents2; + if (listener != null) + { + listener.OnBattleEnded(this); + } + } + } + + internal override bool IsCriticalEvent + { + get { return true; } + } + + internal override byte SerializationType + { + get { return RbSerializerN.BattleEndedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + var obj = (BattleEndedEvent) objec; + + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_BOOL + + serializer.sizeOf(RbSerializerN.BattleResults_TYPE, obj.results); + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (BattleEndedEvent) objec; + + serializer.serialize(buffer, obj.aborted); + serializer.serialize(buffer, RbSerializerN.BattleResults_TYPE, obj.results); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + bool aborted = serializer.deserializeBoolean(buffer); + var results = (BattleResults) serializer.deserializeAny(buffer); + + return new BattleEndedEvent(aborted, results); + } + } + } +} + +//docl \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleResults.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleResults.cs new file mode 100644 index 0000000..8975462 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleResults.cs @@ -0,0 +1,225 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.serialization; + +namespace Robocode +{ + /// + /// Contains the battle results returned by + /// when a battle has ended. + /// + /// + /// + [Serializable] + public class BattleResults : IComparable + { + internal string teamLeaderName; + internal int rank; + internal double score; + internal double survival; + internal double lastSurvivorBonus; + internal double bulletDamage; + internal double bulletDamageBonus; + internal double ramDamage; + internal double ramDamageBonus; + internal int firsts; + internal int seconds; + internal int thirds; + + /// + /// Constructs this BattleResults object. + /// + public BattleResults( + string teamLeaderName, + int rank, + double score, + double survival, + double lastSurvivorBonus, + double bulletDamage, + double bulletDamageBonus, + double ramDamage, + double ramDamageBonus, + int firsts, + int seconds, + int thirds + ) + { + this.teamLeaderName = teamLeaderName; + this.rank = rank; + this.score = score; + this.survival = survival; + this.lastSurvivorBonus = lastSurvivorBonus; + this.bulletDamage = bulletDamage; + this.bulletDamageBonus = bulletDamageBonus; + this.ramDamage = ramDamage; + this.ramDamageBonus = ramDamageBonus; + this.firsts = firsts; + this.seconds = seconds; + this.thirds = thirds; + } + + /// + /// Returns the name of the team leader in the team or the name of the + /// robot if the robot is not participating in a team. + /// + public string TeamLeaderName + { + get { return teamLeaderName; } + } + + /// + /// Returns the rank of this robot in the battle results. + /// + public int Rank + { + get { return rank; } + } + + /// + /// Returns the total score of this robot in the battle. + /// + public int Score + { + get { return (int) (score + 0.5); } + } + + /// + /// Returns the survival score of this robot in the battle. + /// + public int Survival + { + get { return (int) (survival + 0.5); } + } + + /// + /// Returns the last survivor score of this robot in the battle. + /// + public int LastSurvivorBonus + { + get { return (int) (lastSurvivorBonus + 0.5); } + } + + /// + /// Returns the bullet damage score of this robot in the battle. + /// + public int BulletDamage + { + get { return (int) (bulletDamage + 0.5); } + } + + /// + /// Returns the bullet damage bonus of this robot in the battle. + /// + public int BulletDamageBonus + { + get { return (int) (bulletDamageBonus + 0.5); } + } + + /// + /// Returns the ram damage score of this robot in the battle. + /// + public int RamDamage + { + get { return (int) (ramDamage + 0.5); } + } + + /// + /// Returns the ram damage bonus of this robot in the battle. + /// + public int RamDamageBonus + { + get { return (int) (ramDamageBonus + 0.5); } + } + + /// + /// Returns the number of rounds this robot placed first in the battle. + /// + public int Firsts + { + get { return firsts; } + } + + /// + /// Returns the number of rounds this robot placed second in the battle. + /// + public int Seconds + { + get { return seconds; } + } + + /// + /// Returns the number of rounds this robot placed third in the battle. + /// + public int Thirds + { + get { return thirds; } + } + + public int CompareTo(BattleResults o) + { + return score.CompareTo(o.score); + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + var obj = (BattleResults) objec; + + return RbSerializerN.SIZEOF_TYPEINFO + serializer.sizeOf(obj.teamLeaderName) + + 4*RbSerializerN.SIZEOF_INT + + 7*RbSerializerN.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (BattleResults) objec; + + serializer.serialize(buffer, obj.teamLeaderName); + serializer.serialize(buffer, obj.rank); + serializer.serialize(buffer, obj.score); + serializer.serialize(buffer, obj.survival); + serializer.serialize(buffer, obj.lastSurvivorBonus); + serializer.serialize(buffer, obj.bulletDamage); + serializer.serialize(buffer, obj.bulletDamageBonus); + serializer.serialize(buffer, obj.ramDamage); + serializer.serialize(buffer, obj.ramDamageBonus); + serializer.serialize(buffer, obj.firsts); + serializer.serialize(buffer, obj.seconds); + serializer.serialize(buffer, obj.thirds); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + string teamLeaderName = serializer.deserializeString(buffer); + int rank = buffer.getInt(); + double score = buffer.getDouble(); + double survival = buffer.getDouble(); + double lastSurvivorBonus = buffer.getDouble(); + double bulletDamage = buffer.getDouble(); + double bulletDamageBonus = buffer.getDouble(); + double ramDamage = buffer.getDouble(); + double ramDamageBonus = buffer.getDouble(); + int firsts = buffer.getInt(); + int seconds = buffer.getInt(); + int thirds = buffer.getInt(); + + return new BattleResults(teamLeaderName, rank, score, survival, lastSurvivorBonus, bulletDamage, + bulletDamageBonus, ramDamage, ramDamageBonus, firsts, seconds, thirds); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleRules.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleRules.cs new file mode 100644 index 0000000..461d0f1 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BattleRules.cs @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.security; + +namespace Robocode +{ + /// + /// Contains the battle rules returned by BattleStartedEvent.BattleRules + /// when a battle is started and BattleCompletedEvent.BattleRules + /// when a battle is completed. + /// + /// BattleStartedEvent + /// BattleCompletedEvent + [Serializable] + public sealed class BattleRules + { + private readonly int battlefieldWidth; + private readonly int battlefieldHeight; + private readonly int numRounds; + private readonly double gunCoolingRate; + private readonly long inactivityTime; + private readonly bool hideEnemyNames; + private readonly int sentryBorderSize; + + /// + /// Returns the battlefield width. + /// + public int BattlefieldWidth + { + get { return battlefieldWidth; } + } + + /// + /// Returns the battlefield height. + /// + public int BattlefieldHeight + { + get { return battlefieldHeight; } + } + + /// + /// Returns the number of rounds. + /// + public int NumRounds + { + get { return numRounds; } + } + + /// + /// Returns the rate at which the gun will cool down, i.e. the amount of heat the gun heat will drop per turn. + ///

+ /// The gun cooling rate is default 0.1 per turn, but can be changed by the battle setup. + /// So don't count on the cooling rate being 0.1! + /// + /// + /// + ///

+ public double GunCoolingRate + { + get { return gunCoolingRate; } + } + + /// + /// Returns the allowed inactivity time, where the robot is not taking any action, before will begin to be zapped. + /// The inactivity time is measured in turns, and is the allowed time that a robot is allowed to omit taking + /// action before being punished by the game by zapping. + ///

+ /// When a robot is zapped by the game, it will loose 0.1 energy points per turn. Eventually the robot will be + /// killed by zapping until the robot takes action. When the robot takes action, the inactivity time counter is + /// reset. + ///

+ /// The allowed inactivity time is per default 450 turns, but can be changed by the battle setup. + /// So don't count on the inactivity time being 450 turns! + /// + /// + ///

+ public long InactivityTime + { + get { return inactivityTime; } + } + + /// + /// Returns true if the enemy names are hidden, i.e. anonymous; false otherwise. + /// + public bool HideEnemyNames + { + get { return hideEnemyNames; } + } + + /// + /// Returns the sentry border size for a BorderSentry that defines the how + /// far a BorderSentry is allowed to move from the border edges measured in units.
+ /// Hence, the sentry border size defines the width/range of the border area surrounding the battlefield that + /// BorderSentrys cannot leave (sentry robots robots must stay in the border area), but it also define the + /// distance from the border edges where BorderSentrys are allowed/able to make damage to robots entering this + /// border area. + ///
+ public int SentryBorderSize + { + get { return sentryBorderSize; } + } + + private BattleRules(int battlefieldWidth, int battlefieldHeight, int numRounds, double gunCoolingRate, long inactivityTime, + bool hideEnemyNames, int sentryBorderSize) + { + this.battlefieldWidth = battlefieldWidth; + this.battlefieldHeight = battlefieldHeight; + this.numRounds = numRounds; + this.gunCoolingRate = gunCoolingRate; + this.inactivityTime = inactivityTime; + this.hideEnemyNames = hideEnemyNames; + this.sentryBorderSize = sentryBorderSize; + } + + private static IHiddenRulesHelper createHiddenHelper() + { + return new HiddenHelper(); + } + + private class HiddenHelper : IHiddenRulesHelper + { + public BattleRules createRules(int battlefieldWidth, int battlefieldHeight, int numRounds, double gunCoolingRate, long inactivityTime, + bool hideEnemyNames, int borderSentryRobotAttackRange) + { + return new BattleRules(battlefieldWidth, battlefieldHeight, numRounds, gunCoolingRate, inactivityTime, hideEnemyNames, borderSentryRobotAttackRange); + } + } + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Bullet.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Bullet.cs new file mode 100644 index 0000000..2a4ddef --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Bullet.cs @@ -0,0 +1,217 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.security; +using net.sf.robocode.serialization; +using Robocode.Util; + +namespace Robocode +{ + /// + /// + /// Represents a bullet. This is returned from + /// and , and all the bullet-related + /// events. + /// + /// + /// + /// + /// + /// + [Serializable] + public class Bullet + { + private readonly double headingRadians; + private double x; + private double y; + private readonly double power; + private readonly string ownerName; + private string victimName; + private bool _isActive; + private readonly int bulletId; + + /// + /// Called by the game to create a new Bullet object + /// + public Bullet(double heading, double x, double y, double power, string ownerName, string victimName, + bool isActive, int bulletId) + { + headingRadians = heading; + this.x = x; + this.y = y; + this.power = power; + this.ownerName = ownerName; + this.victimName = victimName; + _isActive = isActive; + this.bulletId = bulletId; + } + + public override bool Equals(Object obj) + { + if (obj is Bullet) + { + Bullet bullet = (Bullet)obj; + return bullet.bulletId == bulletId; + } + return Equals(obj); + } + + /// + /// Returns the direction the bullet is/was heading, in degrees + /// (0 <= getHeading() < 360). This is not relative to the direction you are facing. + /// + public double Heading + { + get { return Utils.ToDegrees(headingRadians); } + } + + /// + /// Returns the direction the bullet is/was heading, in radians + /// (0 <= getHeadingRadians() < 2 * Math.PI). This is not relative to the direction you are facing. + /// + public double HeadingRadians + { + get { return headingRadians; } + } + + /// + /// Returns the name of the robot that fired this bullet. + /// + public string Name + { + get { return ownerName; } + } + + /// + /// Returns the power of this bullet. + ///

+ /// The bullet will do (4 * power) damage if it hits another robot. + /// If power is greater than 1, it will do an additional 2 * (power - 1) + /// damage. You will get (3 * power) back if you hit the other robot. + ///

+ public double Power + { + get { return power; } + } + + /// + /// Returns the velocity of this bullet. The velocity of the bullet is + /// constant once it has been fired. + /// + public double Velocity + { + get { return Rules.GetBulletSpeed(power); } + } + + /// + /// Returns the name of the robot that this bullet hit, or null if + /// the bullet has not hit a robot. + /// + public string Victim + { + get { return victimName; } + } + + /// + /// Returns the X position of the bullet. + /// + public double X + { + get { return x; } + } + + /// + /// Returns the Y position of the bullet. + /// + public double Y + { + get { return y; } + } + + /// + /// Checks if this bullet is still active on the battlefield. + /// + public bool IsActive + { + get { return _isActive; } + } + + /// + /// Updates this bullet based on the specified bullet status. + /// + // this method is invisible on RobotAPI + private void update(double x, double y, string victimName, bool isActive) + { + this.x = x; + this.y = y; + this.victimName = victimName; + _isActive = isActive; + } + + internal int getBulletId() + { + return bulletId; + } + + private static IHiddenBulletHelper createHiddenHelper() + { + return new HiddenBulletHelper(); + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new HiddenBulletHelper(); + } + + private class HiddenBulletHelper : IHiddenBulletHelper, ISerializableHelperN + { + public void update(Bullet bullet, double x, double y, string victimName, bool isActive) + { + bullet.update(x, y, victimName, isActive); + } + + public int sizeOf(RbSerializerN serializer, object objec) + { + var obj = (Bullet)objec; + + return RbSerializerN.SIZEOF_TYPEINFO + 4 * RbSerializerN.SIZEOF_DOUBLE + serializer.sizeOf(obj.ownerName) + + serializer.sizeOf(obj.victimName) + RbSerializerN.SIZEOF_BOOL + RbSerializerN.SIZEOF_INT; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (Bullet)objec; + + serializer.serialize(buffer, obj.headingRadians); + serializer.serialize(buffer, obj.x); + serializer.serialize(buffer, obj.y); + serializer.serialize(buffer, obj.power); + serializer.serialize(buffer, obj.ownerName); + serializer.serialize(buffer, obj.victimName); + serializer.serialize(buffer, obj._isActive); + serializer.serialize(buffer, obj.bulletId); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + double headingRadians = buffer.getDouble(); + double x = buffer.getDouble(); + double y = buffer.getDouble(); + double power = buffer.getDouble(); + string ownerName = serializer.deserializeString(buffer); + string victimName = serializer.deserializeString(buffer); + bool isActive = serializer.deserializeBoolean(buffer); + int bulletId = serializer.deserializeInt(buffer); + + return new Bullet(headingRadians, x, y, power, ownerName, victimName, isActive, bulletId); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletHitBulletEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletHitBulletEvent.cs new file mode 100644 index 0000000..6723d1b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletHitBulletEvent.cs @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// This event is sent to + /// when one of your bullets has hit another bullet. + /// + [Serializable] + public sealed class BulletHitBulletEvent : Event + { + private const int DEFAULT_PRIORITY = 55; + + private Bullet bullet; + private readonly Bullet hitBullet; + + /// + /// Called by the game to create a new BulletHitEvent. + /// + public BulletHitBulletEvent(Bullet bullet, Bullet hitBullet) + { + this.bullet = bullet; + this.hitBullet = hitBullet; + } + + /// + /// Returns your bullet that hit another bullet. + /// + public Bullet Bullet + { + get { return bullet; } + } + + /// + /// Returns the bullet that was hit by your bullet. + /// + public Bullet HitBullet + { + get { return hitBullet; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnBulletHitBullet(this); + } + } + + // Needed for .NET version + internal override void UpdateBullets(Dictionary bullets) + { + // we need to pass same instance + bullet = bullets[bullet.getBulletId()]; + } + + internal override byte SerializationType + { + get { return RbSerializerN.BulletHitBulletEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + var obj = (BulletHitBulletEvent) objec; + + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_INT + + serializer.sizeOf(RbSerializerN.Bullet_TYPE, obj.hitBullet); + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (BulletHitBulletEvent) objec; + + // no need to transmit whole bullet, rest of it is already known to proxy side + serializer.serialize(buffer, obj.bullet.getBulletId()); + serializer.serialize(buffer, RbSerializerN.Bullet_TYPE, obj.hitBullet); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + var bullet = new Bullet(0, 0, 0, 0, null, null, false, buffer.getInt()); + var hitBullet = (Bullet) serializer.deserializeAny(buffer); + + return new BulletHitBulletEvent(bullet, hitBullet); + } + } + } +} + +//doc diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletHitEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletHitEvent.cs new file mode 100644 index 0000000..bc35644 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletHitEvent.cs @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// This event is sent to + /// when one of your bullets has hit another robot. + /// + [Serializable] + public sealed class BulletHitEvent : Event + { + private const int DEFAULT_PRIORITY = 50; + + private readonly string name; + private readonly double energy; + private Bullet bullet; + + /// + /// Called by the game to create a new BulletHitEvent. + /// + public BulletHitEvent(string name, double energy, Bullet bullet) + { + this.name = name; + this.energy = energy; + this.bullet = bullet; + } + + /// + /// Returns the bullet of yours that hit the robot. + /// + public Bullet Bullet + { + get { return bullet; } + } + + /// + /// Returns the remaining energy of the robot your bullet has hit (after the + /// damage done by your bullet). + /// + public double VictimEnergy + { + get { return energy; } + } + + /// + /// Returns the name of the robot your bullet hit. + /// + public string VictimName + { + get { return name; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnBulletHit(this); + } + } + + // Needed for .NET version + internal override void UpdateBullets(Dictionary bullets) + { + // we need to pass same instance + bullet = bullets[bullet.getBulletId()]; + } + + internal override byte SerializationType + { + get { return RbSerializerN.BulletHitEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + var obj = (BulletHitEvent) objec; + + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_INT + serializer.sizeOf(obj.name) + + RbSerializerN.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (BulletHitEvent) objec; + + serializer.serialize(buffer, obj.bullet.getBulletId()); + serializer.serialize(buffer, obj.name); + serializer.serialize(buffer, obj.energy); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + var bullet = new Bullet(0, 0, 0, 0, null, null, false, buffer.getInt()); + string name = serializer.deserializeString(buffer); + double energy = buffer.getDouble(); + + return new BulletHitEvent(name, energy, bullet); + } + } + } +} + +//doc diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletMissedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletMissedEvent.cs new file mode 100644 index 0000000..19294d6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/BulletMissedEvent.cs @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// This event is sent to + /// when one of your bullets has missed, i.e. when the bullet has + /// reached the border of the battlefield. + /// + [Serializable] + public sealed class BulletMissedEvent : Event + { + private const int DEFAULT_PRIORITY = 60; + + private Bullet bullet; + + /// + /// + /// Called by the game to create a new BulletMissedEvent. + /// + public BulletMissedEvent(Bullet bullet) + { + this.bullet = bullet; + } + + /// + /// + /// Returns the bullet that missed. + /// + public Bullet Bullet + { + get { return bullet; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnBulletMissed(this); + } + } + + // Needed for .NET version + internal override void UpdateBullets(Dictionary bullets) + { + // we need to pass same instance + bullet = bullets[bullet.getBulletId()]; + } + + internal override byte SerializationType + { + get { return RbSerializerN.BulletMissedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_INT; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (BulletMissedEvent) objec; + + serializer.serialize(buffer, obj.bullet.getBulletId()); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + var bullet = new Bullet(0, 0, 0, 0, null, null, false, buffer.getInt()); + + return new BulletMissedEvent(bullet); + } + } + } +} +//doc diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Condition.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Condition.cs new file mode 100644 index 0000000..974fcea --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Condition.cs @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.io; + +namespace Robocode +{ + /// + /// Condition is used to define custom + /// and custom events for an AdvancedRobot. The code below is taken from the sample robot + /// named samplecs.Target. See the samplecs/Target.cs for details. + /// + /// + /// AddCustomEvent( + /// new Condition("triggerhit", (c) => + /// { + /// return Energy <= trigger; + /// })); + /// + /// + /// + /// + /// + /// + /// + public class Condition + { + private readonly ConditionTest test; + + /// + /// The priority of this condition. Defaults to 80. + /// + public int priority = 80; + + /// + /// The name of this condition. + /// + public string name; + + /// + /// Convinience constructor, allows to pass delegate to method, instead of overriding Test() method. + /// + public Condition(string name, int priority, ConditionTest test) + : this(name, priority) + { + this.test = test; + } + + /// + /// Convinience constructor, allows to pass delegate to method, instead of overriding Test() method. + /// + public Condition(string name, ConditionTest test) + : this(name) + { + this.test = test; + } + + /// + /// Convinience constructor, allows to pass delegate to method, instead of overriding Test() method. + /// + public Condition(ConditionTest test) + { + this.test = test; + } + + /// + /// Creates a new, unnamed Condition with the default priority, which is 80. + /// + protected Condition() + { + } + + /// + /// Creates a new Condition with the specified name, and default priority, which is 80. + /// + /// The name for the new Condition + protected Condition(string name) + { + this.name = name; + } + + /// + /// Creates a new Condition with the specified name and priority. + /// A condition priority is a value from 0 - 99. The higher value, the + /// higher priority. The default priority is 80. + /// + /// The name for the new condition + /// The priority of the new condition + protected Condition(string name, int priority) + { + this.name = name; + if (priority < 0) + { + LoggerN.WriteLineToRobotsConsole("SYSTEM: Priority must be between 0 and 99."); + LoggerN.WriteLineToRobotsConsole("SYSTEM: Priority for condition " + name + " will be 0."); + priority = 0; + } + else if (priority > 99) + { + LoggerN.WriteLineToRobotsConsole("SYSTEM: Priority must be between 0 and 99."); + LoggerN.WriteLineToRobotsConsole("SYSTEM: Priority for condition " + name + " will be 99."); + priority = 99; + } + this.priority = priority; + } + + /// + /// Returns the name of this condition. + /// + public string Name + { + get { return name ?? GetType().Name; } + set { name = value; } + } + + /// + /// Returns the priority of this condition. + /// A condition priority is a value from 0 - 99. The higher value, the + /// higher priority. The default priority is 80. + /// + public int Priority + { + get { return priority; } + set { priority=value; } + } + + /// + /// Overriding the Test() method is the point of a Condition. + /// The game will call your Test() function, and take action if it returns true. + /// This is valid for both and + /// + ///

+ /// You may not take any actions inside of Test(). + ///

+ public virtual bool Test() + { + if (test != null) + { + return test(this); + } + throw new NotImplementedException("You should inherit from Condition class and override Test() method or pass delegate into constructor"); + } + } + + /// + /// Method signature for Test method of + /// + public delegate bool ConditionTest(Condition condition); +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/CustomEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/CustomEvent.cs new file mode 100644 index 0000000..7a3ec36 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/CustomEvent.cs @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.peer; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// This event is sent to + /// when a custom condition is met. Be sure to reset or remove the custom condition to avoid + /// having it recurring repeatedly (see the example for the method. + /// + /// + [Serializable] + public class CustomEvent : Event + { + private const int DEFAULT_PRIORITY = 80; + + private readonly Condition condition; + + /// + /// Called by the game to create a new CustomEvent when a condition is met. + /// + public CustomEvent(Condition condition) + { + this.condition = condition; + if (condition != null) + { + Priority = condition.Priority; + } + } + + /// + /// Called by the game to create a new CustomEvent when a condition is met. + /// The event will have the given priority. + /// An event priority is a value from 0 - 99. The higher value, the higher + /// priority. The default priority is 80. + ///

+ /// This is equivalent to calling on the + /// Condition. + ///

+ /// The condition that must be met + /// The priority of the condition + public CustomEvent(Condition condition, int priority) + { + this.condition = condition; + Priority = priority; + if (condition != null) + { + condition.Priority = priority; + } + } + + /// + /// Returns the condition that fired, causing this event to be generated. + /// Use this to determine which condition fired, and to remove the custom event. + /// + /// + /// public void OnCustomEvent(CustomEvent evnt) + /// { + /// if (event.Condition.Name == "mycondition") + /// { + /// RemoveCustomEvent(event.Condition); + /// // do something else + /// } + /// } + /// + /// + /// + public Condition Condition + { + get { return condition; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override sealed void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsAdvancedRobot()) + { + IAdvancedEvents listener = ((IAdvancedRobot) robot).GetAdvancedEventListener(); + + if (listener != null) + { + listener.OnCustomEvent(this); + } + } + } + + // sealed to disable overrides + public override sealed int CompareTo(Event evnt) + { + return base.CompareTo(evnt); + } + + // sealed to disable overrides + internal override bool IsCriticalEvent + { + get { return false; } + } + + // sealed to disable overrides + public sealed override int Priority + { + get { return base.Priority; } + } + + internal override byte SerializationType + { + get { throw new System.Exception("Serialization not supported on this event type"); } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/DeathEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/DeathEvent.cs new file mode 100644 index 0000000..7c02457 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/DeathEvent.cs @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// This event is sent to when your robot dies. + /// + [Serializable] + public sealed class DeathEvent : Event + { + private const int DEFAULT_PRIORITY = -1; // System event -> cannot be changed!; + + /// + public override int Priority + { + get { return DEFAULT_PRIORITY; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnDeath(this); + } + } + + internal override bool IsCriticalEvent + { + get { return true; } + } + + internal override byte SerializationType + { + get { return RbSerializerN.DeathEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + return new DeathEvent(); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Event.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Event.cs new file mode 100644 index 0000000..b09b84b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Event.cs @@ -0,0 +1,279 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using net.sf.robocode.io; +using net.sf.robocode.peer; +using net.sf.robocode.security; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// The superclass of all Robocode events. + /// + [Serializable] + public abstract class Event : IComparable + { + private const int DEFAULT_PRIORITY = 80; + + private long time; + private int priority; + + // time is valid only after adding to event manager on proxy side, we do not update it on battle side + private volatile bool addedToQueue; + + /// + /// Compares this event to another event regarding precedence. + /// + /// The event precedence is first and foremost determined by the event time, + /// secondly the event priority, and lastly specific event information. + /// + /// This method will first compare the time of each event. If the event time + /// is the same for both events, then this method compared the priority of + /// each event. If the event priorities are equals, then this method will + /// compare the two events based on specific event information. + /// + /// This method is called by the game in order to sort the event queue of a + /// robot to make sure the events are listed in chronological order. + /// + /// + /// the event to compare to this event. + /// + /// Returns a negative value if this event has higher precedence, i.e. must + /// be listed before the specified event. A positive value if this event + /// has a lower precedence, i.e. must be listed after the specified event. + /// 0 means that the precedence of the two events are equal. + /// + public virtual int CompareTo(Event evnt) + { + // Compare the time difference which has precedence over priority. + var timeDiff = (int) (time - evnt.time); + + if (timeDiff != 0) + { + return timeDiff; // Time differ + } + + // Same time -> Compare the difference in priority + int priorityDiff = evnt.Priority - Priority; + + if (priorityDiff != 0) + { + return priorityDiff; // Priority differ + } + + // Same time and priority -> Compare specific event types + // look at overrides in ScannedRobotEvent and HitRobotEvent + + // No difference found + return 0; + } + + /// + /// The time when this event occurred. + /// + /// + /// Note that the time is equal to the turn of a battle round. + /// + /// This method is intended for letting robot developers create their own event types. + /// It is not possible to change the time of an event after it has been added to the event + /// queue of the robot. + /// + public long Time + { + get { return time; } + set + { + if (addedToQueue) + { + LoggerN.WriteLineToRobotsConsole("SYSTEM: The time of an event cannot be changed after it has been added the event queue."); + } + else + { + time = value; + } + } + } + + /// + /// The priority of this event. + /// + /// An event priority is a value from 0 - 99. The higher value, the higher priority. + /// + /// The default priority is 80, but varies depending on the type of event. + /// + /// + /// This method is intended for letting robot developers create their own event types. + /// + /// It is not possible to change the priority of an event after it has been added to the event + /// queue of the robot. + /// + /// + public virtual int Priority + { + get { return priority; } + set + { + if (addedToQueue) + { + LoggerN.WriteLineToRobotsConsole("SYSTEM: The priority of an event cannot be changed after it has been added the event queue."); + } + else + { + SetPriorityHidden(value); + } + } + } + + /// + /// Hidden method for setting the exact time when this event occurred. + /// + /// + /// This method is called by the game engine only. + /// + /// the time when this event occurred. + // This method must be invisible on Robot API + private void SetTimeHidden(long time) + { + // we do not replace time which is set by robot to the future + if (this.time < time) + { + this.time = time; + } + // when this flag is set, robots are not allowed to change the time or priority of the event anymore + addedToQueue = true; + } + + /// + /// Hidden method for setting the priority from the game engine without checking for the 'addedToQueue' flag. + /// + /// + /// This method is called by the game engine only. + /// + /// the new priority of this event. + // This method must be invisible on Robot API + private void SetPriorityHidden(int newPriority) + { + if (newPriority < 0) + { + LoggerN.WriteLineToRobotsConsole("SYSTEM: Priority must be between 0 and 99"); + LoggerN.WriteLineToRobotsConsole("SYSTEM: Priority for " + GetType().Name + " will be 0"); + newPriority = 0; + } + else if (newPriority > 99) + { + LoggerN.WriteLineToRobotsConsole("SYSTEM: Priority must be between 0 and 99"); + LoggerN.WriteLineToRobotsConsole("SYSTEM: Priority for " + GetType().Name + " will be 99"); + newPriority = 99; + } + priority = newPriority; + } + + /// + /// Dispatch this event for a robot, it's statistics, and graphics context. + /// + /// the robot to dispatch to. + /// the robot to statistics to. + /// the robot to graphics to. + // This method must be invisible on Robot API + internal virtual void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + } + + /// + /// The default priority of this event class. + /// + // This method must be invisible on Robot API + internal virtual int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + /// + /// Checks if this event must be delivered even after timeout. + /// + /// + /// true when this event must be delivered even after timeout; + /// false otherwise. + /// + // This method must be invisible on Robot API + internal virtual bool IsCriticalEvent + { + get { return false; } + } + + // This method must be invisible on Robot API + internal virtual byte SerializationType + { + get { throw new System.Exception("Serialization not supported on this event type"); } + } + + // Needed for .NET version + // This method must be invisible on Robot API + internal virtual void UpdateBullets(Dictionary bullets) + { + } + + /// + /// Returns a hidden event helper for accessing hidden methods on this object. + /// + // This method must be invisible on Robot API + private static IHiddenEventHelper createHiddenHelper() + { + return new HiddenEventHelper(); + } + + /// + /// Hidden event helper implementation for accessing the internal methods of an event. + /// + /// + /// This class is used internally by the game engine. + /// + // This method must be invisible on Robot API + private class HiddenEventHelper : IHiddenEventHelper + { + public void SetTime(Event evnt, long newTime) + { + evnt.SetTimeHidden(newTime); + } + + public void SetDefaultPriority(Event evnt) + { + evnt.Priority = evnt.DefaultPriority; + } + + public void SetPriority(Event evnt, int newPriority) + { + evnt.SetPriorityHidden(newPriority); + } + + public bool IsCriticalEvent(Event evnt) + { + return evnt.IsCriticalEvent; + } + + public void Dispatch(Event evnt, IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + evnt.Dispatch(robot, statics, graphics); + } + + public byte GetSerializationType(Event evnt) + { + return evnt.SerializationType; + } + + // Needed for .NET version + public void UpdateBullets(Event evnt, Dictionary bullets) + { + evnt.UpdateBullets(bullets); + } + } + } +} +//doc diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/GunTurnCompleteCondition.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/GunTurnCompleteCondition.cs new file mode 100644 index 0000000..e6f7fe0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/GunTurnCompleteCondition.cs @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode +{ + /// + /// A prebuilt condition you can use that indicates your gun has finished turning. + /// + /// + public class GunTurnCompleteCondition : Condition + { + private readonly AdvancedRobot robot; + + /// + /// Creates a new GunTurnCompleteCondition with default priority. + /// The default priority is 80. + /// + /// Your robot, which must be an + public GunTurnCompleteCondition(AdvancedRobot robot) + { + this.robot = robot; + } + + /// + /// Creates a new GunTurnCompleteCondition with a specific priority. + /// A condition priority is a value from 0 - 99. The higher value, the + /// higher priority. The default priority is 80. + /// + /// + /// Your robot, which must be an + /// The priority of this condition + public GunTurnCompleteCondition(AdvancedRobot robot, int priority) + { + this.robot = robot; + this.priority = priority; + } + + /// + /// Tests if the gun has stopped turning. + /// Returns true if the gun has stopped turning + /// + public override bool Test() + { + return (robot.GunTurnRemaining == 0); + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitByBulletEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitByBulletEvent.cs new file mode 100644 index 0000000..394eff0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitByBulletEvent.cs @@ -0,0 +1,177 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A HitByBulletEvent is sent to + /// when your robot has been hit by a bullet. + /// You can use the information contained in this event to determine what to do. + /// + [Serializable] + public sealed class HitByBulletEvent : Event + { + private const int DEFAULT_PRIORITY = 20; + + private readonly double bearing; + private readonly Bullet bullet; + + /// + /// Called by the game to create a new HitByBulletEvent. + /// + public HitByBulletEvent(double bearing, Bullet bullet) + { + this.bearing = bearing; + this.bullet = bullet; + } + + /// + /// Returns the bearing to the bullet, relative to your robot's heading, + /// in degrees (-180 < getBearing() <= 180). + ///

+ /// If you were to TurnRight(event.Bearing), you would be facing the + /// direction the bullet came from. The calculation used here is: + /// (bullet's heading in degrees + 180) - (your heading in degrees) + ///

+ public double Bearing + { + get { return bearing*180.0/Math.PI; } + } + + /// + /// Returns the bearing to the bullet, relative to your robot's heading, + /// in radians (-Math.PI < getBearingRadians() <= Math.PI). + ///

+ /// If you were to TurnRightRadians(event.BearingRadians), you would be + /// facing the direction the bullet came from. The calculation used here is: + /// (bullet's heading in radians + Math.PI) - (your heading in radians) + ///

+ public double BearingRadians + { + get { return bearing; } + } + + /// + /// Returns the bullet that hit your robot. + /// + public Bullet Bullet + { + get { return bullet; } + } + + /// + /// Returns the heading of the bullet when it hit you, in degrees + /// (0 <= getHeading() < 360). + ///

+ /// Note: This is not relative to the direction you are facing. The robot + /// that fired the bullet was in the opposite direction of getHeading() when + /// it fired the bullet. + ///

+ public double Heading + { + get { return bullet.Heading; } + } + + /// + /// Returns the heading of the bullet when it hit you, in radians + /// (0 <= getHeadingRadians() < 2 * PI). + ///

+ /// Note: This is not relative to the direction you are facing. The robot + /// that fired the bullet was in the opposite direction of + /// getHeadingRadians() when it fired the bullet. + ///

+ public double HeadingRadians + { + get { return bullet.HeadingRadians; } + } + + /// + /// Returns the name of the robot that fired the bullet. + /// + public string Name + { + get { return bullet.Name; } + } + + /// + /// Returns the power of this bullet. The damage you take (in fact, already + /// took) is 4 * power, plus 2 * (power-1) if power > 1. The robot that fired + /// the bullet receives 3 * power back. + /// + public double Power + { + get { return bullet.Power; } + } + + /// + /// Returns the velocity of this bullet. + /// + public double Velocity + { + get { return bullet.Velocity; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnHitByBullet(this); + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.HitByBulletEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + var obj = (HitByBulletEvent) objec; + + return RbSerializerN.SIZEOF_TYPEINFO + serializer.sizeOf(RbSerializerN.Bullet_TYPE, obj.bullet) + + RbSerializerN.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (HitByBulletEvent) objec; + + serializer.serialize(buffer, RbSerializerN.Bullet_TYPE, obj.bullet); + serializer.serialize(buffer, obj.bearing); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + var bullet = (Bullet) serializer.deserializeAny(buffer); + double bearing = buffer.getDouble(); + + return new HitByBulletEvent(bearing, bullet); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitRobotEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitRobotEvent.cs new file mode 100644 index 0000000..675b933 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitRobotEvent.cs @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A HitRobotEvent is sent to + /// when your robot collides with another robot. + /// You can use the information contained in this event to determine what to do. + /// + [Serializable] + public sealed class HitRobotEvent : Event + { + private const int DEFAULT_PRIORITY = 40; + + private readonly string name; + private readonly double bearing; + private readonly double energy; + private readonly bool atFault; + + /// + /// Called by the game to create a new HitRobotEvent. + /// + public HitRobotEvent(string name, double bearing, double energy, bool atFault) + { + this.name = name; + this.bearing = bearing; + this.energy = energy; + this.atFault = atFault; + } + + /// + /// Returns the bearing to the robot you hit, relative to your robot's + /// heading, in degrees (-180 <= getBearing() < 180) + /// + public double Bearing + { + get { return bearing*180.0/Math.PI; } + } + + /// + /// Returns the bearing to the robot you hit, relative to your robot's + /// heading, in radians (-PI <= getBearingRadians() < PI) + /// + public double BearingRadians + { + get { return bearing; } + } + + /// + /// Returns the amount of energy of the robot you hit. + /// + public double Energy + { + get { return energy; } + } + + /// + /// Returns the name of the robot you hit. + /// + public string Name + { + get { return name; } + } + + /// + /// Checks if your robot was moving towards the robot that was hit. + ///

+ /// If returns true then your robot's movement (including + /// turning) will have stopped and been marked complete. + ///

+ /// Note: If two robots are moving toward each other and collide, they will + /// each receive two HitRobotEvents. The first will be the one if isMyFault() + /// returns true. + ///

+ public bool IsMyFault + { + get { return atFault; } + } + + /// + public override int CompareTo(Event evnt) + { + int res = base.CompareTo(evnt); + + if (res != 0) + { + return res; + } + + // Compare the IsMyFault, if the events are HitRobotEvents + // The isMyFault has higher priority when it is set compared to when it is not set + if (evnt is HitRobotEvent) + { + int compare1 = (this).IsMyFault ? -1 : 0; + int compare2 = ((HitRobotEvent) evnt).IsMyFault ? -1 : 0; + + return compare1 - compare2; + } + + // No difference found + return 0; + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnHitRobot(this); + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.HitRobotEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + var obj = (HitRobotEvent) objec; + + return RbSerializerN.SIZEOF_TYPEINFO + serializer.sizeOf(obj.name) + 2*RbSerializerN.SIZEOF_DOUBLE + + RbSerializerN.SIZEOF_BOOL; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (HitRobotEvent) objec; + + serializer.serialize(buffer, obj.name); + serializer.serialize(buffer, obj.bearing); + serializer.serialize(buffer, obj.energy); + serializer.serialize(buffer, obj.atFault); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + string robotName = serializer.deserializeString(buffer); + double bearing = buffer.getDouble(); + double energy = buffer.getDouble(); + bool atFault = serializer.deserializeBoolean(buffer); + + return new HitRobotEvent(robotName, bearing, energy, atFault); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitWallEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitWallEvent.cs new file mode 100644 index 0000000..1b73982 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/HitWallEvent.cs @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A HitWallEvent is sent to + /// when you collide a wall. + /// You can use the information contained in this event to determine what to do. + /// + [Serializable] + public sealed class HitWallEvent : Event + { + private const int DEFAULT_PRIORITY = 30; + + private readonly double bearing; + + /// + /// Called by the game to create a new HitWallEvent. + /// + public HitWallEvent(double bearing) + { + this.bearing = bearing; + } + + /// + /// Returns the bearing to the wall you hit, relative to your robot's + /// heading, in degrees (-180 <= getBearing() < 180) + /// + public double Bearing + { + get { return bearing*180.0/Math.PI; } + } + + + /// + /// Returns the bearing to the wall you hit, relative to your robot's + /// heading, in radians (-PI <= getBearingRadians() < PI) + /// + public double BearingRadians + { + get { return bearing; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnHitWall(this); + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.HitWallEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (HitWallEvent) objec; + + serializer.serialize(buffer, obj.bearing); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + double bearing = buffer.getDouble(); + + return new HitWallEvent(bearing); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IBorderSentry.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IBorderSentry.cs new file mode 100644 index 0000000..ea60f9c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IBorderSentry.cs @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode +{ + /// + /// A robot that implement IBorderSentry is a robot type used for keeping other robots away from the borders, + /// i.e. guarding the borders in order to prevent "wall crawlers".
+ /// Robots that implement IBorderSentry have 400 extra life/energy (500 in total), but is placed at the border + /// of the battlefield when the game is started.
+ /// Border sentry robots cannot move away from the border area, and they can only make damage to robots that + /// are moving into the border area. The size of the border area is determined by the + /// battle rules.
+ /// This type of robot is intended for use in battles where robots should be forced away from the borders in + /// order to prevent "wall crawlers".
+ /// Border sentry robots does not get scores, and will not occur in the battle results or rankings. + ///
+ /// + /// + /// + /// + /// + /// + /// + public interface IBorderSentry + { + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IDroid.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IDroid.cs new file mode 100644 index 0000000..4c682b3 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IDroid.cs @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode +{ + /// + /// Robots that implement IDroid have no scanner, but an extra 20 life/energy. + /// This class is intended for use in teams. + /// + /// + /// + /// + /// + /// + /// + public interface IDroid + { + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IGraphics.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IGraphics.cs new file mode 100644 index 0000000..e92c808 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/IGraphics.cs @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Drawing; + +namespace Robocode +{ + /// + /// + /// + public interface IGraphics + { +#pragma warning disable 1591 + //TODO xml doc + void DrawLine(Pen pen, float x1, float y1, float x2, float y2); + void DrawLine(Pen pen, PointF pt1, PointF pt2); + void DrawLine(Pen pen, int x1, int y1, int x2, int y2); + void DrawLine(Pen pen, Point pt1, Point pt2); + void DrawArc(Pen pen, float x, float y, float width, float height, float startAngle, float sweepAngle); + void DrawArc(Pen pen, RectangleF rect, float startAngle, float sweepAngle); + void DrawArc(Pen pen, int x, int y, int width, int height, int startAngle, int sweepAngle); + void DrawArc(Pen pen, Rectangle rect, float startAngle, float sweepAngle); + void DrawRectangle(Pen pen, RectangleF rect); + void DrawRectangle(Pen pen, Rectangle rect); + void DrawRectangle(Pen pen, float x, float y, float width, float height); + void DrawRectangle(Pen pen, int x, int y, int width, int height); + void DrawEllipse(Pen pen, RectangleF rect); + void DrawEllipse(Pen pen, float x, float y, float width, float height); + void DrawEllipse(Pen pen, Rectangle rect); + void DrawEllipse(Pen pen, int x, int y, int width, int height); + void DrawPie(Pen pen, RectangleF rect, float startAngle, float sweepAngle); + void DrawPie(Pen pen, float x, float y, float width, float height, float startAngle, float sweepAngle); + void DrawPie(Pen pen, Rectangle rect, float startAngle, float sweepAngle); + void DrawPie(Pen pen, int x, int y, int width, int height, int startAngle, int sweepAngle); + void DrawPolygon(Pen pen, PointF[] points); + void DrawPolygon(Pen pen, Point[] points); + void FillRectangle(Brush brush, RectangleF rect); + void FillRectangle(Brush brush, float x, float y, float width, float height); + void FillRectangle(Brush brush, Rectangle rect); + void FillRectangle(Brush brush, int x, int y, int width, int height); + void FillPolygon(Brush brush, PointF[] points); + void FillPolygon(Brush brush, Point[] points); + void FillEllipse(Brush brush, RectangleF rect); + void FillEllipse(Brush brush, float x, float y, float width, float height); + void FillEllipse(Brush brush, Rectangle rect); + void FillEllipse(Brush brush, int x, int y, int width, int height); + void FillPie(Brush brush, Rectangle rect, float startAngle, float sweepAngle); + void FillPie(Brush brush, float x, float y, float width, float height, float startAngle, float sweepAngle); + void FillPie(Brush brush, int x, int y, int width, int height, int startAngle, int sweepAngle); + void DrawString(string s, Font font, Brush brush, int x, int y); + void DrawString(string s, Font font, Brush brush, float x, float y); + void DrawString(string s, Font font, Brush brush, PointF point); + void DrawString(string s, Font font, Brush brush, Point point); + + /* + void DrawLines(Pen pen, PointF[] points); + void DrawLines(Pen pen, Point[] points); + void DrawRectangles(Pen pen, RectangleF[] rects); + void DrawRectangles(Pen pen, Rectangle[] rects); + void DrawPath(Pen pen, GraphicsPath path); + void DrawCurve(Pen pen, PointF[] points); + void DrawCurve(Pen pen, PointF[] points, float tension); + void DrawCurve(Pen pen, PointF[] points, int offset, int numberOfSegments); + void DrawCurve(Pen pen, PointF[] points, int offset, int numberOfSegments, float tension); + void DrawCurve(Pen pen, Point[] points); + void DrawCurve(Pen pen, Point[] points, float tension); + void DrawCurve(Pen pen, Point[] points, int offset, int numberOfSegments, float tension); + void DrawClosedCurve(Pen pen, PointF[] points); + void DrawClosedCurve(Pen pen, PointF[] points, float tension, FillMode fillmode); + void DrawClosedCurve(Pen pen, Point[] points); + void DrawClosedCurve(Pen pen, Point[] points, float tension, FillMode fillmode); + void FillPolygon(Brush brush, PointF[] points, FillMode fillMode); + void FillPolygon(Brush brush, Point[] points, FillMode fillMode); + void FillRectangles(Brush brush, RectangleF[] rects); + void FillRectangles(Brush brush, Rectangle[] rects); + void FillClosedCurve(Brush brush, PointF[] points); + void FillClosedCurve(Brush brush, PointF[] points, FillMode fillmode); + void FillClosedCurve(Brush brush, PointF[] points, FillMode fillmode, float tension); + void FillClosedCurve(Brush brush, Point[] points); + void FillClosedCurve(Brush brush, Point[] points, FillMode fillmode); + void FillClosedCurve(Brush brush, Point[] points, FillMode fillmode, float tension); + void FillRegion(Brush brush, Region region); + void FillPath(Brush brush, GraphicsPath path); + void DrawString(string s, Font font, Brush brush, float x, float y, StringFormat format); + void DrawString(string s, Font font, Brush brush, PointF point, StringFormat format); + void DrawString(string s, Font font, Brush brush, RectangleF layoutRectangle); + void DrawString(string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format); + + SizeF MeasureString(string text, Font font, SizeF layoutArea, StringFormat stringFormat, + out int charactersFitted, out int linesFilled); + + SizeF MeasureString(string text, Font font, PointF origin, StringFormat stringFormat); + SizeF MeasureString(string text, Font font, SizeF layoutArea); + SizeF MeasureString(string text, Font font, SizeF layoutArea, StringFormat stringFormat); + SizeF MeasureString(string text, Font font); + SizeF MeasureString(string text, Font font, int width); + SizeF MeasureString(string text, Font font, int width, StringFormat format); + Region[] MeasureCharacterRanges(string text, Font font, RectangleF layoutRect, StringFormat stringFormat); + + void ResetTransform(); + void MultiplyTransform(Matrix matrix); + void MultiplyTransform(Matrix matrix, MatrixOrder order); + void TranslateTransform(float dx, float dy); + void TranslateTransform(float dx, float dy, MatrixOrder order); + void ScaleTransform(float sx, float sy); + void ScaleTransform(float sx, float sy, MatrixOrder order); + void RotateTransform(float angle); + void RotateTransform(float angle, MatrixOrder order); + void TransformPoints(CoordinateSpace destSpace, CoordinateSpace srcSpace, PointF[] pts); + void TransformPoints(CoordinateSpace destSpace, CoordinateSpace srcSpace, Point[] pts); + void SetClip(Graphics g); + void SetClip(Graphics g, CombineMode combineMode); + void SetClip(Rectangle rect); + void SetClip(Rectangle rect, CombineMode combineMode); + void SetClip(RectangleF rect); + void SetClip(RectangleF rect, CombineMode combineMode); + void SetClip(GraphicsPath path); + void SetClip(GraphicsPath path, CombineMode combineMode); + void SetClip(Region region, CombineMode combineMode); + void IntersectClip(Rectangle rect); + void IntersectClip(RectangleF rect); + void IntersectClip(Region region); + void ExcludeClip(Rectangle rect); + void ExcludeClip(Region region); + void ResetClip(); + void TranslateClip(float dx, float dy); + void TranslateClip(int dx, int dy); + bool IsVisible(int x, int y); + bool IsVisible(Point point); + bool IsVisible(float x, float y); + bool IsVisible(PointF point); + bool IsVisible(int x, int y, int width, int height); + bool IsVisible(Rectangle rect); + bool IsVisible(float x, float y, float width, float height); + bool IsVisible(RectangleF rect); + CompositingMode CompositingMode { get; set; } + Point RenderingOrigin { get; set; } + CompositingQuality CompositingQuality { get; set; } + TextRenderingHint TextRenderingHint { get; set; } + int TextContrast { get; set; } + SmoothingMode SmoothingMode { get; set; } + PixelOffsetMode PixelOffsetMode { get; set; } + InterpolationMode InterpolationMode { get; set; } + Matrix Transform { get; set; } + GraphicsUnit PageUnit { get; set; } + float PageScale { get; set; } + float DpiX { get; } + float DpiY { get; } + Region Clip { get; set; } + RectangleF ClipBounds { get; } + bool IsClipEmpty { get; } + RectangleF VisibleClipBounds { get; } + bool IsVisibleClipEmpty { get; } + */ + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/JuniorRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/JuniorRobot.cs new file mode 100644 index 0000000..0ea5d59 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/JuniorRobot.cs @@ -0,0 +1,1324 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using System.IO; +using Robocode.Exception; +using Robocode.RobotInterfaces; +using Robocode.RobotInterfaces.Peer; +using Robocode.Util; + +namespace Robocode +{ + /// + /// This is the simplest robot type, which is simpler than the and + /// classes. The JuniorRobot has a simplified model, in + /// purpose of teaching programming skills to inexperienced in programming + /// students. The simplified robot model will keep player from overwhelming of + /// Robocode's rules, programming syntax and programming concept. + ///

+ /// Instead of using getters and setters, public fields are provided for + /// receiving information like the last scanned robot, the coordinate of the + /// robot etc. + ///

+ /// All methods on this class are blocking calls, i.e. they do not return before + /// their action has been completed and will at least take one turn to execute. + /// However, setting colors is executed immediately and does not cost a turn to + /// perform. + /// + /// + /// + /// + ///

+ public abstract class JuniorRobot : IJuniorRobot + { + internal IBasicRobotPeer peer; + internal TextWriter _output; + + /// + /// The color black (0x000000) + /// + public const int BLACK=0; + + /// + /// The color white (0xFFFFFF) + /// + public const int WHITE = 0xFFFFFF; + + /// + /// The color red (0xFF0000) + /// + public const int RED = 0xFF0000; + + /// + /// The color orange (0xFFA500) + /// + public const int ORANGE = 0xFFA500; + + /// + /// The color yellow (0xFFFF00) + /// + public const int YELLOW = 0xFFFF00; + + /// + /// The color green (0x008000) + /// + public const int GREEN = 0x008000; + + /// + /// The color blue (0x0000FF) + /// + public const int BLUE = 0x0000FF; + + /// + /// The color purple (0x800080) + /// + public const int PURPLE = 0x800080; + + /// + /// The color brown (0x8B4513) + /// + public const int BROWN = 0x8B4513; + + /// + /// The color gray (0x808080) + /// + public const int GRAY = 0x808080; + + /// + /// Contains the width of the battlefield. + /// + /// + /// + private int fieldWidth; + + /// + /// Contains the height of the battlefield. + /// + /// + /// + private int fieldHeight; + + /// + /// Current number of other robots on the battle field. + /// + private int others; + + /// + /// Current energy of this robot, where 100 means full energy and 0 means no energy (dead). + /// + private int energy; + + /// + /// Current horizontal location of this robot (in pixels). + /// + /// + /// + private int robotX; + + /// + /// Current vertical location of this robot (in pixels). + /// + /// + /// + private int robotY; + + /// + /// Current heading angle of this robot (in degrees). + /// + /// + /// + /// + /// + /// + /// + /// + /// + private int heading; + + /// + /// Current gun heading angle of this robot (in degrees). + /// + /// + /// + /// + /// + /// + /// + private int gunHeading; + + /// + /// Current gun heading angle of this robot compared to its body (in degrees). + /// + /// + /// + /// + /// + /// + /// + private int gunBearing; + + /// + /// Flag specifying if the gun is ready to Fire, i.e. gun heat <= 0. + /// true means that the gun is able to Fire; false + /// means that the gun cannot Fire yet as it still needs to cool down. + /// + /// + /// + /// + private bool gunReady; + + /// + /// Current distance to the scanned nearest other robot (in pixels). + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + private int scannedDistance = -1; + + /// + /// Current angle to the scanned nearest other robot (in degrees). + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + private int scannedAngle = -1; + + /// + /// Current angle to the scanned nearest other robot (in degrees) compared to + /// the body of this robot. + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + private int scannedBearing = -1; + + /// + /// Current velocity of the scanned nearest other robot. + /// If there is no robot in the radar's sight, this field will be -99. + /// Note that a positive value means that the robot moves forward, a negative + /// value means that the robot moved backward, and 0 means that the robot is + /// not moving at all. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + private int scannedVelocity = -99; + + /// + /// Current heading of the scanned nearest other robot (in degrees). + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + private int scannedHeading = -1; + + /// + /// Current energy of scanned nearest other robot. + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + private int scannedEnergy = -1; + + /// + /// Latest angle from where this robot was hit by a bullet (in degrees). + /// If the robot has never been hit, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + private int hitByBulletAngle = -1; + + /// + /// Latest angle from where this robot was hit by a bullet (in degrees) + /// compared to the body of this robot. + /// If the robot has never been hit, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + private int hitByBulletBearing = -1; + + /// + /// Latest angle where this robot has hit another robot (in degrees). + /// If this robot has never hit another robot, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + private int hitRobotAngle = -1; + + /// + /// Latest angle where this robot has hit another robot (in degrees) + /// compared to the body of this robot. + /// If this robot has never hit another robot, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + private int hitRobotBearing = -1; + + /// + /// Latest angle where this robot has hit a wall (in degrees). + /// If this robot has never hit a wall, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + private int hitWallAngle = -1; + + /// + /// Latest angle where this robot has hit a wall (in degrees) + /// compared to the body of this robot. + /// If this robot has never hit a wall, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + private int hitWallBearing = -1; + + /// + /// The robot event handler for this robot. + /// + private InnerEventHandler innerEventHandler; + + + /// + /// The Out stream your robot should use to print. + ///

+ /// You can view the print-outs by clicking the button for your robot in the + /// right side of the battle window. + ///

+ /// + /// + /// // Print Out a line each time my robot hits another robot + /// public void OnHitRobot(HitRobotEvent e) + /// { + /// Out.WriteLine("I hit a robot! My energy: " + Energy + " his energy: " + e.Energy); + /// } + /// + /// + ///

+ public TextWriter Out + { + get { return _output; } + } + + /// + /// Contains the width of the battlefield. + /// + /// + /// + public int FieldWidth + { + get { return fieldWidth; } + } + + /// + /// Contains the height of the battlefield. + /// + /// + /// + public int FieldHeight + { + get { return fieldHeight; } + } + + /// + /// Current number of other robots on the battle field. + /// + public int Others + { + get { return others; } + } + + /// + /// Current energy of this robot, where 100 means full energy and 0 means no energy (dead). + /// + public int Energy + { + get { return energy; } + } + + /// + /// Current horizontal location of this robot (in pixels). + /// + /// + /// + public int RobotX + { + get { return robotX; } + } + + /// + /// Current vertical location of this robot (in pixels). + /// + /// + /// + public int RobotY + { + get { return robotY; } + } + + /// + /// Current heading angle of this robot (in degrees). + /// + /// + /// + /// + /// + /// + /// + /// + /// + public int Heading + { + get { return heading; } + } + + /// + /// Current gun heading angle of this robot (in degrees). + /// + /// + /// + /// + /// + /// + /// + public int GunHeading + { + get { return gunHeading; } + } + + /// + /// Current gun heading angle of this robot compared to its body (in degrees). + /// + /// + /// + /// + /// + /// + /// + public int GunBearing + { + get { return gunBearing; } + } + + /// + /// Flag specifying if the gun is ready to Fire, i.e. gun heat <= 0. + /// true means that the gun is able to Fire; false + /// means that the gun cannot Fire yet as it still needs to cool down. + /// + /// + /// + /// + public bool IsGunReady + { + get { return gunReady; } + } + + /// + /// Current distance to the scanned nearest other robot (in pixels). + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + public int ScannedDistance + { + get { return scannedDistance; } + } + + /// + /// Current angle to the scanned nearest other robot (in degrees). + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + public int ScannedAngle + { + get { return scannedAngle; } + } + + /// + /// Current angle to the scanned nearest other robot (in degrees) compared to + /// the body of this robot. + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + public int ScannedBearing + { + get { return scannedBearing; } + } + + /// + /// Current velocity of the scanned nearest other robot. + /// If there is no robot in the radar's sight, this field will be -99. + /// Note that a positive value means that the robot moves forward, a negative + /// value means that the robot moved backward, and 0 means that the robot is + /// not moving at all. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + public int ScannedVelocity + { + get { return scannedVelocity; } + } + + /// + /// Current heading of the scanned nearest other robot (in degrees). + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + /// + public int ScannedHeading + { + get { return scannedHeading; } + } + + /// + /// Current energy of scanned nearest other robot. + /// If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + /// + /// + /// + public int ScannedEnergy + { + get { return scannedEnergy; } + } + + /// + /// Latest angle from where this robot was hit by a bullet (in degrees). + /// If the robot has never been hit, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + public int HitByBulletAngle + { + get { return hitByBulletAngle; } + } + + /// + /// Latest angle from where this robot was hit by a bullet (in degrees) + /// compared to the body of this robot. + /// If the robot has never been hit, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + public int HitByBulletBearing + { + get { return hitByBulletBearing; } + } + + /// + /// Latest angle where this robot has hit another robot (in degrees). + /// If this robot has never hit another robot, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + public int HitRobotAngle + { + get { return hitRobotAngle; } + } + + /// + /// Latest angle where this robot has hit another robot (in degrees) + /// compared to the body of this robot. + /// If this robot has never hit another robot, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + public int HitRobotBearing + { + get { return hitRobotBearing; } + } + + /// + /// Latest angle where this robot has hit a wall (in degrees). + /// If this robot has never hit a wall, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + public int HitWallAngle + { + get { return hitWallAngle; } + } + + /// + /// Latest angle where this robot has hit a wall (in degrees) + /// compared to the body of this robot. + /// If this robot has never hit a wall, this field will be less than 0, i.e. -1. + /// This field will not be updated while event is active. + /// + /// + /// + /// + public int HitWallBearing + { + get { return hitWallBearing; } + } + + /// + void IBasicRobot.SetOut(TextWriter outpt) + { + _output = outpt; + } + + /// + void IBasicRobot.SetPeer(IBasicRobotPeer per) + { + peer = per; + } + + /// + /// Throws a RobotException. This method should be called when the robot's peer + /// is uninitialized. + /// + internal static void UninitializedException() + { + throw new RobotException( + "You cannot call the methods before your Run() method is called, or you are using a Robot object that the game doesn't know about."); + } + + /// + IRunnable IBasicRobot.GetRobotRunnable() + { + return getEventHandler(); + } + + /// + IBasicEvents IBasicRobot.GetBasicEventListener() + { + return getEventHandler(); + } + + + /// + /// Moves this robot forward by pixels. + /// + /// + /// + /// + /// The amount of pixels to move forward + public void Ahead(int distance) + { + if (peer != null) + { + peer.Move(distance); + } + else + { + UninitializedException(); + } + } + + /// + /// Moves this robot backward by pixels. + /// + /// + /// + /// + /// + /// the amount of pixels to move backward + public void Back(int distance) + { + Ahead(-distance); + } + + /// + /// Turns the gun to the specified angle (in degrees) relative to body of this robot. + /// The gun will turn to the side with the shortest delta angle to the specified angle. + /// + /// + /// + /// + /// + /// + /// the angle to turn the gun to relative to the body of this robot + public void BearGunTo(int angle) + { + if (peer != null) + { + peer.TurnGun( + Utils.NormalRelativeAngle(peer.GetBodyHeading() + Utils.ToRadians(angle) - peer.GetGunHeading())); + } + else + { + UninitializedException(); + } + } + + /// + /// Skips a turn. + /// + /// + public void DoNothing() + { + if (peer != null) + { + peer.Execute(); + } + else + { + UninitializedException(); + } + } + + /// + /// Skips the specified number of turns. + /// + /// + /// The number of turns to skip + public void DoNothing(int turns) + { + if (turns <= 0) + { + return; + } + if (peer != null) + { + for (int i = 0; i < turns; i++) + { + peer.Execute(); + } + } + else + { + UninitializedException(); + } + } + + /// + /// Fires a bullet with the default power of 1. + /// If the gun heat is more than 0 and hence cannot Fire, this method will + /// suspend until the gun is ready to Fire, and then Fire a bullet. + /// + /// + /// + public void Fire() + { + Fire(1); + } + + /// + /// Fires a bullet with the specified bullet power, which is between 0.1 and 3 + /// where 3 is the maximum bullet power. + /// If the gun heat is more than 0 and hence cannot Fire, this method will + /// suspend until the gun is ready to Fire, and then Fire a bullet. + /// + /// + /// Between 0.1 and 3 + public void Fire(double power) + { + if (peer != null) + { + getEventHandler().juniorFirePower = power; + peer.Execute(); + } + else + { + UninitializedException(); + } + } + + /// + /// This event method is called from the game when this robot has been hit + /// by another robot's bullet. When this event occurs the + /// and fields values + /// are automatically updated. + /// + /// + /// + /// + public virtual void OnHitByBullet() + { + } + + /// + /// This event method is called from the game when a bullet from this robot + /// has hit another robot. When this event occurs the + /// and fields values are automatically updated. + /// + /// + /// + /// + public virtual void OnHitRobot() + { + } + + /// + /// This event method is called from the game when this robot has hit a wall. + /// When this event occurs the and + /// fields values are automatically updated. + /// + /// + /// + /// + public virtual void OnHitWall() + { + } + + /// + /// This event method is called from the game when the radar detects another + /// robot. When this event occurs the , + /// , , and + /// field values are automatically updated. + /// + /// + /// + /// + /// + public virtual void OnScannedRobot() + { + } + + /// + /// The main method in every robot. You must override this to set up your + /// robot's basic behavior. + ///

+ /// + /// + /// // A basic robot that moves around in a square + /// public void Run() + /// { + /// Ahead(100); + /// TurnRight(90); + /// } + /// + /// + /// This method is automatically re-called when it has returned. + ///

+ public virtual void Run() + { + } + + /// + /// Sets the colors of the robot. The color values are RGB values. + /// You can use the colors that are already defined for this class. + /// + /// + /// The RGB color value for the body + /// The RGB color value for the gun + /// The RGB color value for the radar + public void SetColors(int bodyColor, int gunColor, int radarColor) + { + if (peer != null) + { + peer.SetBodyColor(Color.FromArgb(bodyColor)); + peer.SetGunColor(Color.FromArgb(gunColor)); + peer.SetRadarColor(Color.FromArgb(radarColor)); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the colors of the robot. The color values are RGB values. + /// You can use the colors that are already defined for this class. + /// + /// + /// The RGB color value for the body + /// The RGB color value for the gun + /// The RGB color value for the radar + /// The RGB color value for the bullets + /// The RGB color value for the scan arc + public void SetColors(int bodyColor, int gunColor, int radarColor, int bulletColor, int scanArcColor) + { + if (peer != null) + { + peer.SetBodyColor(Color.FromArgb(bodyColor)); + peer.SetGunColor(Color.FromArgb(gunColor)); + peer.SetRadarColor(Color.FromArgb(radarColor)); + peer.SetBulletColor(Color.FromArgb(bulletColor)); + peer.SetScanColor(Color.FromArgb(scanArcColor)); + } + else + { + UninitializedException(); + } + } + + /// + /// Moves this robot forward by pixels and turns this robot left by degrees + /// at the same time. The robot will move in a curve that follows a perfect + /// circle, and the moving and turning will end at the same time. + ///

+ /// Note that the max. velocity and max. turn rate is automatically adjusted, + /// which means that the robot will move slower the sharper the turn is + /// compared to the distance. + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The amount of pixels to move forward + /// The amount of degrees to turn to the left + public void TurnAheadLeft(int distance, int degrees) + { + TurnAheadRight(distance, -degrees); + } + + /// + /// Moves this robot forward by pixels and turns this robot right by degrees + /// at the same time. The robot will move in a curve that follows a perfect + /// circle, and the moving and turning will end at the same time. + ///

+ /// Note that the max. velocity and max. turn rate is automatically adjusted, + /// which means that the robot will move slower the sharper the turn is + /// compared to the distance. + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The amount of pixels to move forward + /// The amount of degrees to turn to the right + public void TurnAheadRight(int distance, int degrees) + { + if (peer != null) + { + ((IJuniorRobotPeer) peer).TurnAndMove(distance, Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Moves this robot backward by pixels and turns this robot left by degrees + /// at the same time. The robot will move in a curve that follows a perfect + /// circle, and the moving and turning will end at the same time. + ///

+ /// Note that the max. velocity and max. turn rate is automatically adjusted, + /// which means that the robot will move slower the sharper the turn is + /// compared to the distance. + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The amount of pixels to move backward + /// The amount of degrees to turn to the left + public void TurnBackLeft(int distance, int degrees) + { + TurnAheadRight(-distance, degrees); + } + + /// + /// Moves this robot backward by pixels and turns this robot right by degrees + /// at the same time. The robot will move in a curve that follows a perfect + /// circle, and the moving and turning will end at the same time. + ///

+ /// Note that the max. velocity and max. turn rate is automatically adjusted, + /// which means that the robot will move slower the sharper the turn is + /// compared to the distance. + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The amount of pixels to move backward + /// The amount of degrees to turn to the right + public void TurnBackRight(int distance, int degrees) + { + TurnAheadRight(-distance, -degrees); + } + + /// + /// Turns the gun left by degrees. + /// + /// + /// + /// + /// + /// + /// The amount of degrees to turn the gun to the left + public void TurnGunLeft(int degrees) + { + TurnGunRight(-degrees); + } + + /// + /// Turns the gun right by degrees. + /// + /// + /// + /// + /// + /// + /// The amount of degrees to turn the gun to the right + public void TurnGunRight(int degrees) + { + if (peer != null) + { + peer.TurnGun(Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Turns the gun to the specified angle (in degrees). + /// The gun will turn to the side with the shortest delta angle to the + /// specified angle. + /// + /// + /// + /// + /// + /// + /// The angle to turn the gun to + public void TurnGunTo(int angle) + { + if (peer != null) + { + peer.TurnGun(Utils.NormalRelativeAngle(Utils.ToRadians(angle) - peer.GetGunHeading())); + } + else + { + UninitializedException(); + } + } + + /// + /// Turns this robot left by degrees. + /// + /// + /// + /// + /// + /// + /// + /// + /// The amount of degrees to turn to the left + public void TurnLeft(int degrees) + { + TurnRight(-degrees); + } + + /// + /// Turns this robot right by degrees. + /// + /// + /// + /// + /// + /// + /// + /// + /// The amount of degrees to turn to the right + public void TurnRight(int degrees) + { + if (peer != null) + { + peer.TurnBody(Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Turns this robot to the specified angle (in degrees). + /// The robot will turn to the side with the shortest delta angle to the + /// specified angle. + /// + /// + /// + /// + /// + /// + /// + /// + /// The angle to turn this robot to + public void TurnTo(int angle) + { + if (peer != null) + { + peer.TurnBody(Utils.NormalRelativeAngle(Utils.ToRadians(angle) - peer.GetBodyHeading())); + } + else + { + UninitializedException(); + } + } + + /// + /// Returns the event handler of this robot. + /// + private InnerEventHandler getEventHandler() + { + if (innerEventHandler == null) + { + innerEventHandler = new InnerEventHandler(this); + } + return innerEventHandler; + } + + /// + /// The JuniorRobot event handler, which extends the basic robot events, + /// IBasicEvents, and IRunnable. + /// + private sealed class InnerEventHandler : IBasicEvents, IRunnable + { + public InnerEventHandler(JuniorRobot robot) + { + this.robot = robot; + } + + private readonly JuniorRobot robot; + internal double juniorFirePower; + private long currentTurn; + + public void OnBulletHit(BulletHitEvent evnt) + { + } + + public void OnBulletHitBullet(BulletHitBulletEvent evnt) + { + } + + public void OnBulletMissed(BulletMissedEvent evnt) + { + } + + public void OnDeath(DeathEvent evnt) + { + } + + public void OnHitByBullet(HitByBulletEvent evnt) + { + double angle = robot.peer.GetBodyHeading() + evnt.BearingRadians; + + robot.hitByBulletAngle = (int) (Utils.ToDegrees(Utils.NormalAbsoluteAngle(angle)) + 0.5); + robot.hitByBulletBearing = (int) (evnt.Bearing + 0.5); + robot.OnHitByBullet(); + } + + public void OnHitRobot(HitRobotEvent evnt) + { + double angle = robot.peer.GetBodyHeading() + evnt.BearingRadians; + + robot.hitRobotAngle = (int) (Utils.ToDegrees(Utils.NormalAbsoluteAngle(angle)) + 0.5); + robot.hitRobotBearing = (int) (evnt.Bearing + 0.5); + robot.OnHitRobot(); + } + + public void OnHitWall(HitWallEvent evnt) + { + double angle = robot.peer.GetBodyHeading() + evnt.BearingRadians; + + robot.hitWallAngle = (int) (Utils.ToDegrees(Utils.NormalAbsoluteAngle(angle)) + 0.5); + robot.hitWallBearing = (int) (evnt.Bearing + 0.5); + robot.OnHitWall(); + } + + public void OnRobotDeath(RobotDeathEvent evnt) + { + robot.others = robot.peer.GetOthers(); + } + + public void OnScannedRobot(ScannedRobotEvent evnt) + { + robot.scannedDistance = (int) (evnt.Distance + 0.5); + robot.scannedEnergy = Math.Max(1, (int) (evnt.Energy + 0.5)); + robot.scannedAngle = (int) (Utils.ToDegrees( + Utils.NormalAbsoluteAngle(robot.peer.GetBodyHeading() + + evnt.BearingRadians)) + + 0.5); + robot.scannedBearing = (int) (evnt.Bearing + 0.5); + robot.scannedHeading = (int) (evnt.Heading + 0.5); + robot.scannedVelocity = (int) (evnt.Velocity + 0.5); + + robot.OnScannedRobot(); + } + + public void OnStatus(StatusEvent e) + { + RobotStatus s = e.Status; + + robot.others = robot.peer.GetOthers(); + robot.energy = Math.Max(1, (int) (s.Energy + 0.5)); + robot.robotX = (int) (s.X + 0.5); + robot.robotY = (int) (s.Y + 0.5); + robot.heading = (int) (Utils.ToDegrees(s.Heading) + 0.5); + robot.gunHeading = (int) (Utils.ToDegrees(s.GunHeading) + 0.5); + robot.gunBearing = + (int) (Utils.ToDegrees(Utils.NormalRelativeAngle(s.GunHeading - s.Heading)) + 0.5); + robot.gunReady = (s.GunHeat <= 0); + + currentTurn = e.Time; + + // Auto Fire + if (juniorFirePower > 0 && robot.gunReady && (robot.peer.GetGunTurnRemaining() == 0)) + { + if (robot.peer.SetFire(juniorFirePower) != null) + { + robot.gunReady = false; + juniorFirePower = 0; + } + } + + // Reset event data + robot.scannedDistance = -1; + robot.scannedAngle = -1; + robot.scannedBearing = -1; + robot.scannedVelocity = -99; + robot.scannedHeading = -1; + robot.scannedEnergy = -1; + robot.hitByBulletAngle = -1; + robot.hitByBulletBearing = -1; + robot.hitRobotAngle = -1; + robot.hitRobotBearing = -1; + robot.hitWallAngle = -1; + robot.hitWallBearing = -1; + } + + public void OnWin(WinEvent evnt) + { + } + + // ReSharper disable FunctionNeverReturns + public void Run() + { + robot.fieldWidth = (int) (robot.peer.GetBattleFieldWidth() + 0.5); + robot.fieldHeight = (int) (robot.peer.GetBattleFieldHeight() + 0.5); + + // noinspection InfiniteLoopStatement + while (true) + { + long lastTurn = currentTurn; // Used for the Rescan check + + robot.Run(); // Run the code in the JuniorRobot + + // Make sure that we Rescan if the robot did not execute anything this turn. + // When the robot executes the currentTurn will automatically be increased by 1, + // So when the turn stays the same, the robot did not take any action this turn. + if (lastTurn == currentTurn) + { + robot.peer.Rescan(); // Spend a turn on rescanning + } + } + } + } + // ReSharper restore FunctionNeverReturns + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyEvent.cs new file mode 100644 index 0000000..1bb3bdd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyEvent.cs @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; + +namespace Robocode +{ + /// + /// Super class of all events that originates from the keyboard. + /// + [Serializable] + public abstract class KeyEvent : Event + { + private readonly char keyChar; + private readonly int keyCode; + private readonly int keyLocation; + private readonly int id; + private readonly int modifiersEx; + private readonly long when; + + /// + /// Called by game + /// + protected KeyEvent(char keyChar, int keyCode, int keyLocation, int id, int modifiersEx, long when) + { + this.keyChar = keyChar; + this.keyCode = keyCode; + this.keyLocation = keyLocation; + this.id = id; + this.modifiersEx = modifiersEx; + this.when = when; + } + + /// + /// Char of they key pressed + /// + public char KeyChar + { + get { return keyChar; } + } + + /// + /// + /// + public int KeyCode + { + get { return keyCode; } + } + + internal int KeyLocation + { + get { return keyLocation; } + } + + internal int ID + { + get { return id; } + } + + internal int ModifiersEx + { + get { return modifiersEx; } + } + + /// + /// Age of the event + /// + public long When + { + get { return when; } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyPressedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyPressedEvent.cs new file mode 100644 index 0000000..0ec1caa --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyPressedEvent.cs @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A KeyPressedEvent is sent to + /// when a key has been pressed on the keyboard. + /// + /// + /// + [Serializable] + public sealed class KeyPressedEvent : KeyEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new KeyPressedEvent. + /// + public KeyPressedEvent(char keyChar, int keyCode, int keyLocation, int id, int modifiersEx, long when) + : base(keyChar, keyCode, keyLocation, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnKeyPressed(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.KeyPressedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_CHAR + RbSerializerN.SIZEOF_INT + + RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG + RbSerializerN.SIZEOF_INT + + RbSerializerN.SIZEOF_INT; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (KeyPressedEvent) objec; + serializer.serialize(buffer, obj.KeyChar); + serializer.serialize(buffer, obj.KeyCode); + serializer.serialize(buffer, obj.KeyLocation); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + char keyChar = buffer.getChar(); + int keyCode = buffer.getInt(); + int keyLocation = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + return new KeyPressedEvent(keyChar, keyCode, keyLocation, id, modifiersEx, when); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyReleasedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyReleasedEvent.cs new file mode 100644 index 0000000..30add3e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyReleasedEvent.cs @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A KeyReleasedEvent is sent to + /// when a key has been released on the keyboard. + /// + /// + /// + [Serializable] + public sealed class KeyReleasedEvent : KeyEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new KeyReleasedEvent. + /// + public KeyReleasedEvent(char keyChar, int keyCode, int keyLocation, int id, int modifiersEx, long when) + : base(keyChar, keyCode, keyLocation, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnKeyReleased(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.KeyReleasedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_CHAR + RbSerializerN.SIZEOF_INT + + RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG + RbSerializerN.SIZEOF_INT + + RbSerializerN.SIZEOF_INT; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (KeyReleasedEvent) objec; + + serializer.serialize(buffer, obj.KeyChar); + serializer.serialize(buffer, obj.KeyCode); + serializer.serialize(buffer, obj.KeyLocation); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + char keyChar = buffer.getChar(); + int keyCode = buffer.getInt(); + int keyLocation = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new KeyReleasedEvent(keyChar, keyCode, keyLocation, id, modifiersEx, when); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyTypedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyTypedEvent.cs new file mode 100644 index 0000000..b59b4fa --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/KeyTypedEvent.cs @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A KeyTypedEvent is sent to + /// when a key has been typed (pressed and released) on the keyboard. + /// + /// + /// + [Serializable] + public sealed class KeyTypedEvent : KeyEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new KeyTypedEvent. + /// + public KeyTypedEvent(char keyChar, int keyCode, int keyLocation, int id, int modifiersEx, long when) + : base(keyChar, keyCode, keyLocation, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnKeyTyped(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.KeyTypedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_CHAR + RbSerializerN.SIZEOF_INT + + RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG + RbSerializerN.SIZEOF_INT + + RbSerializerN.SIZEOF_INT; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (KeyTypedEvent) objec; + + serializer.serialize(buffer, obj.KeyChar); + serializer.serialize(buffer, obj.KeyCode); + serializer.serialize(buffer, obj.KeyLocation); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + char keyChar = buffer.getChar(); + int keyCode = buffer.getInt(); + int keyLocation = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new KeyTypedEvent(keyChar, keyCode, keyLocation, id, modifiersEx, when); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Keys.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Keys.cs new file mode 100644 index 0000000..fd834ca --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Keys.cs @@ -0,0 +1,292 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// This class is based on the source code from Sun's Java 1.5.0 API for java.awt.event.KeyEvent, but +// rewritten for C# and .NET with the purpose to bridge the .NET and Java internals of Robocode. + +namespace Robocode +{ +#pragma warning disable 1591 + /// + public static class Keys + { + public const int KEY_FIRST = 400; + + public const int KEY_LAST = 402; + + public const int KEY_TYPED = KEY_FIRST; + + public const int KEY_PRESSED = 1 + KEY_FIRST; + + public const int KEY_RELEASED = 2 + KEY_FIRST; + + public const int VK_ENTER = 0x0A; + public const int VK_BACK_SPACE = 0x20; + public const int VK_TAB = 0x08; + public const int VK_CANCEL = 0x03; + public const int VK_CLEAR = 0x0C; + public const int VK_SHIFT = 0x10; + public const int VK_CONTROL = 0x11; + public const int VK_ALT = 0x12; + public const int VK_PAUSE = 0x13; + public const int VK_CAPS_LOCK = 0x14; + public const int VK_ESCAPE = 0x1B; + public const int VK_SPACE = 0x20; + public const int VK_PAGE_UP = 0x21; + public const int VK_PAGE_DOWN = 0x22; + public const int VK_END = 0x23; + public const int VK_HOME = 0x24; + + public const int VK_LEFT = 0x25; + + public const int VK_UP = 0x26; + + public const int VK_RIGHT = 0x27; + + public const int VK_DOWN = 0x28; + + public const int VK_COMMA = 0x2C; + + public const int VK_MINUS = 0x2D; + + public const int VK_PERIOD = 0x2E; + + public const int VK_SLASH = 0x2F; + + public const int VK_0 = 0x30; + public const int VK_1 = 0x31; + public const int VK_2 = 0x32; + public const int VK_3 = 0x33; + public const int VK_4 = 0x34; + public const int VK_5 = 0x35; + public const int VK_6 = 0x36; + public const int VK_7 = 0x37; + public const int VK_8 = 0x38; + public const int VK_9 = 0x39; + + public const int VK_SEMICOLON = 0x3B; + + public const int VK_EQUALS = 0x3D; + + public const int VK_A = 0x41; + public const int VK_B = 0x42; + public const int VK_C = 0x43; + public const int VK_D = 0x44; + public const int VK_E = 0x45; + public const int VK_F = 0x46; + public const int VK_G = 0x47; + public const int VK_H = 0x48; + public const int VK_I = 0x49; + public const int VK_J = 0x4A; + public const int VK_K = 0x4B; + public const int VK_L = 0x4C; + public const int VK_M = 0x4D; + public const int VK_N = 0x4E; + public const int VK_O = 0x4F; + public const int VK_P = 0x50; + public const int VK_Q = 0x51; + public const int VK_R = 0x52; + public const int VK_S = 0x53; + public const int VK_T = 0x54; + public const int VK_U = 0x55; + public const int VK_V = 0x56; + public const int VK_W = 0x57; + public const int VK_X = 0x58; + public const int VK_Y = 0x59; + public const int VK_Z = 0x5A; + + public const int VK_OPEN_BRACKET = 0x5B; + + public const int VK_BACK_SLASH = 0x5C; + + public const int VK_CLOSE_BRACKET = 0x5D; + + public const int VK_NUMPAD0 = 0x60; + public const int VK_NUMPAD1 = 0x61; + public const int VK_NUMPAD2 = 0x62; + public const int VK_NUMPAD3 = 0x63; + public const int VK_NUMPAD4 = 0x64; + public const int VK_NUMPAD5 = 0x65; + public const int VK_NUMPAD6 = 0x66; + public const int VK_NUMPAD7 = 0x67; + public const int VK_NUMPAD8 = 0x68; + public const int VK_NUMPAD9 = 0x69; + public const int VK_MULTIPLY = 0x6A; + public const int VK_ADD = 0x6B; + + public const int VK_SEPARATER = 0x6C; + + public const int VK_SEPARATOR = VK_SEPARATER; + + public const int VK_SUBTRACT = 0x6D; + public const int VK_DECIMAL = 0x6E; + public const int VK_DIVIDE = 0x6F; + public const int VK_DELETE = 0x7F; + public const int VK_NUM_LOCK = 0x90; + public const int VK_SCROLL_LOCK = 0x91; + + public const int VK_F1 = 0x70; + + public const int VK_F2 = 0x71; + + public const int VK_F3 = 0x72; + + public const int VK_F4 = 0x73; + + public const int VK_F5 = 0x74; + + public const int VK_F6 = 0x75; + + public const int VK_F7 = 0x76; + + public const int VK_F8 = 0x77; + + public const int VK_F9 = 0x78; + + public const int VK_F10 = 0x79; + + public const int VK_F11 = 0x7A; + + public const int VK_F12 = 0x7B; + + public const int VK_F13 = 0xF000; + + public const int VK_F14 = 0xF001; + + public const int VK_F15 = 0xF002; + + public const int VK_F16 = 0xF003; + + public const int VK_F17 = 0xF004; + + public const int VK_F18 = 0xF005; + + public const int VK_F19 = 0xF006; + + public const int VK_F20 = 0xF007; + + public const int VK_F21 = 0xF008; + + public const int VK_F22 = 0xF009; + + public const int VK_F23 = 0xF00A; + + public const int VK_F24 = 0xF00B; + + public const int VK_PRINTSCREEN = 0x9A; + public const int VK_INSERT = 0x9B; + public const int VK_HELP = 0x9C; + public const int VK_META = 0x9D; + + public const int VK_BACK_QUOTE = 0xC0; + public const int VK_QUOTE = 0xDE; + + public const int VK_KP_UP = 0xE0; + + public const int VK_KP_DOWN = 0xE1; + + public const int VK_KP_LEFT = 0xE2; + + public const int VK_KP_RIGHT = 0xE3; + + public const int VK_DEAD_GRAVE = 0x80; + public const int VK_DEAD_ACUTE = 0x81; + public const int VK_DEAD_CIRCUMFLEX = 0x82; + public const int VK_DEAD_TILDE = 0x83; + public const int VK_DEAD_MACRON = 0x84; + public const int VK_DEAD_BREVE = 0x85; + public const int VK_DEAD_ABOVEDOT = 0x86; + public const int VK_DEAD_DIAERESIS = 0x87; + public const int VK_DEAD_ABOVERING = 0x88; + public const int VK_DEAD_DOUBLEACUTE = 0x89; + public const int VK_DEAD_CARON = 0x8a; + public const int VK_DEAD_CEDILLA = 0x8b; + public const int VK_DEAD_OGONEK = 0x8c; + public const int VK_DEAD_IOTA = 0x8d; + public const int VK_DEAD_VOICED_SOUND = 0x8e; + public const int VK_DEAD_SEMIVOICED_SOUND = 0x8f; + + public const int VK_AMPERSAND = 0x96; + public const int VK_ASTERISK = 0x97; + public const int VK_QUOTEDBL = 0x98; + public const int VK_LESS = 0x99; + public const int VK_GREATER = 0xa0; + public const int VK_BRACELEFT = 0xa1; + public const int VK_BRACERIGHT = 0xa2; + + public const int VK_AT = 0x0200; + public const int VK_COLON = 0x0201; + public const int VK_CIRCUMFLEX = 0x0202; + public const int VK_DOLLAR = 0x0203; + public const int VK_EURO_SIGN = 0x0204; + + public const int VK_EXCLAMATION_MARK = 0x0205; + public const int VK_INVERTED_EXCLAMATION_MARK = 0x0206; + public const int VK_LEFT_PARENTHESIS = 0x0207; + public const int VK_NUMBER_SIGN = 0x0208; + public const int VK_PLUS = 0x0209; + public const int VK_RIGHT_PARENTHESIS = 0x020A; + public const int VK_UNDERSCORE = 0x020B; + public const int VK_WINDOWS = 0x020C; + public const int VK_CONTEXT_MENU = 0x020D; + public const int VK_const = 0x0018; + public const int VK_CONVERT = 0x001C; + public const int VK_NONCONVERT = 0x001D; + public const int VK_ACCEPT = 0x001E; + public const int VK_MODECHANGE = 0x001F; + public const int VK_KANA = 0x0015; + public const int VK_KANJI = 0x0019; + public const int VK_ALPHANUMERIC = 0x00F0; + public const int VK_KATAKANA = 0x00F1; + public const int VK_HIRAGANA = 0x00F2; + public const int VK_FULL_WIDTH = 0x00F3; + public const int VK_HALF_WIDTH = 0x00F4; + public const int VK_ROMAN_CHARACTERS = 0x00F5; + public const int VK_ALL_CANDIDATES = 0x0100; + public const int VK_PREVIOUS_CANDIDATE = 0x0101; + public const int VK_CODE_INPUT = 0x0102; + public const int VK_JAPANESE_KATAKANA = 0x0103; + public const int VK_JAPANESE_HIRAGANA = 0x0104; + public const int VK_JAPANESE_ROMAN = 0x0105; + public const int VK_KANA_LOCK = 0x0106; + public const int VK_INPUT_METHOD_ON_OFF = 0x0107; + public const int VK_CUT = 0xFFD1; + public const int VK_COPY = 0xFFCD; + public const int VK_PASTE = 0xFFCF; + public const int VK_UNDO = 0xFFCB; + public const int VK_AGAIN = 0xFFC9; + public const int VK_FIND = 0xFFD0; + public const int VK_PROPS = 0xFFCA; + public const int VK_STOP = 0xFFC8; + public const int VK_COMPOSE = 0xFF20; + public const int VK_ALT_GRAPH = 0xFF7E; + public const int VK_BEGIN = 0xFF58; + public const int VK_UNDEFINED = 0x0; + public const int KEY_LOCATION_UNKNOWN = 0; + public const int KEY_LOCATION_STANDARD = 1; + public const int KEY_LOCATION_LEFT = 2; + public const int KEY_LOCATION_RIGHT = 3; + public const int KEY_LOCATION_NUMPAD = 4; + public static readonly char CHAR_UNDEFINED = (char) 0xFFFF; + public const int MOUSE_FIRST = 500; + public const int MOUSE_LAST = 507; + public const int MOUSE_CLICKED = MOUSE_FIRST; + public const int MOUSE_PRESSED = 1 + MOUSE_FIRST; //Event.MOUSE_DOWN + public const int MOUSE_RELEASED = 2 + MOUSE_FIRST; //Event.MOUSE_UP + public const int MOUSE_MOVED = 3 + MOUSE_FIRST; //Event.MOUSE_MOVE + public const int MOUSE_ENTERED = 4 + MOUSE_FIRST; //Event.MOUSE_ENTER + public const int MOUSE_EXITED = 5 + MOUSE_FIRST; //Event.MOUSE_EXIT + public const int MOUSE_DRAGGED = 6 + MOUSE_FIRST; //Event.MOUSE_DRAG + public const int MOUSE_WHEEL = 7 + MOUSE_FIRST; + public const int NOBUTTON = 0; + public const int BUTTON1 = 1; + public const int BUTTON2 = 2; + public const int BUTTON3 = 3; + + } +#pragma warning restore 1591 +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MessageEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MessageEvent.cs new file mode 100644 index 0000000..8e01625 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MessageEvent.cs @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.peer; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A MessageEvent is sent to + /// when a teammate sends a message to your robot. + /// You can use the information contained in this event to determine what to do. + /// + [Serializable] + public sealed class MessageEvent : Event + { + private const int DEFAULT_PRIORITY = 75; + + private readonly string sender; + [NonSerialized] + private readonly object message; + + /// + /// Called by the game to create a new MessageEvent. + /// + public MessageEvent(string sender, object message) + { + this.sender = sender; + this.message = message; + } + + /// + /// Returns the name of the sending robot. + /// + public string Sender + { + get { return sender; } + } + + /// + /// Returns the message itself. + /// + public object Message + { + get { return message; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsTeamRobot()) + { + ITeamEvents listener = ((ITeamRobot) robot).GetTeamEventListener(); + + if (listener != null) + { + listener.OnMessageReceived(this); + } + } + } + + internal override byte SerializationType + { + get { throw new System.Exception("Serialization of event type not supported"); } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseClickedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseClickedEvent.cs new file mode 100644 index 0000000..bfeba0b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseClickedEvent.cs @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A MouseClickedEvent is sent to + /// when the mouse is clicked inside the battle view. + /// + /// + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class MouseClickedEvent : MouseEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new MouseClickedEvent. + /// + public MouseClickedEvent(int button, int clickCount, int x, int y, int id, int modifiersEx, long when) + : base(button, clickCount, x, y, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnMouseClicked(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.MouseClickedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + 6*RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (MouseClickedEvent) objec; + + serializer.serialize(buffer, obj.Button); + serializer.serialize(buffer, obj.ClickCount); + serializer.serialize(buffer, obj.X); + serializer.serialize(buffer, obj.Y); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseClickedEvent(button, clickCount, x, y, id, modifiersEx, when); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseDraggedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseDraggedEvent.cs new file mode 100644 index 0000000..013a1e3 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseDraggedEvent.cs @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A MouseDraggedEvent is sent to + /// when the mouse is dragged inside the battle view. + /// + /// + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class MouseDraggedEvent : MouseEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new MouseDraggedEvent. + /// + public MouseDraggedEvent(int button, int clickCount, int x, int y, int id, int modifiersEx, long when) + : base(button, clickCount, x, y, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnMouseDragged(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.MouseDraggedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + 6*RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (MouseDraggedEvent) objec; + + serializer.serialize(buffer, obj.Button); + serializer.serialize(buffer, obj.ClickCount); + serializer.serialize(buffer, obj.X); + serializer.serialize(buffer, obj.Y); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseDraggedEvent(button, clickCount, x, y, id, modifiersEx, when); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseEnteredEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseEnteredEvent.cs new file mode 100644 index 0000000..b0ce310 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseEnteredEvent.cs @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A MouseEnteredEvent is sent to + /// when the mouse has entered the battle view. + /// + /// + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class MouseEnteredEvent : MouseEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new MouseDraggedEvent. + /// + public MouseEnteredEvent(int button, int clickCount, int x, int y, int id, int modifiersEx, long when) + : base(button, clickCount, x, y, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnMouseEntered(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.MouseEnteredEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + 6*RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (MouseEnteredEvent)objec; + + serializer.serialize(buffer, obj.Button); + serializer.serialize(buffer, obj.ClickCount); + serializer.serialize(buffer, obj.X); + serializer.serialize(buffer, obj.Y); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseEnteredEvent(button, clickCount, x, y, id, modifiersEx, when); + } + } + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseEvent.cs new file mode 100644 index 0000000..2f87e17 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseEvent.cs @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; + +namespace Robocode +{ + /// + /// Super class of all events that originates from the mouse. + /// + [Serializable] + public abstract class MouseEvent : Event + { + private readonly int button; + private readonly int clickCount; + private readonly int x; + private readonly int y; + private readonly int id; + private readonly int modifiersEx; + private readonly long when; + + /// + /// Called by the game to create a new MouseEvent. + /// + protected MouseEvent(int button, int clickCount, int x, int y, int id, int modifiersEx, long when) + { + this.button = button; + this.clickCount = clickCount; + this.x = x; + this.y = y; + this.id = id; + this.modifiersEx = modifiersEx; + this.when = when; + } + + /// + /// Number of the button + /// + public int Button + { + get { return button; } + } + + /// + /// Click count + /// + public int ClickCount + { + get { return clickCount; } + } + + /// + /// Cursor coordinates + /// + public int X + { + get { return x; } + } + + /// + /// Cursor coordinates + /// + public int Y + { + get { return y; } + } + + internal int ID + { + get { return id; } + } + + internal int ModifiersEx + { + get { return modifiersEx; } + } + + /// + /// Age of the event + /// + public long When + { + get { return when; } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseExitedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseExitedEvent.cs new file mode 100644 index 0000000..7a39cc7 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseExitedEvent.cs @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A MouseExitedEvent is sent to + /// when the mouse has exited the battle view. + /// + /// + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class MouseExitedEvent : MouseEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new MouseDraggedEvent. + /// + public MouseExitedEvent(int button, int clickCount, int x, int y, int id, int modifiersEx, long when) + : base(button, clickCount, x, y, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnMouseExited(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.MouseExitedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + 6*RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (MouseExitedEvent)objec; + + serializer.serialize(buffer, obj.Button); + serializer.serialize(buffer, obj.ClickCount); + serializer.serialize(buffer, obj.X); + serializer.serialize(buffer, obj.Y); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseExitedEvent(button, clickCount, x, y, id, modifiersEx, when); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseMovedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseMovedEvent.cs new file mode 100644 index 0000000..6b4b640 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseMovedEvent.cs @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A MouseMovedEvent is sent to + /// when the mouse has moved inside the battle view. + /// + /// + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class MouseMovedEvent : MouseEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new MouseDraggedEvent. + /// + public MouseMovedEvent(int button, int clickCount, int x, int y, int id, int modifiersEx, long when) + : base(button, clickCount, x, y, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnMouseMoved(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.MouseMovedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + 6*RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (MouseMovedEvent)objec; + + serializer.serialize(buffer, obj.Button); + serializer.serialize(buffer, obj.ClickCount); + serializer.serialize(buffer, obj.X); + serializer.serialize(buffer, obj.Y); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseMovedEvent(button, clickCount, x, y, id, modifiersEx, when); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MousePressedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MousePressedEvent.cs new file mode 100644 index 0000000..35b7470 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MousePressedEvent.cs @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A MousePressedEvent is sent to + /// when the mouse is pressed inside the battle view. + /// + /// + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class MousePressedEvent : MouseEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new MouseDraggedEvent. + /// + public MousePressedEvent(int button, int clickCount, int x, int y, int id, int modifiersEx, long when) + : base(button, clickCount, x, y, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnMousePressed(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.MousePressedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + 6*RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (MousePressedEvent)objec; + + serializer.serialize(buffer, obj.Button); + serializer.serialize(buffer, obj.ClickCount); + serializer.serialize(buffer, obj.X); + serializer.serialize(buffer, obj.Y); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MousePressedEvent(button, clickCount, x, y, id, modifiersEx, when); + } + } + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseReleasedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseReleasedEvent.cs new file mode 100644 index 0000000..f3c6e75 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseReleasedEvent.cs @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A MouseReleasedEvent is sent to + /// when the mouse is released inside the battle view. + /// + /// + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class MouseReleasedEvent : MouseEvent + { + private const int DEFAULT_PRIORITY = 98; + + /// + /// Called by the game to create a new MouseDraggedEvent. + /// + public MouseReleasedEvent(int button, int clickCount, int x, int y, int id, int modifiersEx, long when) + : base(button, clickCount, x, y, id, modifiersEx, when) + { + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnMouseReleased(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.MouseReleasedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + 6*RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (MouseReleasedEvent)objec; + + serializer.serialize(buffer, obj.Button); + serializer.serialize(buffer, obj.ClickCount); + serializer.serialize(buffer, obj.X); + serializer.serialize(buffer, obj.Y); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseReleasedEvent(button, clickCount, x, y, id, modifiersEx, when); + } + } + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseWheelMovedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseWheelMovedEvent.cs new file mode 100644 index 0000000..986507d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MouseWheelMovedEvent.cs @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A MouseWheelMovedEvent is sent to + /// when the mouse wheel is rotated inside the battle view. + /// + /// + /// + /// + /// + /// + /// + /// + [Serializable] + public sealed class MouseWheelMovedEvent : MouseEvent + { + private const int DEFAULT_PRIORITY = 98; + private readonly int scrollType; + private readonly int scrollAmount; + private readonly int wheelRotation; + + /// + /// Called by the game to create a new MouseWheelMovedEvent. + /// + public MouseWheelMovedEvent(int clickCount, int x, int y, int scrollType, int scrollAmount, int wheelRotation, + int id, int modifiersEx, long when) + : base(-1, clickCount, x, y, id, modifiersEx, when) + { + this.scrollType = scrollType; + this.scrollAmount = scrollAmount; + this.wheelRotation = wheelRotation; + } + + internal int ScrollType + { + get { return scrollType; } + } + + internal int ScrollAmount + { + get { return scrollAmount; } + } + + /// + /// Indicates how far the mouse wheel was rotated. + /// + public int WheelRotation + { + get { return wheelRotation; } + } + + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsInteractiveRobot()) + { + IInteractiveEvents listener = ((IInteractiveRobot) robot).GetInteractiveEventListener(); + + if (listener != null) + { + listener.OnMouseWheelMoved(this); + } + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.MouseWheelMovedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + 8*RbSerializerN.SIZEOF_INT + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (MouseWheelMovedEvent) objec; + + serializer.serialize(buffer, obj.ClickCount); + serializer.serialize(buffer, obj.X); + serializer.serialize(buffer, obj.Y); + serializer.serialize(buffer, obj.ScrollType); + serializer.serialize(buffer, obj.ScrollAmount); + serializer.serialize(buffer, obj.WheelRotation); + serializer.serialize(buffer, obj.ID); + serializer.serialize(buffer, obj.ModifiersEx); + serializer.serialize(buffer, obj.When); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int scrollType = buffer.getInt(); + int scrollAmount = buffer.getInt(); + int wheelRotation = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseWheelMovedEvent(clickCount, x, y, scrollType, scrollAmount, wheelRotation, id, + modifiersEx, when); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MoveCompleteCondition.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MoveCompleteCondition.cs new file mode 100644 index 0000000..dde6a0b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/MoveCompleteCondition.cs @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode +{ + /// + /// A prebuilt condition you can use that indicates your robot has finished moving. + /// + /// + public class MoveCompleteCondition : Condition + { + private readonly AdvancedRobot robot; + + /// + /// Creates a new MoveCompleteCondition with default priority. + /// The default priority is 80. + /// + /// Your robot, which must be a + public MoveCompleteCondition(AdvancedRobot robot) + { + this.robot = robot; + } + + /// + /// Creates a new MoveCompleteCondition with the specified priority. + /// A condition priority is a value from 0 - 99. The higher value, the + /// higher priority. The default priority is 80. + /// + /// + /// Your robot, which must be a + /// The priority of this condition + public MoveCompleteCondition(AdvancedRobot robot, int priority) + { + this.robot = robot; + this.priority = priority; + } + + /// + /// Tests if the robot has stopped moving. + /// Returns true if the robot has stopped moving + /// + public override bool Test() + { + return (robot.DistanceRemaining == 0); + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/PaintEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/PaintEvent.cs new file mode 100644 index 0000000..6848122 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/PaintEvent.cs @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.peer; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// This event occurs when your robot should paint, where the + /// is called on your robot. + ///

+ /// You can use this event for setting the event priority by calling + /// + ///

+ [Serializable] + public sealed class PaintEvent : Event + { + private const int DEFAULT_PRIORITY = 5; + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsPaintRobot()) + { + IPaintEvents listener = ((IPaintRobot) robot).GetPaintEventListener(); + + if (listener != null) + { + listener.OnPaint(graphics); + } + } + } + + internal override byte SerializationType + { + get { throw new System.Exception("Serialization of this type is not supported"); } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RadarTurnCompleteCondition.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RadarTurnCompleteCondition.cs new file mode 100644 index 0000000..a46092a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RadarTurnCompleteCondition.cs @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode +{ + /// + /// A prebuilt condition you can use that indicates your radar has finished turning. + /// + /// + public class RadarTurnCompleteCondition : Condition + { + private readonly AdvancedRobot robot; + + /// + /// Creates a new RadarTurnCompleteCondition with default priority. + /// The default priority is 80. + /// + /// Your robot, which must be a + public RadarTurnCompleteCondition(AdvancedRobot robot) + { + this.robot = robot; + } + + /// + /// Creates a new RadarTurnCompleteCondition with the specified priority. + /// A condition priority is a value from 0 - 99. The higher value, the + /// higher priority. The default priority is 80. + /// + /// + /// Your robot, which must be a + /// The priority of this condition + public RadarTurnCompleteCondition(AdvancedRobot robot, int priority) + { + this.robot = robot; + this.priority = priority; + } + + /// + /// Tests if the radar has stopped turning. + /// Returns true if the radar has stopped turning; false otherwise + /// + public override bool Test() + { + return (robot.RadarTurnRemaining == 0); + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RateControlRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RateControlRobot.cs new file mode 100644 index 0000000..2521bcd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RateControlRobot.cs @@ -0,0 +1,364 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using Robocode.Util; + +namespace Robocode +{ + /// + /// This advanced robot type allows you to set a rate for each of the robot's movements. + ///

+ /// You can set the rate for: + ///

    + ///
  • velocity - pixels per turn
  • + ///
  • robot turn - radians per turn
  • + ///
  • gun rotation - radians per turn
  • + ///
  • radar rotation - radians per turn
  • + ///
+ /// When you set a rate for one of the above movements, the movement will continue the move by + /// specified rate for ever, until the rate is changed. In order to move ahead or right, the + /// rate must be set to a positive value. If a negative value is used instead, the movement + /// will go back or to the left. In order to stop the movement, the rate must be + /// set to 0. + /// + /// Note: When calling , , + /// , and variants, + /// any previous calls to "movement" functions outside of , + /// such as , + /// , + /// and similar will be + /// overridden when calling the on this robot class. + ///

+ /// Look into the source code for the samplecs.VelociRobot in order to see how to use this + /// robot type. + /// + /// + /// + /// + /// + /// + ///

+ public abstract class RateControlRobot : TeamRobot + { + private double velocityRate; // Pixels per turn + private double turnRate; // Radians per turn + private double gunRotationRate; // Radians per turn + private double radarRotationRate; // Radians per turn + + /// + /// + /// The speed the robot will move (forward), in pixels per turn. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot will move backwards + ///

+ /// + /// + /// // Set the robot to move forward 2 pixels per turn + /// VelocityRate = 2; + /// + /// // Set the robot to move backwards 8 pixels per turn + /// // (overrides the previous order) + /// VelocityRate = -8; + /// + /// ... + /// // Executes the last VelocityRate + /// Execute(); + /// + /// + /// Note: This method overrules and + /// + /// + /// + /// + /// + /// + /// + ///

+ public double VelocityRate + { + get { return velocityRate; } + set { velocityRate = value; } + } + + /// + /// + /// The robot's clockwise (right) rotation per turn, in degrees. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot turns counterclockwise (left) + ///

+ /// + /// + /// // Set the robot to turn right 10 degrees per turn + /// TurnRate = 10; + /// + /// // Set the robot to turn left 4 degrees per turn + /// // (overrides the previous order) + /// TurnRate = -5; + /// + /// ... + /// // Executes the last TurnRate + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public double TurnRate + { + get { return Utils.ToRadians(turnRate); } + set { turnRate = Utils.ToRadians(value); } + } + + /// + /// The robot's clockwise (right) rotation per turn, in radians. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot turns counterclockwise (left) + ///

+ /// + /// + /// // Set the robot to turn right pi / 32 radians per turn + /// TurnRateRadians = Math.PI / 32; + /// + /// // Set the robot to turn left pi / 20 radians per turn + /// // (overrides the previous order) + /// TurnRateRadians = -Math.PI / 20; + /// + /// ... + /// // Executes the last TurnRateRadians + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public double TurnRateRadians + { + get { return turnRate; } + set { turnRate = value; } + } + + /// + /// The gun's clockwise (right) rotation per turn, in degrees. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the gun turns counterclockwise (left) + ///

+ /// + /// + /// // Set the gun to turn right 15 degrees per turn + /// GunRotationRate = 15; + /// + /// // Set the gun to turn left 9 degrees per turn + /// // (overrides the previous order) + /// GunRotationRate = -9; + /// + /// ... + /// // Executes the last GunRotationRate() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public double GunRotationRate + { + get { return Utils.ToDegrees(gunRotationRate); } + set { gunRotationRate = Utils.ToRadians(value); } + } + + /// + /// The gun's clockwise (right) rotation per turn, in radians. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the gun turns counterclockwise (left) + ///

+ /// + /// + /// // Set the gun to turn right pi / 16 radians per turn + /// GunRotationRateRadians = Math.PI / 16; + /// + /// // Set the gun to turn left pi / 12 radians per turn + /// // (overrides the previous order) + /// GunRotationRateRadians = -Math.PI / 12; + /// + /// ... + /// // Executes the last GunRotationRateRadians + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public double GunRotationRateRadians + { + get { return gunRotationRate; } + set { gunRotationRate = value; } + } + + /// + /// The radar's clockwise (right) rotation per turn, in degrees. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the radar turns counterclockwise (left) + ///

+ /// + /// + /// // Set the radar to turn right 45 degrees per turn + /// RadarRotationRate = 45; + /// + /// // Set the radar to turn left 15 degrees per turn + /// // (overrides the previous order) + /// RadarRotationRate = -15; + /// + /// ... + /// // Executes the last RadarRotationRate + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public double RadarRotationRate + { + get { return Utils.ToDegrees(radarRotationRate); } + set { radarRotationRate = Utils.ToRadians(value); } + } + + /// + /// The radar's clockwise (right) rotation per turn, in radians. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the radar turns counterclockwise (left) + ///

+ /// + /// + /// // Set the radar to turn right pi / 4 radians per turn + /// RadarRotationRateRadians = Math.PI / 4; + /// + /// // Set the radar to turn left pi / 8 radians per turn + /// // (overrides the previous order) + /// RadarRotationRateRadians = -Math.PI / 8; + /// + /// ... + /// // Executes the last RadarRotationRateRadians + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public double RadarRotationRateRadians + { + get { return radarRotationRate; } + set { radarRotationRate = value; } + } + + /// + /// Executes any pending actions, or continues executing actions that are + /// in process. This call returns after the actions have been started. + ///

+ /// Note that advanced robots must call this function in order to + /// Execute pending set* calls like e.g. , + /// , + /// etc. Otherwise, these calls will never get executed. + ///

+ /// Any previous calls to "movement" functions outside of + /// , such as + /// , + /// , + /// + /// etc. will be overridden when this method is called on this robot class. + ///

+ /// + /// In this example the robot will move while turning: + /// + /// VelocityRate = 6; + /// TurnRate = 7; + /// + /// while (true) + /// { + /// Execute(); + /// } + /// + /// + ///

+ public override void Execute() + { + MaxVelocity = velocityRate; + if (velocityRate > 0) + { + SetAhead(Double.PositiveInfinity); + } + else if (velocityRate < 0) + { + SetBack(Double.PositiveInfinity); + } + else + { + SetAhead(0); + } + + SetTurnGunRightRadians(gunRotationRate); + SetTurnRadarRightRadians(radarRotationRate); + SetTurnRightRadians(turnRate); + + base.Execute(); + } + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Robot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Robot.cs new file mode 100644 index 0000000..4d65225 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Robot.cs @@ -0,0 +1,1927 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using System.IO; +using System.Security.Permissions; +using net.sf.robocode.security; +using Robocode.Exception; +using Robocode.RobotInterfaces; +using Robocode.RobotInterfaces.Peer; +using Robocode.Util; + +namespace Robocode +{ + /// + /// + /// The basic robot class that you will extend to create your own robots. + ///

+ /// Please note the following standards will be used: + ///

+ /// heading - absolute angle in degrees with 0 facing up the screen, + /// positive clockwise. 0 <= heading < 360. + ///

+ /// bearing - relative angle to some obj from your robot's heading, + /// positive clockwise. -180 < bearing <= 180 + ///

+ /// All coordinates are expressed as (x,y). + /// All coordinates are positive. + ///

+ /// The origin (0,0) is at the bottom left of the screen. + ///

+ /// Positive X is right. + /// Positive Y is up. + ///
+ ///
+ /// Building your first robot + /// + /// + /// + /// + /// + /// + /// + ///

+ public abstract class Robot : IInteractiveRobot, IPaintRobot, IBasicEvents3, IInteractiveEvents, IPaintEvents, IRunnable + { + private const int + WIDTH = 36, + HEIGHT = 36; + + internal IBasicRobotPeer peer; + internal TextWriter _output; + + /// + /// The Out stream your robot should use to print. + ///

+ /// You can view the print-outs by clicking the button for your robot in the + /// right side of the battle window. + ///

+ /// + /// + /// // Print Out a line each time my robot hits another robot + /// public void OnHitRobot(HitRobotEvent e) + /// { + /// Out.WriteLine("I hit a robot! My energy: " + Energy + " his energy: " + e.Energy); + /// } + /// + /// + ///

+ public TextWriter Out + { + get { return _output; } + } + + [RobocodeInternalPermission(SecurityAction.LinkDemand)] + void IBasicRobot.SetOut(TextWriter outpt) + { + _output = outpt; + } + + [RobocodeInternalPermission(SecurityAction.LinkDemand)] + void IBasicRobot.SetPeer(IBasicRobotPeer per) + { + peer = per; + } + + /// + /// Throws a RobotException. + /// This method should be called when the robot's peer is uninitialized. + /// + internal static void UninitializedException() + { + throw new RobotException( + "You cannot call the methods before your Run() method is called, or you are using a Robot object that the game doesn't know about."); + } + + /// + IRunnable IBasicRobot.GetRobotRunnable() + { + return this; + } + + /// + IBasicEvents IBasicRobot.GetBasicEventListener() + { + return this; + } + + /// + IInteractiveEvents IInteractiveRobot.GetInteractiveEventListener() + { + return this; + } + + /// + IPaintEvents IPaintRobot.GetPaintEventListener() + { + return this; + } + + /// + /// Immediately moves your robot ahead (forward) by distance measured in + /// pixels. + ///

+ /// This call executes immediately, and does not return until it is complete, + /// i.e. when the remaining distance to move is 0. + ///

+ /// If the robot collides with a wall, the move is complete, meaning that the + /// robot will not move any further. If the robot collides with another + /// robot, the move is complete if you are heading toward the other robot. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot is set to move backward + /// instead of forward. + ///

+ /// + /// + /// // Move the robot 100 pixels forward + /// Ahead(100); + /// + /// // Afterwards, move the robot 50 pixels backward + /// Ahead(-50); + /// + /// + ///

+ /// + /// The distance to move ahead measured in pixels. + /// If this value is negative, the robot will move back instead of ahead. + /// + /// + /// + /// + public void Ahead(double distance) + { + if (peer != null) + { + peer.Move(distance); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately moves your robot backward by distance measured in pixels. + ///

+ /// This call executes immediately, and does not return until it is complete, + /// i.e. when the remaining distance to move is 0. + ///

+ /// If the robot collides with a wall, the move is complete, meaning that the + /// robot will not move any further. If the robot collides with another + /// robot, the move is complete if you are heading toward the other robot. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot is set to move forward instead + /// of backward. + ///

+ /// + /// + /// // Move the robot 100 pixels backward + /// Back(100); + /// + /// // Afterwards, move the robot 50 pixels forward + /// Back(-50); + /// + /// + /// + /// + /// + ///

+ /// + /// The distance to move back measured in pixels. + /// If this value is negative, the robot will move ahead instead of back. + /// + public void Back(double distance) + { + if (peer != null) + { + peer.Move(-distance); + } + else + { + UninitializedException(); + } + } + + /// + /// Returns the width of the current battlefield measured in pixels. + /// + public double BattleFieldWidth + { + get + { + if (peer != null) + { + return peer.GetBattleFieldWidth(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the height of the current battlefield measured in pixels. + /// + public double BattleFieldHeight + { + get + { + if (peer != null) + { + return peer.GetBattleFieldHeight(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the direction that the robot's body is facing, in degrees. + /// The value returned will be between 0 and 360 (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// 90 means East, 180 means South, and 270 means West. + /// + /// + ///

+ public double Heading + { + get + { + if (peer != null) + { + double rv = 180.0*peer.GetBodyHeading()/Math.PI; + + while (rv < 0) + { + rv += 360; + } + while (rv >= 360) + { + rv -= 360; + } + return rv; + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the height of the robot measured in pixels. + /// + /// + public double Height + { + get + { + if (peer == null) + { + UninitializedException(); + } + return HEIGHT; + } + } + + /// + /// Returns the width of the robot measured in pixels. + /// + /// + public double Width + { + get + { + if (peer == null) + { + UninitializedException(); + } + return WIDTH; + } + } + + /// + /// Returns the robot's name. + /// + public string Name + { + get + { + if (peer != null) + { + return peer.GetName(); + } + UninitializedException(); + return null; // never called + } + } + + /// + /// Returns the X position of the robot. (0,0) is at the bottom left of the battlefield. + /// + /// + public double X + { + get + { + if (peer != null) + { + return peer.GetX(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the Y position of the robot. (0,0) is at the bottom left of the battlefield. + /// + /// + public double Y + { + get + { + if (peer != null) + { + return peer.GetY(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// The main method in every robot. You must override this to set up your + /// robot's basic behavior. + ///

+ /// + /// + /// // A basic robot that moves around in a square + /// public void Run() + /// { + /// while (true) + /// { + /// Ahead(100); + /// TurnRight(90); + /// } + /// } + /// + /// + ///

+ public virtual void Run() + { + } + + /// + /// Immediately turns the robot's body to the left by degrees. + ///

+ /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the robot's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's body is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Turn the robot 180 degrees to the left + /// TurnLeft(180); + /// + /// // Afterwards, turn the robot 90 degrees to the right + /// TurnLeft(-90); + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's body to the left. + /// If degrees > 0 the robot will turn left. + /// If degrees < 0 the robot will turn right. + /// If degrees = 0 the robot will not turn, but execute. + /// + public void TurnLeft(double degrees) + { + if (peer != null) + { + peer.TurnBody(-Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// + /// Immediately turns the robot's body to the right by degrees. + /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the robot's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's body is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Turn the robot 180 degrees to the right + /// TurnRight(180); + /// + /// // Afterwards, turn the robot 90 degrees to the left + /// TurnRight(-90); + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's body to the right. + /// If degrees > 0 the robot will turn right. + /// If degrees < 0 the robot will turn left. + /// If degrees = 0 the robot will not turn, but execute. + /// + public void TurnRight(double degrees) + { + if (peer != null) + { + peer.TurnBody(Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Do nothing this turn, meaning that the robot will skip it's turn. + ///

+ /// This call executes immediately, and does not return until the turn is over. + ///

+ public void DoNothing() + { + if (peer != null) + { + peer.Execute(); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately fires a bullet. The bullet will travel in the direction the + /// gun is pointing. + ///

+ /// The specified bullet power is an amount of energy that will be taken from + /// the robot's energy. Hence, the more power you want to spend on the + /// bullet, the more energy is taken from your robot. + ///

+ /// The bullet will do (4 * power) damage if it hits another robot. If power + /// is greater than 1, it will do an additional 2 * (power - 1) damage. + /// You will get (3 * power) back if you hit the other robot. You can call + /// + /// for getting the damage that a + /// bullet with a specific bullet power will do. + ///

+ /// The specified bullet power should be between + /// and . + ///

+ /// Note that the gun cannot Fire if the gun is overheated, meaning that + /// + /// returns a value > 0. + ///

+ /// A event is generated when the bullet hits a robot (), + /// wall (), or another bullet + /// (). + ///

+ /// + /// + /// // Fire a bullet with maximum power if the gun is ready + /// if (GetGunHeat() == 0) + /// { + /// Fire(Rules.MAX_BULLET_POWER); + /// } + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of energy given to the bullet, and subtracted from the robot's energy. + /// + public void Fire(double power) + { + if (peer != null) + { + peer.SetFire(power); + peer.Execute(); + } + else + { + UninitializedException(); + } + } + + /// + /// + /// Immediately fires a bullet. The bullet will travel in the direction the + /// gun is pointing. + ///

+ /// The specified bullet power is an amount of energy that will be taken from + /// the robot's energy. Hence, the more power you want to spend on the + /// bullet, the more energy is taken from your robot. + ///

+ /// The bullet will do (4 * power) damage if it hits another robot. If power + /// is greater than 1, it will do an additional 2 * (power - 1) damage. + /// You will get (3 * power) back if you hit the other robot. You can call + /// + /// for getting the damage that a + /// bullet with a specific bullet power will do. + ///

+ /// The specified bullet power should be between + /// and . + ///

+ /// Note that the gun cannot Fire if the gun is overheated, meaning that + /// returns a value > 0. + ///

+ /// A event is generated when the bullet hits a robot (), + /// wall (), or another bullet + /// (). + ///

+ /// + /// + /// // Fire a bullet with maximum power if the gun is ready + /// if (GetGunHeat() == 0) + /// { + /// Bullet bullet = FireBullet(Rules.MAX_BULLET_POWER); + /// + /// // Get the velocity of the bullet + /// if (bullet != null) + /// { + /// double bulletVelocity = bullet.Velocity; + /// } + /// } + /// + /// + /// Returns a + /// + /// That contains information about the bullet if it was actually fired, + /// which can be used for tracking the bullet after it has been fired. + /// If the bullet was not fired, null is returned. + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// power the amount of energy given to the bullet, and subtracted from the robot's energy. + /// + public Bullet FireBullet(double power) + { + if (peer != null) + { + return peer.Fire(power); + } + UninitializedException(); + return null; + } + + /// + /// Returns the rate at which the gun will cool down, i.e. the amount of heat + /// the gun heat will drop per turn. + ///

+ /// The gun cooling rate is default 0.1 / turn, but can be changed by the + /// battle setup. So don't count on the cooling rate being 0.1! + /// + /// + /// + ///

+ public double GunCoolingRate + { + get + { + if (peer != null) + { + return peer.GetGunCoolingRate(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the direction that the robot's gun is facing, in degrees. + /// The value returned will be between 0 and 360 (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// 90 means East, 180 means South, and 270 means West. + /// + /// + ///

+ public double GunHeading + { + get + { + if (peer != null) + { + return peer.GetGunHeading()*180.0/Math.PI; + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the current heat of the gun. The gun cannot Fire unless this is + /// 0. (Calls to Fire will succeed, but will not actually Fire unless + /// GetGunHeat() == 0). + ///

+ /// The amount of gun heat generated when the gun is fired is 1 + (firePower / 5). + /// Each turn the gun heat drops by the amount returned by , + /// which is a battle setup. + ///

+ /// Note that all guns are "hot" at the start of each round, where the gun heat is 3. + /// + /// + /// + ///

+ public double GunHeat + { + get + { + if (peer != null) + { + return peer.GetGunHeat(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the number of rounds in the current battle. + /// + /// + public int NumRounds + { + get + { + if (peer != null) + { + return peer.GetNumRounds(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the sentry border size for a BorderSentry that defines the how + /// far a BorderSentry is allowed to move from the border edges measured in units.
+ /// Hence, the sentry border size defines the width/range of the border area surrounding the battlefield that + /// BorderSentrys cannot leave (sentry robots robots must stay in the border area), but it also define the + /// distance from the border edges where BorderSentrys are allowed/able to make damage to robots entering this + /// border area. + ///
+ public int SentryBorderSize + { + get { + if (peer != null) + { + return peer.GetSentryBorderSize(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns how many opponents that are left in the current round. + /// + public int Others + { + get + { + if (peer != null) + { + return peer.GetOthers(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns how many sentry robots that are left in the current round. + /// + public int NumSentries + { + get + { + if (peer != null) + { + return peer.GetNumSentries(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the direction that the robot's radar is facing, in degrees. + /// The value returned will be between 0 and 360 (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// 90 means East, 180 means South, and 270 means West. + /// + /// + ///

+ public double RadarHeading + { + get + { + if (peer != null) + { + return peer.GetRadarHeading()*180.0/Math.PI; + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the current round number (0 to - 1) of the battle. + /// + /// + public int RoundNum + { + get + { + if (peer != null) + { + return peer.GetRoundNum(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the game time of the current round, where the time is equal to + /// the current turn in the round. + ///

+ /// A battle consists of multiple rounds. + ///

+ /// Time is reset to 0 at the beginning of every round. + ///

+ public long Time + { + get + { + if (peer != null) + { + return peer.GetTime(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns the velocity of the robot measured in pixels/turn. + ///

+ /// The maximum velocity of a robot is defined by + /// (8 pixels / turn). + /// + ///

+ public double Velocity + { + get + { + if (peer != null) + { + return peer.GetVelocity(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + public virtual void OnBulletHit(BulletHitEvent evnt) + { + } + + /// + public virtual void OnBulletHitBullet(BulletHitBulletEvent evnt) + { + } + + /// + public virtual void OnBulletMissed(BulletMissedEvent evnt) + { + } + + /// + public virtual void OnDeath(DeathEvent evnt) + { + } + + /// + public virtual void OnHitByBullet(HitByBulletEvent evnt) + { + } + + /// + public virtual void OnHitRobot(HitRobotEvent evnt) + { + } + + /// + public virtual void OnHitWall(HitWallEvent evnt) + { + } + + /// + public virtual void OnRobotDeath(RobotDeathEvent evnt) + { + } + + /// + public virtual void OnScannedRobot(ScannedRobotEvent evnt) + { + } + + /// + public virtual void OnWin(WinEvent evnt) + { + } + + /// + public virtual void OnRoundEnded(RoundEndedEvent evnt) + { + } + + /// + public virtual void OnBattleEnded(BattleEndedEvent evnt) + { + } + + /// + /// + /// Scans for other robots. This method is called automatically by the game, + /// as long as the robot is moving, turning its body, turning its gun, or + /// turning its radar. + ///

+ /// Scan will cause + /// to be called if you see a robot. + ///

+ /// There are 2 reasons to call manually: + ///

    + ///
  1. + /// You want to scan after you stop moving. + ///
  2. + ///
  3. + /// You want to interrupt the + /// event. This is more likely. If you are in + /// and call + /// , and you still see a robot, then the system will interrupt your + /// event immediately and start it + /// from the top. + ///
  4. + ///
+ ///

+ /// This call executes immediately. + /// + /// + ///

+ public void Scan() + { + if (peer != null) + { + peer.Rescan(); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the gun to turn independent from the robot's turn. + ///

+ /// Ok, so this needs some explanation: The gun is mounted on the robot's + /// body. So, normally, if the robot turns 90 degrees to the right, then the + /// gun will turn with it as it is mounted on top of the robot's body. To + /// compensate for this, you can call + /// . + /// When this is set, the gun will turn independent from the robot's turn, + /// i.e. the gun will compensate for the robot's body turn. + ///

+ /// Note: This method is additive until you reach the maximum the gun can + /// turn. The "adjust" is added to the amount you set for turning the robot, + /// then capped by the physics of the game. If you turn infinite, then the + /// adjust is ignored (and hence overridden). + ///

+ /// + /// Assuming both the robot and gun start Out facing up (0 degrees): + /// + /// // Set gun to turn with the robot's turn + /// SetAdjustGunForRobotTurn(false); // This is the default + /// TurnRight(90); + /// // At this point, both the robot and gun are facing right (90 degrees) + /// TurnLeft(90); + /// // Both are back to 0 degrees + /// + /// -- or -- + /// + /// // Set gun to turn independent from the robot's turn + /// SetAdjustGunForRobotTurn(true); + /// TurnRight(90); + /// // At this point, the robot is facing right (90 degrees), but the gun is still facing up. + /// TurnLeft(90); + /// // Both are back to 0 degrees. + /// + /// + ///

+ /// Note: The gun compensating this way does count as "turning the gun". + /// + ///

+ public virtual bool IsAdjustGunForRobotTurn + { + get + { + if (peer != null) + { + return ((IStandardRobotPeer) peer).IsAdjustGunForBodyTurn(); + } + UninitializedException(); + return false; + } + set + { + if (peer != null) + { + ((IStandardRobotPeer) peer).SetAdjustGunForBodyTurn(value); + } + else + { + UninitializedException(); + } + } + } + + /// + /// Sets the radar to turn independent from the robot's turn. + ///

+ /// Ok, so this needs some explanation: The radar is mounted on the gun, and + /// the gun is mounted on the robot's body. So, normally, if the robot turns + /// 90 degrees to the right, the gun turns, as does the radar. Hence, if the + /// robot turns 90 degrees to the right, then the gun and radar will turn + /// with it as the radar is mounted on top of the gun. To compensate for + /// this, you can call = true. + /// When this is set, the radar will turn independent from the robot's turn, + /// i.e. the radar will compensate for the robot's turn. + ///

+ /// Note: This method is additive until you reach the maximum the radar can + /// turn. The "adjust" is added to the amount you set for turning the robot, + /// then capped by the physics of the game. If you turn infinite, then the + /// adjust is ignored (and hence overridden). + ///

+ /// + /// Assuming the robot, gun, and radar all start Out facing up (0 + /// degrees): + /// + /// // Set radar to turn with the robots's turn + /// SetAdjustRadarForRobotTurn(false); // This is the default + /// TurnRight(90); + /// // At this point, the body, gun, and radar are all facing right (90 degrees); + /// + /// -- or -- + /// + /// // Set radar to turn independent from the robot's turn + /// SetAdjustRadarForRobotTurn(true); + /// TurnRight(90); + /// // At this point, the robot and gun are facing right (90 degrees), but the radar is still facing up. + /// + /// + /// + /// + ///

+ public bool IsAdjustRadarForRobotTurn + { + get + { + if (peer != null) + { + return ((IStandardRobotPeer) peer).IsAdjustRadarForBodyTurn(); + } + UninitializedException(); + return false; + } + set + { + if (peer != null) + { + ((IStandardRobotPeer) peer).SetAdjustRadarForBodyTurn(value); + } + else + { + UninitializedException(); + } + } + } + + /// + /// Sets the radar to turn independent from the gun's turn. + ///

+ /// Ok, so this needs some explanation: The radar is mounted on the robot's + /// gun. So, normally, if the gun turns 90 degrees to the right, then the + /// radar will turn with it as it is mounted on top of the gun. To compensate + /// for this, you can call = (true). + /// When this is set, the radar will turn independent from the robot's turn, + /// i.e. the radar will compensate for the gun's turn. + ///

+ /// Note: This method is additive until you reach the maximum the radar can + /// turn. The "adjust" is added to the amount you set for turning the gun, + /// then capped by the physics of the game. If you turn infinite, then the + /// adjust is ignored (and hence overridden). + ///

+ /// + /// Assuming both the gun and radar start Out facing up (0 degrees): + /// + /// // Set radar to turn with the gun's turn + /// SetAdjustRadarForGunTurn(false); // This is the default + /// TurnGunRight(90); + /// // At this point, both the radar and gun are facing right (90 degrees); + /// + /// -- or -- + /// + /// // Set radar to turn independent from the gun's turn + /// SetAdjustRadarForGunTurn(true); + /// TurnGunRight(90); + /// // At this point, the gun is facing right (90 degrees), but the radar is still facing up. + /// + /// + /// Note: Calling will automatically call + /// with the same value, unless you have + /// already called it earlier. This behavior is primarily for backward compatibility + /// with older Robocode robots. + /// + /// + ///

+ public bool IsAdjustRadarForGunTurn + { + get + { + if (peer != null) + { + return ((IStandardRobotPeer) peer).IsAdjustRadarForGunTurn(); + } + UninitializedException(); + return false; + } + set + { + if (peer != null) + { + ((IStandardRobotPeer) peer).SetAdjustRadarForGunTurn(value); + } + else + { + UninitializedException(); + } + } + } + + /// + /// Sets the color of the robot's body, gun, and radar in the same time. + ///

+ /// You may only call this method one time per battle. A null + /// indicates the default (blue) color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetColors(null, Color.Red, Color.fromArgb(150, 0, 150)); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The new body color + /// The new gun color + /// The new radar color + public void SetColors(Color bodyColor, Color gunColor, Color radarColor) + { + if (peer != null) + { + peer.SetBodyColor(bodyColor); + peer.SetGunColor(gunColor); + peer.SetRadarColor(radarColor); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the color of the robot's body, gun, radar, bullet, and scan arc in + /// the same time. + ///

+ /// You may only call this method one time per battle. A null + /// indicates the default (blue) color for the body, gun, radar, and scan + /// arc, but white for the bullet color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetColors(null, Color.Red, Color.Greeen, null, Color.fromArgb(150, 0, 150)); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The new body color + /// The new gun color + /// The new radar color + /// The new bullet color + /// The new scan arc color + public void SetColors(Color bodyColor, Color gunColor, Color radarColor, Color bulletColor, Color scanArcColor) + { + if (peer != null) + { + peer.SetBodyColor(bodyColor); + peer.SetGunColor(gunColor); + peer.SetRadarColor(radarColor); + peer.SetBulletColor(bulletColor); + peer.SetScanColor(scanArcColor); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets all the robot's color to the same color in the same time, i.e. the + /// color of the body, gun, radar, bullet, and scan arc. + ///

+ /// You may only call this method one time per battle. A null + /// indicates the default (blue) color for the body, gun, radar, and scan + /// arc, but white for the bullet color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetAllColors(Color.Red); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The new color for all the colors of the robot + public void SetAllColors(Color color) + { + if (peer != null) + { + peer.SetBodyColor(color); + peer.SetGunColor(color); + peer.SetRadarColor(color); + peer.SetBulletColor(color); + peer.SetScanColor(color); + } + else + { + UninitializedException(); + } + } + + /// + /// Sets the color of the robot's body. + ///

+ /// A null indicates the default (blue) color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetBodyColor(Color.Black); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public Color BodyColor + { + set + { + if (peer != null) + { + peer.SetBodyColor(value); + } + else + { + UninitializedException(); + } + } + get + { + if (peer != null) + { + return peer.GetBodyColor(); + } + UninitializedException(); + return default(Color); + } + } + + /// + /// + /// Sets the color of the robot's gun. + ///

+ /// A null indicates the default (blue) color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetGunColor(Color.Red); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public Color GunColor + { + set + { + if (peer != null) + { + peer.SetGunColor(value); + } + else + { + UninitializedException(); + } + } + get + { + if (peer != null) + { + return peer.GetGunColor(); + } + UninitializedException(); + return default(Color); + } + } + + /// + /// + /// Sets the color of the robot's radar. + ///

+ /// A null indicates the default (blue) color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetRadarColor(Color.Yellow); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public Color RadarColor + { + set + { + if (peer != null) + { + peer.SetRadarColor(value); + } + else + { + UninitializedException(); + } + } + get + { + if (peer != null) + { + return peer.GetRadarColor(); + } + UninitializedException(); + return default(Color); + } + } + + /// + /// + /// Sets the color of the robot's bullets. + ///

+ /// A null indicates the default white color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetBulletColor(Color.Green); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public Color BulletColor + { + set + { + if (peer != null) + { + peer.SetBulletColor(value); + } + else + { + UninitializedException(); + } + } + get + { + if (peer != null) + { + return peer.GetBulletColor(); + } + UninitializedException(); + return default(Color); + } + } + + /// + /// + /// Sets the color of the robot's scan arc. + ///

+ /// A null indicates the default (blue) color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetScanColor(Color.White); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ public Color ScanColor + { + set + { + if (peer != null) + { + peer.SetScanColor(value); + } + else + { + UninitializedException(); + } + } + get + { + if (peer != null) + { + return peer.GetScanColor(); + } + UninitializedException(); + return default(Color); + } + } + + /// + /// + /// Immediately stops all movement, and saves it for a call to . + /// If there is already movement saved from a previous stop, this will have no effect. + ///

+ /// This method is equivalent to Stop(false). + /// + /// + ///

+ public void Stop() + { + Stop(false); + } + + /// + /// Immediately stops all movement, and saves it for a call to . + /// If there is already movement saved from a previous stop, you can overwrite it by + /// calling Stop(true). + /// + /// + /// + /// + /// If there is already movement saved from a previous stop, you can overwrite it by + /// calling Stop(true). + /// + public void Stop(bool overwrite) + { + if (peer != null) + { + ((IStandardRobotPeer) peer).Stop(overwrite); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately resumes the movement you stopped by , if any. + ///

+ /// This call executes immediately, and does not return until it is complete. + /// + /// + ///

+ public void Resume() + { + if (peer != null) + { + ((IStandardRobotPeer) peer).Resume(); + } + else + { + UninitializedException(); + } + } + + /// + /// + /// Immediately turns the robot's gun to the left by degrees. + ///

+ /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the gun's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's gun is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Turn the robot's gun 180 degrees to the left + /// TurnGunLeft(180); + /// + /// // Afterwards, turn the robot's gun 90 degrees to the right + /// TurnGunLeft(-90); + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's gun to the left. + /// If degrees > 0 the robot's gun will turn left. + /// If degrees < 0 the robot's gun will turn right. + /// If degrees = 0 the robot's gun will not turn, but execute. + /// + public void TurnGunLeft(double degrees) + { + if (peer != null) + { + peer.TurnGun(-Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// + /// Immediately turns the robot's gun to the right by degrees. + /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the gun's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's gun is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Turn the robot's gun 180 degrees to the right + /// TurnGunRight(180); + /// + /// // Afterwards, turn the robot's gun 90 degrees to the left + /// TurnGunRight(-90); + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's gun to the right. + /// If degrees > 0 the robot's gun will turn right. + /// If degrees < 0 the robot's gun will turn left. + /// If degrees = 0 the robot's gun will not turn, but execute. + /// + public void TurnGunRight(double degrees) + { + if (peer != null) + { + peer.TurnGun(Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Immediately turns the robot's radar to the left by degrees. + ///

+ /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the radar's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's radar is set to turn right + /// instead of left. + ///

+ /// + /// + /// // Turn the robot's radar 180 degrees to the left + /// TurnRadarLeft(180); + /// + /// // Afterwards, turn the robot's radar 90 degrees to the right + /// TurnRadarLeft(-90); + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's radar to the left. + /// If degrees > 0 the robot's radar will turn left. + /// If degrees < 0 the robot's radar will turn right. + /// If degrees = 0 the robot's radar will not turn, but execute. + /// + public void TurnRadarLeft(double degrees) + { + if (peer != null) + { + ((IStandardRobotPeer) peer).TurnRadar(-Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// + /// Immediately turns the robot's radar to the right by degrees. + /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the radar's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, + /// where negative values means that the robot's radar is set to turn left + /// instead of right. + ///

+ /// + /// + /// // Turn the robot's radar 180 degrees to the right + /// TurnRadarRight(180); + /// + /// // Afterwards, turn the robot's radar 90 degrees to the left + /// TurnRadarRight(-90); + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of degrees to turn the robot's radar to the right. + /// If degrees > 0 the robot's radar will turn right. + /// If degrees < 0 the robot's radar will turn left. + /// If degrees = 0 the robot's radar will not turn, but execute. + /// + public void TurnRadarRight(double degrees) + { + if (peer != null) + { + ((IStandardRobotPeer) peer).TurnRadar(Utils.ToRadians(degrees)); + } + else + { + UninitializedException(); + } + } + + /// + /// Returns the robot's current energy. + /// + public double Energy + { + get + { + if (peer != null) + { + return peer.GetEnergy(); + } + UninitializedException(); + return 0; // never called + } + } + + /// + /// Returns a graphics context used for painting graphical items for the robot. + ///

+ /// This method is very useful for debugging your robot. + ///

+ /// Note that the robot will only be painted if the "Paint" is enabled on the + /// robot's console window; otherwise the robot will never get painted (the + /// reason being that all robots might have graphical items that must be + /// painted, and then you might not be able to tell what graphical items that + /// have been painted for your robot). + ///

+ /// Also note that the coordinate system for the graphical context where you + /// paint items fits for the Robocode coordinate system where (0, 0) is at + /// the bottom left corner of the battlefield, where X is towards right and Y + /// is upwards. + /// + ///

+ public IGraphics Graphics + { + get + { + if (peer != null) + { + return peer.GetGraphics(); + } + UninitializedException(); + return null; // never called + } + } + + /// + /// Sets the debug property with the specified key to the specified value. + ///

+ /// This method is very useful when debugging or reviewing your robot as you + /// will be able to see this property displayed in the robot console for your + /// robots under the Debug Properties tab page. + ///

+ public DebugPropertyH DebugProperty + { + get + { + if (peer != null) + { + if (debugProperty == null) + { + debugProperty = new DebugPropertyH(peer); + } + return debugProperty; + } + UninitializedException(); + return null; + } + } + + private DebugPropertyH debugProperty; + + /// + /// Container class for debug properties + /// + public class DebugPropertyH + { + private readonly IBasicRobotPeer peer; + + internal DebugPropertyH(IBasicRobotPeer peer) + { + this.peer = peer; + } + + /// + /// Set the new value of the debug property, where null or + /// the empty string is used for removing this debug property. + /// + /// + /// The name/key of the debug property + /// + /// + public string this[string key] + { + set { peer.SetDebugProperty(key, value); } + } + } + + + /// + public virtual void OnPaint(IGraphics graphics) + { + } + + /// + public virtual void OnKeyPressed(KeyEvent e) + { + } + + /// + public virtual void OnKeyReleased(KeyEvent e) + { + } + + /// + public virtual void OnKeyTyped(KeyEvent e) + { + } + + /// + public virtual void OnMouseClicked(MouseEvent e) + { + } + + /// + public virtual void OnMouseEntered(MouseEvent e) + { + } + + /// + public virtual void OnMouseExited(MouseEvent e) + { + } + + /// + public virtual void OnMousePressed(MouseEvent e) + { + } + + /// + public virtual void OnMouseReleased(MouseEvent e) + { + } + + /// + public virtual void OnMouseMoved(MouseEvent e) + { + } + + /// + public virtual void OnMouseDragged(MouseEvent e) + { + } + + /// + public virtual void OnMouseWheelMoved(MouseWheelMovedEvent e) + { + } + + /// + public virtual void OnStatus(StatusEvent e) + { + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RobotDeathEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RobotDeathEvent.cs new file mode 100644 index 0000000..e93c3cf --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RobotDeathEvent.cs @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// This event is sent to + /// when another robot (not your robot) dies. + /// + [Serializable] + public sealed class RobotDeathEvent : Event + { + private const int DEFAULT_PRIORITY = 70; + + private readonly string robotName; + + /// + /// Called by the game to create a new RobotDeathEvent. + /// + /// the name of the robot that died + public RobotDeathEvent(string robotName) + { + this.robotName = robotName; + } + + /// + /// Returns the name of the robot that died. + /// + public string Name + { + get { return robotName; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnRobotDeath(this); + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.RobotDeathEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + var obj = (RobotDeathEvent) objec; + + return RbSerializerN.SIZEOF_TYPEINFO + serializer.sizeOf(obj.robotName); + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (RobotDeathEvent) objec; + + serializer.serialize(buffer, obj.robotName); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + string name = serializer.deserializeString(buffer); + + return new RobotDeathEvent(name); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RobotStatus.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RobotStatus.cs new file mode 100644 index 0000000..0d6be6e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RobotStatus.cs @@ -0,0 +1,401 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.security; +using net.sf.robocode.serialization; +using Robocode.Util; + +namespace Robocode +{ + /// + /// Contains the status of a robot for a specific time/turn returned by + /// . + /// + [Serializable] + public sealed class RobotStatus + { + private readonly double energy; + private readonly double x; + private readonly double y; + private readonly double bodyHeading; + private readonly double gunHeading; + private readonly double radarHeading; + private readonly double velocity; + private readonly double bodyTurnRemaining; + private readonly double radarTurnRemaining; + private readonly double gunTurnRemaining; + private readonly double distanceRemaining; + private readonly double gunHeat; + private readonly int others; + private readonly int numSentries; + private readonly int roundNum; + private readonly int numRounds; + private readonly long time; + + /// + /// Returns the robot's current energy. + /// + public double Energy + { + get { return energy; } + } + + /// + /// Returns the X position of the robot. (0,0) is at the bottom left of the + /// battlefield. + /// + /// + public double X + { + get { return x; } + } + + /// + /// Returns the Y position of the robot. (0,0) is at the bottom left of the + /// battlefield. + /// + /// + public double Y + { + get { return y; } + } + + /// + /// Returns the direction that the robot's body is facing, in radians. + /// The value returned will be between 0 and 2 * PI (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// PI / 2 means East, PI means South, and 3 * PI / 2 means West. + ///

+ public double HeadingRadians + { + get { return bodyHeading; } + } + + /// + /// Returns the direction that the robot's body is facing, in degrees. + /// The value returned will be between 0 and 360 (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// 90 means East, 180 means South, and 270 means West. + ///

+ public double Heading + { + get { return Utils.ToDegrees(bodyHeading); } + } + + /// + /// Returns the direction that the robot's gun is facing, in radians. + /// The value returned will be between 0 and 2 * PI (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// PI / 2 means East, PI means South, and 3 * PI / 2 means West. + ///

+ public double GunHeadingRadians + { + get { return gunHeading; } + } + + /// + /// Returns the direction that the robot's gun is facing, in degrees. + /// The value returned will be between 0 and 360 (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// 90 means East, 180 means South, and 270 means West. + ///

+ public double GunHeading + { + get { return Utils.ToDegrees(gunHeading); } + } + + /// + /// Returns the direction that the robot's radar is facing, in radians. + /// The value returned will be between 0 and 2 * PI (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// PI / 2 means East, PI means South, and 3 * PI / 2 means West. + ///

+ public double RadarHeadingRadians + { + get { return radarHeading; } + } + + /// + /// Returns the direction that the robot's radar is facing, in degrees. + /// The value returned will be between 0 and 360 (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// 90 means East, 180 means South, and 270 means West. + ///

+ public double RadarHeading + { + get { return Utils.ToDegrees(radarHeading); } + } + + /// + /// Returns the velocity of the robot measured in pixels/turn. + ///

+ /// The maximum velocity of a robot is defined by + /// (8 pixels / turn). + /// + ///

+ public double Velocity + { + get { return velocity; } + } + + /// + /// Returns the angle remaining in the robots's turn, in radians. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the robot is currently turning to the right. + /// Negative values means that the robot is currently turning to the left. + ///

+ public double TurnRemainingRadians + { + get { return bodyTurnRemaining; } + } + + /// + /// Returns the angle remaining in the robots's turn, in degrees. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the robot is currently turning to the right. + /// Negative values means that the robot is currently turning to the left. + ///

+ public double TurnRemaining + { + get { return Utils.ToDegrees(bodyTurnRemaining); } + } + + /// + /// Returns the angle remaining in the radar's turn, in radians. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the radar is currently turning to the right. + /// Negative values means that the radar is currently turning to the left. + ///

+ public double RadarTurnRemainingRadians + { + get { return radarTurnRemaining; } + } + + /// + /// Returns the angle remaining in the radar's turn, in degrees. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the radar is currently turning to the right. + /// Negative values means that the radar is currently turning to the left. + ///

+ public double RadarTurnRemaining + { + get { return Utils.ToDegrees(radarTurnRemaining); } + } + + /// + /// Returns the angle remaining in the gun's turn, in radians. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the gun is currently turning to the right. + /// Negative values means that the gun is currently turning to the left. + ///

+ public double GunTurnRemainingRadians + { + get { return gunTurnRemaining; } + } + + /// + /// Returns the angle remaining in the gun's turn, in degrees. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the gun is currently turning to the right. + /// Negative values means that the gun is currently turning to the left. + ///

+ public double GunTurnRemaining + { + get { return Utils.ToDegrees(gunTurnRemaining); } + } + + /// + /// Returns the distance remaining in the robot's current move measured in + /// pixels. + ///

+ /// This call returns both positive and negative values. + /// Positive values means that the robot is currently moving forwards. + /// Negative values means that the robot is currently moving backwards. + ///

+ public double DistanceRemaining + { + get { return distanceRemaining; } + } + + /// + /// Returns the current heat of the gun. The gun cannot Fire unless this is + /// 0. (Calls to Fire will succeed, but will not actually Fire unless + /// GetGunHeat() == 0). + ///

+ /// The amount of gun heat generated when the gun is fired is + /// 1 + (firePower / 5). Each turn the gun heat drops by the amount returned + /// by , which is a battle setup. + ///

+ /// Note that all guns are "hot" at the start of each round, where the gun + /// heat is 3. + ///

+ /// + /// + /// + public double GunHeat + { + get { return gunHeat; } + } + + /// + /// Returns how many opponents that are left in the current round. + /// + public int Others + { + get { return others; } + } + + /// + /// Returns how many sentry robots that are left in the current round. + /// + public int NumSentries + { + get { return numSentries; } + } + + /// + /// Returns the number of rounds in the current battle. + /// + /// + public int NumRounds + { + get { return numRounds; } + } + + /// + /// Returns the current round number (0 to - 1) of + /// the battle. + /// + /// + public int RoundNum + { + get { return roundNum; } + } + + /// + /// Returns the game time of the round, where the time is equal to the current turn in the round. + /// + public long Time + { + get { return time; } + } + + private RobotStatus(double energy, double x, double y, double bodyHeading, double gunHeading, + double radarHeading, + double velocity, double bodyTurnRemaining, double radarTurnRemaining, + double gunTurnRemaining, + double distanceRemaining, double gunHeat, + int others, int numSentries, + int roundNum, int numRounds, long time) + { + this.energy = energy; + this.x = x; + this.y = y; + this.bodyHeading = bodyHeading; + this.gunHeading = gunHeading; + this.radarHeading = radarHeading; + this.bodyTurnRemaining = bodyTurnRemaining; + this.velocity = velocity; + this.radarTurnRemaining = radarTurnRemaining; + this.gunTurnRemaining = gunTurnRemaining; + this.distanceRemaining = distanceRemaining; + this.gunHeat = gunHeat; + this.others = others; + this.numSentries = numSentries; + this.roundNum = roundNum; + this.numRounds = numRounds; + this.time = time; + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN, IHiddenStatusHelper + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + 12*RbSerializerN.SIZEOF_DOUBLE + 4*RbSerializerN.SIZEOF_INT + + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (RobotStatus) objec; + + serializer.serialize(buffer, obj.energy); + serializer.serialize(buffer, obj.x); + serializer.serialize(buffer, obj.y); + serializer.serialize(buffer, obj.bodyHeading); + serializer.serialize(buffer, obj.gunHeading); + serializer.serialize(buffer, obj.radarHeading); + serializer.serialize(buffer, obj.velocity); + serializer.serialize(buffer, obj.bodyTurnRemaining); + serializer.serialize(buffer, obj.radarTurnRemaining); + serializer.serialize(buffer, obj.gunTurnRemaining); + serializer.serialize(buffer, obj.distanceRemaining); + serializer.serialize(buffer, obj.gunHeat); + serializer.serialize(buffer, obj.others); + serializer.serialize(buffer, obj.numSentries); + serializer.serialize(buffer, obj.roundNum); + serializer.serialize(buffer, obj.numRounds); + serializer.serialize(buffer, obj.time); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + double energy = buffer.getDouble(); + double x = buffer.getDouble(); + double y = buffer.getDouble(); + double bodyHeading = buffer.getDouble(); + double gunHeading = buffer.getDouble(); + double radarHeading = buffer.getDouble(); + double velocity = buffer.getDouble(); + double bodyTurnRemaining = buffer.getDouble(); + double radarTurnRemaining = buffer.getDouble(); + double gunTurnRemaining = buffer.getDouble(); + double distanceRemaining = buffer.getDouble(); + double gunHeat = buffer.getDouble(); + int others = buffer.getInt(); + int numSentries = buffer.getInt(); + int roundNum = buffer.getInt(); + int numRounds = buffer.getInt(); + long time = buffer.getLong(); + + return new RobotStatus(energy, x, y, bodyHeading, gunHeading, radarHeading, velocity, bodyTurnRemaining, + radarTurnRemaining, gunTurnRemaining, distanceRemaining, gunHeat, others, numSentries, + roundNum, numRounds, time); + } + + public RobotStatus createStatus(double energy, double x, double y, double bodyHeading, double gunHeading, + double radarHeading, double velocity, double bodyTurnRemaining, + double radarTurnRemaining, double gunTurnRemaining, double distanceRemaining, + double gunHeat, int others, int numSentries, int roundNum, int numRounds, long time) + { + return new RobotStatus(energy, x, y, bodyHeading, gunHeading, radarHeading, velocity, bodyTurnRemaining, + radarTurnRemaining, gunTurnRemaining, distanceRemaining, gunHeat, others, numSentries, + roundNum, numRounds, time); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RoundEndedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RoundEndedEvent.cs new file mode 100644 index 0000000..5554c77 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/RoundEndedEvent.cs @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A RoundEndedEvent is sent to when a round has ended. + /// You can use the information contained in this event to determine which round that has ended. + /// + /// + public class RoundEndedEvent : Event + { + private const int DEFAULT_PRIORITY = 110; // System event -> cannot be changed! + + private readonly int round; + private readonly int turns; + private readonly int totalTurns; + + + /// + /// Called by the game to create a new RoundEndedEvent. + /// + /// The round that has ended (zero-indexed) + /// The number of turns that this round reached + /// The total number of turns reached in the battle when this round ended + public RoundEndedEvent(int round, int turns, int totalTurns) + { + this.round = round; + this.turns = turns; + this.totalTurns = totalTurns; + } + + /// + /// The round that ended (zero-indexed). + /// + public int Round + { + get { return round; } + } + + /// + /// The number of turns that this round reached. + /// + public int Turns + { + get { return turns; } + } + + /// + /// The total number of turns reached in the battle when this round ended. + /// + public int TotalTurns + { + get { return totalTurns; } + } + + internal override sealed int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + /// + public override sealed int Priority + { + get { return DEFAULT_PRIORITY; } + } + + internal override sealed void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (robot != null) + { + IBasicEvents3 listener = robot.GetBasicEventListener() as IBasicEvents3; + + + if (listener != null) + { + listener.OnRoundEnded(this); + } + } + } + + internal override sealed bool IsCriticalEvent + { + get { return true; } + } + + internal override byte SerializationType + { + get { return RbSerializerN.RoundEndedEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, Object obje) + { + return RbSerializerN.SIZEOF_TYPEINFO + 3*RbSerializerN.SIZEOF_INT; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, Object obje) + { + RoundEndedEvent evnt = (RoundEndedEvent) obje; + + serializer.serialize(buffer, evnt.round); + serializer.serialize(buffer, evnt.turns); + serializer.serialize(buffer, evnt.totalTurns); + } + + public Object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int round = serializer.deserializeInt(buffer); + int turns = serializer.deserializeInt(buffer); + int totalTurns = serializer.deserializeInt(buffer); + + return new RoundEndedEvent(round, turns, totalTurns); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Rules.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Rules.cs new file mode 100644 index 0000000..50af6b4 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Rules.cs @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using Robocode.Util; + +namespace Robocode +{ + /// + /// Constants and methods that defines the rules of Robocode. + /// Constants are used for rules that will not change. + /// Methods are provided for rules that can be changed between battles or which depends + /// on some other factor. + /// + public static class Rules + { + // Hide the constructor in the docs as it should not be used + + /// + /// The acceleration of a robot, i.e. the increase of velocity when the + /// robot moves forward, which is 1 pixel/turn. + /// + public static readonly double ACCELERATION = 1; + + /// + /// The deceleration of a robot, i.e. the decrease of velocity when the + /// robot moves backwards (or brakes), which is 2 pixels/turn. + /// + public static readonly double DECELERATION = 2; + + /// + /// The maximum velocity of a robot, which is 8 pixels/turn. + /// + public static readonly double MAX_VELOCITY = 8; + + /// + /// The radar scan radius, which is 1200 pixels. + /// Robots which is more than 1200 pixels away cannot be seen on the radar. + /// + public static readonly double RADAR_SCAN_RADIUS = 1200; + + /// + /// The minimum bullet power, i.e the amount of energy required for firing a + /// bullet, which is 0.1 energy points. + /// + public static readonly double MIN_BULLET_POWER = 0.1; + + /// + /// The maximum bullet power, i.e. the maximum amount of energy that can be + /// transferred to a bullet when it is fired, which is 3 energy points. + /// + public static readonly double MAX_BULLET_POWER = 3; + + /// + /// The maximum turning rate of the robot, in degrees, which is + /// 10 degress/turn. + /// Note, that the turn rate of the robot depends on it's velocity. + /// + /// + /// + /// + public static readonly double MAX_TURN_RATE = 10; + + /// + /// The maximum turning rate of the robot measured in radians instead of + /// degrees. + /// + /// + /// + /// + /// + public static readonly double MAX_TURN_RATE_RADIANS = Utils.ToRadians(MAX_TURN_RATE); + + /// + /// The turning rate of the gun measured in degrees, which is 20 degrees/turn. + /// Note, that if AdjustGunForRobotTurn = true has been set, the gun turn is + /// independent of the robot turn. In this case the gun moves relatively to the screen. + ///

+ /// If AdjustGunForRobotTurn = false has been set or AdjustGunForRobotTurn has not + /// been called at all (this is the default), then the gun turn is dependent on + /// the robot turn, and in this case the gun moves relatively to the robot body. + /// + /// + /// + ///

+ public static readonly double GUN_TURN_RATE = 20; + + /// + /// The turning rate of the gun measured in radians instead of degrees. + /// + /// + /// + public static readonly double GUN_TURN_RATE_RADIANS = Utils.ToRadians(GUN_TURN_RATE); + + /// + /// The turning rate of the radar measured in degrees, which is 45 degrees/turn. + /// Note, that if AdjustRadarForRobotTurn = true and/or + /// AdjustRadarForGunTurn = true has been set, the radar turn is independent of + /// the robot and/or gun turn. If both properties hava been set to true, the radar + /// moves relatively to the screen. + ///

+ /// If AdjustRadarForRobotTurn = false and/or AdjustRadarForGunTurn = false + /// have been set or not set at all (this is the default), then the radar turn is + /// dependent on the robot and/or gun turn, and in this case the radar moves + /// relatively to the gun and/or robot body. + /// + /// + /// + /// + ///

+ public static readonly double RADAR_TURN_RATE = 45; + + /// + /// The turning rate of the radar measured in radians instead of degrees. + /// + /// + /// + public static readonly double RADAR_TURN_RATE_RADIANS = Utils.ToRadians(RADAR_TURN_RATE); + + /// + /// The amount of damage taken when a robot hits or is hit by another robot, + /// which is 0.6 energy points. + /// + public static readonly double ROBOT_HIT_DAMAGE = 0.6; + + /// + /// The amount of bonus given when a robot moving forward hits an opponent + /// robot (ramming), which is 1.2 energy points. + /// + public static readonly double ROBOT_HIT_BONUS = 1.2; + + /// + /// Returns the turn rate of a robot given a specific velocity measured in + /// degrees/turn. + /// + /// + /// The velocity of the robot. + public static double GetTurnRate(double velocity) + { + return MAX_TURN_RATE - 0.75*velocity; + } + + /// + /// Returns the turn rate of a robot given a specific velocity measured in + /// radians/turn. + /// + /// + /// the velocity of the robot. + public static double GetTurnRateRadians(double velocity) + { + return Utils.ToRadians(GetTurnRate(velocity)); + } + + /// + /// Returns the amount of damage taken when robot hits a wall with a + /// specific velocity. + /// + /// the velocity of the robot. + public static double GetWallHitDamage(double velocity) + { + return Math.Max(Math.Abs(velocity)/2 - 1, 0); + } + + /// + /// Returns the amount of damage of a bullet given a specific bullet power. + /// + /// the energy power of the bullet. + public static double GetBulletDamage(double bulletPower) + { + double damage = 4*bulletPower; + + if (bulletPower > 1) + { + damage += 2*(bulletPower - 1); + } + return damage; + } + + /// + /// Returns the amount of bonus given when a robot's bullet hits an opponent + /// robot given a specific bullet power. + /// + /// the energy power of the bullet + public static double GetBulletHitBonus(double bulletPower) + { + return 3*bulletPower; + } + + /// + /// Returns the speed of a bullet given a specific bullet power measured in + /// pixels/turn. + /// + /// the energy power of the bullet. + public static double GetBulletSpeed(double bulletPower) + { + bulletPower = Math.Min(Math.Max(bulletPower, MIN_BULLET_POWER), MAX_BULLET_POWER); + return 20 - 3 * bulletPower; + } + + /// + /// Returns the heat produced by firing the gun given a specific bullet power. + /// + /// the energy power of the bullet + public static double GetGunHeat(double bulletPower) + { + return 1 + (bulletPower/5); + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/ScannedRobotEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/ScannedRobotEvent.cs new file mode 100644 index 0000000..c76ff49 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/ScannedRobotEvent.cs @@ -0,0 +1,238 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A ScannedRobotEvent is sent to + /// OnScannedRobot()} when you scan a robot. + /// You can use the information contained in this event to determine what to do. + ///

+ /// Note: You should not inherit from this class in your own event class! + /// The internal logic of this event class might change. Hence, your robot might + /// not work in future Robocode versions, if you choose to inherit from this class. + ///

+ public class ScannedRobotEvent : Event + { + private const int DEFAULT_PRIORITY = 10; + + private readonly string name; + private readonly double energy; + private readonly double heading; + private readonly double bearing; + private readonly double distance; + private readonly double velocity; + private readonly bool isSentryRobot; + + [Obsolete("ScannedRobotEvent() is obsolete.\n" + + "Please use ScannedRobotEvent(string, double, double, double, double, double, bool) instead.")] + internal ScannedRobotEvent() + : this(null, 0, 0, 0, 0, 0, false) + { + } + + /// + /// Called by the game to create a new ScannedRobotEvent. + /// + /// The name of the scanned robot + /// The energy of the scanned robot + /// The bearing of the scanned robot, in radians + /// The distance from your robot to the scanned robot + /// The heading of the scanned robot + /// The velocity of the scanned robot + [Obsolete("ScannedRobotEvent(string, double, double, double, double, double) is obsolete.\n" + + "Please use ScannedRobotEvent(string, double, double, double, double, double, bool) instead.")] + public ScannedRobotEvent(string name, double energy, double bearing, double distance, double heading, double velocity) : + this(name, energy, bearing, distance, heading, velocity, false) + { + } + + /// + /// Called by the game to create a new ScannedRobotEvent. + /// + /// The name of the scanned robot + /// The energy of the scanned robot + /// The bearing of the scanned robot, in radians + /// The distance from your robot to the scanned robot + /// The heading of the scanned robot + /// The velocity of the scanned robot + /// Flag specifying if the scanned robot is a sentry robot + public ScannedRobotEvent(string name, double energy, double bearing, double distance, double heading, double velocity, bool isSentryRobot) + { + this.name = name; + this.energy = energy; + this.bearing = bearing; + this.distance = distance; + this.heading = heading; + this.velocity = velocity; + this.isSentryRobot = isSentryRobot; + } + + /// + /// Returns the bearing to the robot you scanned, relative to your robot's + /// heading, in degrees (-180 <= getBearing() < 180) + /// + public double Bearing + { + get { return bearing*180.0/Math.PI; } + } + + /// + /// Returns the bearing to the robot you scanned, relative to your robot's + /// heading, in radians (-PI <= getBearingRadians() < PI) + /// + public double BearingRadians + { + get { return bearing; } + } + + /// + /// Returns the distance to the robot (your center to his center). + /// + public double Distance + { + get { return distance; } + } + + /// + /// Returns the energy of the robot. + /// + public double Energy + { + get { return energy; } + } + + /// + /// Returns the heading of the robot, in degrees (0 <= getHeading() < 360) + /// + public double Heading + { + get { return heading*180.0/Math.PI; } + } + + /// + /// Returns the heading of the robot, in radians (0 <= getHeading() < 2 * PI) + /// + public double HeadingRadians + { + get { return heading; } + } + + + /// + /// Returns the name of the robot. + /// + public string Name + { + get { return name; } + } + + + /// + /// Returns the velocity of the robot. + /// + public double Velocity + { + get { return velocity; } + } + + /// + /// true if the scanned robot is a sentry robot; false otherwise. + /// + public bool IsSentryRobot + { + get { return isSentryRobot; } + } + + /// + public override sealed int CompareTo(Event evnt) + { + int res = base.CompareTo(evnt); + + if (res != 0) + { + return res; + } + // Compare the distance, if the events are ScannedRobotEvents + // The shorter distance to the robot, the higher priority + if (evnt is ScannedRobotEvent) + { + return (int) (Distance - ((ScannedRobotEvent) evnt).Distance); + } + // No difference found + return 0; + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnScannedRobot(this); + } + } + + internal override byte SerializationType + { + get { return RbSerializerN.ScannedRobotEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + var obj = (ScannedRobotEvent) objec; + + return RbSerializerN.SIZEOF_TYPEINFO + serializer.sizeOf(obj.name) + 5 * RbSerializerN.SIZEOF_DOUBLE + RbSerializerN.SIZEOF_BOOL; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (ScannedRobotEvent) objec; + + serializer.serialize(buffer, obj.name); + serializer.serialize(buffer, obj.energy); + serializer.serialize(buffer, obj.heading); + serializer.serialize(buffer, obj.bearing); + serializer.serialize(buffer, obj.distance); + serializer.serialize(buffer, obj.velocity); + serializer.serialize(buffer, obj.isSentryRobot); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + string name = serializer.deserializeString(buffer); + double energy = buffer.getDouble(); + double heading = buffer.getDouble(); + double bearing = buffer.getDouble(); + double distance = buffer.getDouble(); + double velocity = buffer.getDouble(); + bool isSentryRobot = serializer.deserializeBoolean(buffer); + + return new ScannedRobotEvent(name, energy, bearing, distance, heading, velocity, isSentryRobot); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/SkippedTurnEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/SkippedTurnEvent.cs new file mode 100644 index 0000000..a0aaef0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/SkippedTurnEvent.cs @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// A SkippedTurnEvent is sent to + /// OnSkippedTurn()} when your robot is forced to skipping a turn. + /// You must take an action every turn in order to participate in the game. + /// + /// + /// Thread.Sleep(1000); + /// + /// will cause many SkippedTurnEvents, because you are not responding to the game. + /// If you receive 30 SkippedTurnEvents, you will be removed from the round. + ///

+ /// Instead, you should do something such as: + /// + /// for (int i = 0; i < 30; i++) + /// { + /// DoNothing(); // or perhaps Scan(); + /// } + /// + /// + ///

+ /// This event may also be generated if you are simply doing too much processing + /// between actions, that is using too much processing power for the calculations + /// etc. in your robot. + /// + /// + ///

+ public sealed class SkippedTurnEvent : Event + { + private const int DEFAULT_PRIORITY = 100; // System event -> cannot be changed!; + + private readonly long skippedTurn; + + /// + /// Called by the game to create a new SkippedTurnEvent. + /// + public SkippedTurnEvent(long skippedTurn) + { + this.skippedTurn = skippedTurn; + } + + /// + /// Returns the turn that was skipped. + /// + public long SkippedTurn + { + get { return skippedTurn; } + } + + /// + public override int Priority + { + get { return DEFAULT_PRIORITY; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + if (statics.IsAdvancedRobot()) + { + IAdvancedEvents listener = ((IAdvancedRobot) robot).GetAdvancedEventListener(); + + if (listener != null) + { + listener.OnSkippedTurn(this); + } + } + } + + internal override bool IsCriticalEvent + { + get { return true; } + } + + internal override byte SerializationType + { + get { return RbSerializerN.SkippedTurnEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_LONG; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + var obj = (SkippedTurnEvent)objec; + + serializer.serialize(buffer, obj.skippedTurn); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + long skippedTurn = buffer.getLong(); + + return new SkippedTurnEvent(skippedTurn); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/StatusEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/StatusEvent.cs new file mode 100644 index 0000000..84bac6a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/StatusEvent.cs @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.peer; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// This event is sent to every + /// turn in a battle to provide the status of the robot. + /// + [Serializable] + public sealed class StatusEvent : Event + { + private const int DEFAULT_PRIORITY = 99; + + private readonly RobotStatus status; + + /// + /// This constructor is called internally from the game in order to create + /// a new . + /// + /// + /// the current states + public StatusEvent(RobotStatus status) + { + this.status = status; + } + + /// + /// Returns the at the time defined by . + /// + /// + public RobotStatus Status + { + get { return status; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnStatus(this); + } + } + + internal override byte SerializationType + { + get { throw new System.Exception("Serialization of this type is not supported"); } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/TeamRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/TeamRobot.cs new file mode 100644 index 0000000..bfa6eda --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/TeamRobot.cs @@ -0,0 +1,193 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Collections.Generic; +using Robocode.RobotInterfaces; +using Robocode.RobotInterfaces.Peer; + +namespace Robocode +{ + /// + /// An advanced type of robot that supports sending messages between team + /// mates in a robot team. + ///

+ /// If you have not done already, you should create a or + /// first. + /// + /// + /// + /// + /// + /// + ///

+ public abstract class TeamRobot : AdvancedRobot, ITeamRobot, ITeamEvents + { + + /// + /// Broadcasts a message to all teammates. + ///

+ /// + /// + /// public void Run() + /// { + /// BroadcastMessage("I'm here!"); + /// } + /// + /// + ///

+ /// The message to broadcast to all teammates + /// if the message could not be broadcasted to the teammates. + /// + /// + /// + /// + public void BroadcastMessage(object message) + { + if (peer != null) + { + ((ITeamRobotPeer) peer).BroadcastMessage(message); + } + else + { + UninitializedException(); + } + } + + /// + /// Returns a list containing all MessageEvents currently in the robot's queue. + /// You might, for example, call this while processing another event. + ///

+ /// + /// + /// foreach (MessageEvent e in GetMessageEvents()) + /// { + /// // do something with e + /// } + /// + /// + /// + /// + ///

+ public IList GetMessageEvents() + { + if (peer != null) + { + return new List(((ITeamRobotPeer) peer).GetMessageEvents()); + } + UninitializedException(); + return null; // never called + } + + /// + ITeamEvents ITeamRobot.GetTeamEventListener() + { + return this; // this robot is listening + } + + /// + /// Returns the names of all teammates, or null there is no teammates. + /// The length of the string array is equal to the number of teammates. + ///

+ /// + /// + /// public void Run() + /// { + /// // Prints Out all teammates + /// string[] teammates = GetTeammates(); + /// if (teammates != null) + /// { + /// foreach (string member in teammates) + /// { + /// Out.WriteLine(member); + /// } + /// } + /// } + /// + /// + /// + /// + /// + ///

+ public string[] Teammates + { + get + { + if (peer != null) + { + return ((ITeamRobotPeer) peer).GetTeammates(); + } + UninitializedException(); + return null; + } + } + + /// + /// Checks if a given robot name is the name of one of your teammates. + ///

+ /// + /// + /// public void OnScannedRobot(ScannedRobotEvent e) + /// { + /// if (IsTeammate(e.Name) + /// { + /// return; + /// } + /// Fire(1); + /// } + /// + /// + /// + /// + /// + ///

+ /// The robot name to check + public bool IsTeammate(string name) + { + if (peer != null) + { + return ((ITeamRobotPeer) peer).IsTeammate(name); + } + UninitializedException(); + return false; + } + + /// + public virtual void OnMessageReceived(MessageEvent evnt) + { + } + + /// + /// Sends a message to one (or more) teammates. + ///

+ /// + /// + /// public void Run() + /// { + /// SendMessage("Sample.DroidBot", "I'm here!"); + /// } + /// + /// + /// + /// + /// + ///

+ /// The name of the intended recipient of the message + /// The message to send + public void SendMessage(string name, object message) + { + if (peer != null) + { + ((ITeamRobotPeer) peer).SendMessage(name, message); + } + else + { + UninitializedException(); + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Thread.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Thread.cs new file mode 100644 index 0000000..3bcdfdd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/Thread.cs @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Threading; +using net.sf.robocode.io; +using net.sf.robocode.security; + +namespace Robocode +{ + /// + /// Wrapper for .NET Thread, secured according to robocode rules. + /// + public class Thread + { + private static readonly object syncRoot=new object(); + private static int runningCounter; + + private readonly System.Threading.Thread thread; + private readonly ParameterizedThreadStart real1; + private readonly ThreadStart real2; + + /// + /// Initializes a new instance of the Thread class + /// + /// A ThreadStart delegate that represents the methods to be invoked when this thread begins executing. + public Thread(ParameterizedThreadStart start) + { + if (start == null) + { + throw new ArgumentException("start"); + } + int id = CheckCount(); + real1 = start; + thread = new System.Threading.Thread(main); + string name = (string) AppDomain.CurrentDomain.GetData("robotName"); + if (!string.IsNullOrEmpty(name)) + { + thread.Name = name + " [" + id + "]"; + } + } + + /// + /// Initializes a new instance of the Thread class + /// + /// A ThreadStart delegate that represents the methods to be invoked when this thread begins executing. + public Thread(ThreadStart start) + { + if (start==null) + { + throw new ArgumentException("start"); + } + int id = CheckCount(); + real2 = start; + thread = new System.Threading.Thread(main); + string name = (string)AppDomain.CurrentDomain.GetData("robotName"); + if (!string.IsNullOrEmpty(name)) + { + thread.Name = name + " [" + id + "]"; + } + } + + private static int CheckCount() + { + lock (syncRoot) + { + if (runningCounter > 5) + { + string message = "Preventing " + HiddenAccessN.GetRobotName() + "from thread creation. You may only create 5 threads at same time."; + LoggerN.logError(message); + LoggerN.WriteLineToRobotsConsole(message); + throw new AccessViolationException(message); + } + runningCounter++; + return runningCounter; + } + } + + /// + /// Blocks the current thread for the specified number of milliseconds. + /// + public static void Sleep(int millisecondsTimeout) + { + System.Threading.Thread.Sleep(millisecondsTimeout); + } + + /// + /// Causes a thread to be scheduled for execution. + /// + public void Start(object param) + { + thread.Start(param); + } + + /// + /// Causes a thread to be scheduled for execution. + /// + public void Start() + { + thread.Start(null); + } + + private void main(object param) + { + try + { + if (real1!=null) + { + real1.Invoke(param); + } + real2.Invoke(); + } + catch (System.Exception ex) + { + Console.WriteLine("Undandled exception on thread " + thread.Name); + Console.WriteLine(ex); + } + finally + { + lock (syncRoot) + { + runningCounter--; + } + } + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/TurnCompleteCondition.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/TurnCompleteCondition.cs new file mode 100644 index 0000000..4a5af67 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/TurnCompleteCondition.cs @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode +{ + /// + /// A prebuilt condition you can use that indicates your robot has finished turning. + /// + /// + public class TurnCompleteCondition : Condition + { + private readonly AdvancedRobot robot; + + /// + /// Creates a new TurnCompleteCondition with default priority. + /// The default priority is 80. + /// + /// Your robot, which must be an + public TurnCompleteCondition(AdvancedRobot robot) + { + this.robot = robot; + } + + /// + /// Creates a new TurnCompleteCondition with the specified priority. + /// A condition priority is a value from 0 - 99. The higher value, the + /// higher priority. The default priority is 80. + /// + /// Your robot, which must be an + /// The priority of this condition + /// + public TurnCompleteCondition(AdvancedRobot robot, int priority) + { + this.robot = robot; + this.priority = priority; + } + + /// + /// Tests if the robot has finished turning. + /// Returns true if the robot has stopped turning; false otherwise + /// + public override bool Test() + { + return (robot.TurnRemaining == 0); + } + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/WinEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/WinEvent.cs new file mode 100644 index 0000000..2cd83be --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/WinEvent.cs @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.serialization; +using Robocode.RobotInterfaces; + +namespace Robocode +{ + /// + /// This event is sent to when your robot + /// wins the round in a battle. + /// + [Serializable] + public sealed class WinEvent : Event + { + private const int DEFAULT_PRIORITY = 100; // System event -> cannot be changed!; + + /// + public override int Priority + { + get { return DEFAULT_PRIORITY; } + } + + internal override int DefaultPriority + { + get { return DEFAULT_PRIORITY; } + } + + internal override void Dispatch(IBasicRobot robot, IRobotStaticsN statics, IGraphics graphics) + { + IBasicEvents listener = robot.GetBasicEventListener(); + + if (listener != null) + { + listener.OnWin(this); + } + } + + internal override bool IsCriticalEvent + { + get { return true; } + } + + internal override byte SerializationType + { + get { return RbSerializerN.WinEvent_TYPE; } + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + private class SerializableHelper : ISerializableHelperN + { + public int sizeOf(RbSerializerN serializer, object objec) + { + return RbSerializerN.SIZEOF_TYPEINFO; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object objec) + { + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + return new WinEvent(); + } + } + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/exception/EventInterruptedException.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/exception/EventInterruptedException.cs new file mode 100644 index 0000000..b7891db --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/exception/EventInterruptedException.cs @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Runtime.Serialization; + +namespace Robocode.Exception +{ + /// + [Serializable] + public class EventInterruptedException : System.Exception + { + private readonly int priority = int.MinValue; + + /// + /// Used by game + /// + public EventInterruptedException(int priority) + { + this.priority = priority; + } + + /// + /// Last top priority + /// + public int Priority + { + get + { + return priority; + } + } + + /// + /// Serialization constructor + /// + protected EventInterruptedException(SerializationInfo info, StreamingContext context) : + base(info, context) + { + } + + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/exception/RobotException.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/exception/RobotException.cs new file mode 100644 index 0000000..4d37cf6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/exception/RobotException.cs @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Runtime.Serialization; + +namespace Robocode.Exception +{ + /// + /// Throw this exception to stop robot + /// + /// + [Serializable] + public class RobotException : System.Exception + { + /// + /// Default constructor + /// + public RobotException() + { + } + + /// + /// Constructor with message + /// + public RobotException(string s) + : base(s) + { + } + + /// + /// Deserialization constructor + /// + protected RobotException(SerializationInfo info, StreamingContext context) : + base(info, context) + { + } + + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IAdvancedEvents.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IAdvancedEvents.cs new file mode 100644 index 0000000..e7579e1 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IAdvancedEvents.cs @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace Robocode.RobotInterfaces +{ + /// + /// An event interface for receiving advanced robot events with an + /// + /// + /// + public interface IAdvancedEvents + { + /// + /// This method is called if the robot is using too much time between + /// actions. When this event occur, the robot's turn is skipped, meaning that + /// it cannot take action anymore in this turn. + ///

+ /// If you receive 30 skipped turn event, your robot will be removed from the + /// round and loose the round. + ///

+ /// You will only receive this event after taking an action. So a robot in an + /// infinite loop will not receive any events, and will simply be stopped. + ///

+ /// No correctly working, reasonable robot should ever receive this event + /// unless it is using too many CPU cycles. + /// + /// + ///

+ /// The skipped turn event set by the game + void OnSkippedTurn(SkippedTurnEvent evnt); + + /// + /// This method is called when a custom condition is met. + ///

+ /// See the sample robots for examples of use, e.g. the Sample.Target + /// robot. + /// + /// + /// + ///

+ /// The custom event that occurred + void OnCustomEvent(CustomEvent evnt); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IAdvancedRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IAdvancedRobot.cs new file mode 100644 index 0000000..392ab8d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IAdvancedRobot.cs @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode.RobotInterfaces +{ + /// + /// A robot interface for creating a more advanced type of robot like + /// that is able to handle advanced robot events. + /// An advanced robot allows non-blocking calls, custom events, get notifications + /// about skipped turns, and also allow writes to the file system. + /// + /// + /// + /// + /// + /// + public interface IAdvancedRobot : IBasicRobot + { + /// + /// This method is called by the game to notify this robot about advanced + /// robot event. Hence, this method must be implemented so it returns your + /// listener. + /// + IAdvancedEvents GetAdvancedEventListener(); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents.cs new file mode 100644 index 0000000..2d15b9c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents.cs @@ -0,0 +1,270 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace Robocode.RobotInterfaces +{ + /// + /// An event interface for receiving basic robot events with an + /// . + /// + /// + public interface IBasicEvents + { + /// + /// This method is called every turn in a battle round in order to provide + /// the robot status as a complete snapshot of the robot's current state at + /// that specific time. + ///

+ /// The main benefit of this method is that you'll automatically receive all + /// current data values of the robot like e.g. the x and y coordinate, + /// heading, gun heat etc., which are grouped into the exact same time/turn. + ///

+ /// This is the only way to map the robots data values to a specific time. + /// For example, it is not possible to determine the exact time of the + /// robot's heading by calling first calling and then + /// afterwards, as the time might change + /// after between the and + /// call. + /// + /// + ///

+ void OnStatus(StatusEvent evnt); + + /// + /// This method is called when one of your bullets hits another robot. + /// You should override it in your robot if you want to be informed of this + /// event. + ///

+ /// + /// + /// public void OnBulletHit(BulletHitEvent evnt) + /// { + /// Out.WriteLine("I hit " + evnt.Name + "!"); + /// } + /// + /// + /// + /// + ///

+ void OnBulletHit(BulletHitEvent evnt); + + /// + /// This method is called when one of your bullets hits another bullet. + /// You should override it in your robot if you want to be informed of this + /// event. + ///

+ /// + /// + /// public void OnBulletHitBullet(BulletHitBulletEvent evnt) + /// { + /// Out.WriteLine("I hit a bullet fired by " + evnt.Bullet.Name + "!"); + /// } + /// + /// + /// + /// + ///

+ void OnBulletHitBullet(BulletHitBulletEvent evnt); + + /// + /// This method is called when one of your bullets misses, i.e. hits a wall. + /// You should override it in your robot if you want to be informed of this + /// event. + ///

+ /// + /// + /// public void OnBulletMissed(BulletMissedEvent evnt) + /// { + /// Out.WriteLine("Drat, I missed."); + /// } + /// + /// + /// + /// + ///

+ void OnBulletMissed(BulletMissedEvent evnt); + + /// + /// This method is called if your robot dies. + ///

+ /// You should override it in your robot if you want to be informed of this + /// event. Actions will have no effect if called from this section. The + /// intent is to allow you to perform calculations or print something out + /// when the robot is killed. + /// + /// + /// + /// + ///

+ void OnDeath(DeathEvent evnt); + + /// + /// This method is called when your robot is hit by a bullet. + /// You should override it in your robot if you want to be informed of this + /// event. + ///

+ /// + /// + /// void OnHitByBullet(HitByBulletEvent evnt) + /// { + /// Out.WriteLine(event.RobotName + " hit me!"); + /// } + /// + /// + /// + /// + ///

+ void OnHitByBullet(HitByBulletEvent evnt); + + /// + /// This method is called when your robot collides with another robot. + /// You should override it in your robot if you want to be informed of this + /// event. + ///

+ /// + /// + /// void OnHitRobot(HitRobotEvent evnt) + /// { + /// if (event.Bearing > -90 && evnt.Bearing <= 90) + /// { + /// Back(100); + /// } + /// else + /// { + /// Ahead(100); + /// } + /// } + /// + /// -- or perhaps, for a more advanced robot -- + /// + /// public void OnHitRobot(HitRobotEvent evnt) + /// { + /// if (event.Bearing > -90 && evnt.Bearing <= 90) + /// { + /// SetBack(100); + /// } + /// else + /// { + /// SetAhead(100); + /// } + /// } + /// + /// + ///

+ /// The angle is relative to your robot's facing. So 0 is straight ahead of + /// you. + ///

+ /// This event can be generated if another robot hits you, in which case + /// will return false. + /// In this case, you will not be automatically stopped by the game -- + /// but if you continue moving toward the robot you will hit it (and + /// generate another event). If you are moving away, then you won't hit it. + /// + /// + ///

+ void OnHitRobot(HitRobotEvent evnt); + + /// + /// This method is called when your robot collides with a wall. + /// You should override it in your robot if you want to be informed of this + /// event. + ///

+ /// The wall at the top of the screen is 0 degrees, right is 90 degrees, + /// bottom is 180 degrees, left is 270 degrees. But this event is relative to + /// your heading, so: The bearing is such that + /// will point you perpendicular to the wall. + ///

+ /// + /// + /// void OnHitWall(HitWallEvent evnt) + /// { + /// Out.WriteLine("Ouch, I hit a wall bearing " + evnt.Bearing + " degrees."); + /// } + /// + /// + /// + /// + ///

+ void OnHitWall(HitWallEvent evnt); + + /// + /// This method is called when your robot sees another robot, i.e. when the + /// robot's radar scan "hits" another robot. + /// You should override it in your robot if you want to be informed of this + /// event. (Almost all robots should override this!) + ///

+ /// This event is automatically called if there is a robot in range of your + /// radar. + ///

+ /// Note that the robot's radar can only see robot within the range defined + /// by (1200 pixels). + ///

+ /// Also not that the bearing of the scanned robot is relative to your + /// robot's heading. + ///

+ /// + /// + /// void OnScannedRobot(ScannedRobotEvent evnt) + /// { + /// // Assuming radar and gun are aligned... + /// if (event.Distance < 100) + /// { + /// Fire(3); + /// } + /// else + /// { + /// Fire(1); + /// } + /// } + /// + /// + ///

+ /// Note:
+ /// The game assists Robots in firing, as follows: + ///

    + ///
  • If the gun and radar are aligned (and were aligned last turn),
  • + ///
  • and the event is current,
  • + ///
  • and you call Fire() before taking any other actions, Robot.Fire(double) will Fire directly at the robot.
  • + ///
+ ///

+ /// In essence, this means that if you can see a robot, and it doesn't move, + /// then Fire will hit it. + ///

+ /// AdvancedRobots will NOT be assisted in this manner, and are expected to + /// examine the event to determine if would + /// hit. (i.e. you are spinning your gun around, but by the time you get the + /// event, your gun is 5 degrees past the robot). + /// + /// + /// + ///

+ void OnScannedRobot(ScannedRobotEvent evnt); + + /// + /// This method is called when another robot dies. + /// You should override it in your robot if you want to be informed of this + /// event. + /// + /// + /// + void OnRobotDeath(RobotDeathEvent evnt); + + /// + /// This method is called if your robot wins a battle. + ///

+ /// Your robot could perform a victory dance here! :-) + /// + /// + /// + ///

+ void OnWin(WinEvent evnt); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents2.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents2.cs new file mode 100644 index 0000000..e08397c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents2.cs @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace Robocode.RobotInterfaces +{ + /// + /// First extended version of the interface. + /// + public interface IBasicEvents2 : IBasicEvents + { + /// + /// This method is called after end of the battle, even when the battle is aborted. + /// You should override it in your robot if you want to be informed of this event. + ///

+ /// + /// + /// public void OnBattleEnded(BattleEndedEvent evnt) + /// { + /// Out.WriteLine("The battle has ended"); + /// } + /// + /// + /// + /// + /// + /// + ///

+ void OnBattleEnded(BattleEndedEvent evnt); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents3.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents3.cs new file mode 100644 index 0000000..1352a47 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicEvents3.cs @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using Robocode; + +namespace Robocode.RobotInterfaces +{ + /// + /// Second extended version of the interface. + /// + public interface IBasicEvents3 : IBasicEvents2 + { + /// + /// This method is called after the end of a round. + /// You should override it in your robot if you want to be informed of this event. + ///

+ /// + /// + /// public void OnRoundEnded(RoundEndedEvent event) + /// { + /// Out.WriteLine("The round has ended"); + /// } + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + void OnRoundEnded(RoundEndedEvent evnt); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicRobot.cs new file mode 100644 index 0000000..ef3dfad --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IBasicRobot.cs @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.IO; +using Robocode.RobotInterfaces.Peer; + +namespace Robocode.RobotInterfaces +{ + /// + /// A robot interface for creating a basic type of robot like + /// that is able to receive common robot events, but not interactive events as + /// with the class. + /// A basic robot allows blocking calls only and cannot handle custom events nor + /// writes to the file system like an advanced robot. + /// + /// + /// + /// + /// + /// + public interface IBasicRobot + { + /// + /// This method is called by the game to invoke the + /// method of your robot, where the program of your robot is implemented. + /// + IRunnable GetRobotRunnable(); + + /// + /// This method is called by the game to notify this robot about basic + /// robot event. Hence, this method must be implemented so it returns your + /// listener. + /// + IBasicEvents GetBasicEventListener(); + + /// + /// Do not call this method! Your robot will simply stop interacting with + /// the game. + ///

+ /// This method is called by the game. A robot peer is the object that deals + /// with game mechanics and rules, and makes sure your robot abides by them. + ///

+ void SetPeer(IBasicRobotPeer peer); + + /// + /// Do not call this method! + ///

+ /// This method is called by the game when setting the Out stream for your + /// robot. + ///

+ void SetOut(TextWriter output); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IInteractiveEvents.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IInteractiveEvents.cs new file mode 100644 index 0000000..b49ec7e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IInteractiveEvents.cs @@ -0,0 +1,183 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace Robocode.RobotInterfaces +{ + /// + /// An event interface for receiving interactive events with an . + /// + /// + public interface IInteractiveEvents + { + /// + /// This method is called when a key has been pressed. + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// key events. + /// + /// + ///

+ /// Holds details about current event + void OnKeyPressed(KeyEvent evnt); + + /// + /// This method is called when a key has been released. + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// key events. + /// + /// + ///

+ /// Holds details about current event + void OnKeyReleased(KeyEvent evnt); + + /// + /// This method is called when a key has been typed (pressed and released). + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// key events. + /// + /// + ///

+ /// Holds details about current event + void OnKeyTyped(KeyEvent evnt); + + /// + /// This method is called when a mouse button has been clicked (pressed and + /// released). + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// mouse events. + /// + /// + /// + /// + /// + /// + /// + ///

+ /// Holds details about current event + void OnMouseClicked(MouseEvent evnt); + + /// + /// This method is called when the mouse has entered the battle view. + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// mouse events. + /// + /// + /// + /// + /// + /// + /// + ///

+ /// Holds details about current event + void OnMouseEntered(MouseEvent evnt); + + /// + /// This method is called when the mouse has exited the battle view. + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// mouse events. + /// + /// + /// + /// + /// + /// + /// + ///

+ /// Holds details about current event + void OnMouseExited(MouseEvent evnt); + + /// + /// This method is called when a mouse button has been pressed. + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// mouse events. + /// + /// + /// + /// + /// + /// + /// + ///

+ /// Holds details about current event + void OnMousePressed(MouseEvent evnt); + + /// + /// This method is called when a mouse button has been released. + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// mouse events. + /// + /// + /// + /// + /// + /// + /// + ///

+ /// Holds details about current event + void OnMouseReleased(MouseEvent evnt); + + /// + /// This method is called when the mouse has been moved. + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// mouse events. + /// + /// + /// + /// + /// + /// + /// + ///

+ /// Holds details about current event + void OnMouseMoved(MouseEvent evnt); + + /// + /// This method is called when a mouse button has been pressed and then + /// dragged. + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// mouse events. + /// + /// + /// + /// + /// + /// + /// + ///

+ /// Holds details about current event + void OnMouseDragged(MouseEvent evnt); + + /// + /// This method is called when the mouse wheel has been rotated. + ///

+ /// See the Sample.Interactive robot for an example of how to use + /// mouse events. + /// + /// + /// + /// + /// + /// + /// + ///

+ /// Holds details about current event + void OnMouseWheelMoved(MouseWheelMovedEvent evnt); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IInteractiveRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IInteractiveRobot.cs new file mode 100644 index 0000000..d2d0ad9 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IInteractiveRobot.cs @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode.RobotInterfaces +{ + /// + /// A robot interface for creating an interactive type of robot like + /// and that is able to + /// receive interactive events from the keyboard or mouse. + /// If a robot is directly inherited from this class it will behave as similar to + /// a . If you need it to behave similar to an + /// or , you should inherit from these + /// interfaces instead, as these are inherited from this interface. + /// + /// + /// + /// + /// + /// + /// + public interface IInteractiveRobot : IBasicRobot + { + /// + /// This method is called by the game to notify this robot about interactive + /// events, i.e. keyboard and mouse events. Hence, this method must be + /// implemented so it returns your listener. + /// + IInteractiveEvents GetInteractiveEventListener(); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IJuniorRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IJuniorRobot.cs new file mode 100644 index 0000000..127970e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IJuniorRobot.cs @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode.RobotInterfaces +{ + /// + /// A robot interface for creating the most primitive robot type, which is a + /// . A junior robot is simpler than the + /// class. + ///

+ /// A junior robot has a simplified model, in purpose of teaching programming + /// skills to inexperienced in programming students. + /// The simplified robot model will keep player from overwhelming of Robocode's + /// rules, programming syntax and programming concept. + ///

+ /// Instead of using getters and setters, public fields are provided for + /// receiving information like the last scanned robot, the coordinate of the + /// robot etc. + ///

+ /// All methods on a junior robot are blocking calls, i.e. they do not return + /// before their action has been completed and will at least take one turn to + /// Execute. + /// + /// + /// + /// + /// + ///

+ public interface IJuniorRobot : IBasicRobot + { + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IPaintEvents.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IPaintEvents.cs new file mode 100644 index 0000000..c423597 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IPaintEvents.cs @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace Robocode.RobotInterfaces +{ + /// + /// An event interface for receiving paint events with an . + /// + /// + public interface IPaintEvents + { + /// + /// This method is called every time the robot is painted. You should + /// override this method if you want to draw items for your robot on the + /// battle field, e.g. targets, virtual bullets etc. + ///

+ /// This method is very useful for debugging your robot. + ///

+ /// Note that the robot will only be painted if the "Paint" is enabled on the + /// robot's console window; otherwise the robot will never get painted (the + /// reason being that all robots might have graphical items that must be + /// painted, and then you might not be able to tell what graphical items that + /// have been painted for your robot). + ///

+ /// Also note that the coordinate system for the graphical context where you + /// paint items fits for the Robocode coordinate system where (0, 0) is at + /// the bottom left corner of the battlefield, where X is towards right and Y + /// is upwards. + /// + ///

+ /// The graphics context to use for painting graphical items for the robot + void OnPaint(IGraphics graphics); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IPaintRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IPaintRobot.cs new file mode 100644 index 0000000..f23f9fc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IPaintRobot.cs @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode.RobotInterfaces +{ + /// + /// A robot interface that makes it possible for a robot to receive paint events. + /// + public interface IPaintRobot : IBasicRobot + { + /// + /// This method is called by the game to notify this robot about painting + /// events. Hence, this method must be implemented so it returns your + /// listener. + /// + IPaintEvents GetPaintEventListener(); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IRunnable.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IRunnable.cs new file mode 100644 index 0000000..a389814 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/IRunnable.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode.RobotInterfaces +{ + /// + /// Interface to anything what could run + /// + public interface IRunnable + { + /// + /// Robot main loop or anything what could run. + /// + void Run(); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/ITeamEvents.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/ITeamEvents.cs new file mode 100644 index 0000000..16723c4 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/ITeamEvents.cs @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace Robocode.RobotInterfaces +{ + /// + /// An event interface for receiving robot team events with an . + /// + /// + public interface ITeamEvents + { + /// + /// This method is called when your robot receives a message from a teammate. + /// You should override it in your robot if you want to be informed of this + /// event. + ///

+ /// + /// + /// public void OnMessageReceived(MessageEvent evnt) + /// { + /// Out.WriteLine(event.Sender + " sent me: " + evnt.Message); + /// } + /// + /// + /// + /// + ///

+ /// The message event sent by the game + void OnMessageReceived(MessageEvent evnt); + } +} +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/ITeamRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/ITeamRobot.cs new file mode 100644 index 0000000..e0b3ceb --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/ITeamRobot.cs @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode.RobotInterfaces +{ + /// + /// A robot interface for creating a team robot like + /// that is able to receive team events. + /// A team robot is an advanced type of robot that supports sending messages + /// between teammates that participates in a team. + /// + /// + /// + /// + /// + /// + /// + public interface ITeamRobot : IAdvancedRobot + { + /// + /// This method is called by the game to notify this robot about team events. + /// Hence, this method must be implemented so it returns your + /// listener. + /// + ITeamEvents GetTeamEventListener(); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IAdvancedRobotPeer.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IAdvancedRobotPeer.cs new file mode 100644 index 0000000..e84346e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IAdvancedRobotPeer.cs @@ -0,0 +1,659 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Collections.Generic; +using System.IO; + +namespace Robocode.RobotInterfaces.Peer +{ + /// + /// The advanced robot peer for advanced robot types like + /// and . + ///

+ /// A robot peer is the object that deals with game mechanics and rules, and + /// makes sure your robot abides by them. + /// + /// + /// + /// + ///

+ public interface IAdvancedRobotPeer : IStandardRobotPeer + { + /// + /// This call is identical to , + /// but returns immediately, and will not execute until you + /// call or take an action that executes. + ///

+ /// If there is already movement saved from a previous stop, you can + /// overwrite it by calling SetStop(true). + /// + /// + /// + /// + ///

+ /// true if the movement saved from a previous stop + /// should be overwritten; false otherwise. + void SetStop(bool overwrite); + + /// + /// Sets the robot to Resume the movement stopped by + /// or , if any. + ///

+ /// This call returns immediately, and will not execute until you call + /// or take an action that executes. + /// + /// + /// + /// + /// + ///

+ void SetResume(); + + /// + /// Sets the robot to move forward or backward by distance measured in pixels + /// when the next execution takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// or take an action that executes. + ///

+ /// Note that both positive and negative values can be given as input, where + /// positive values means that the robot is set to move forward, and negative + /// values means that the robot is set to move backward. If 0 is given as + /// input, the robot will stop its movement, but will have to decelerate + /// till it stands still, and will thus not be able to stop its movement + /// immediately, but eventually. + ///

+ /// + /// + /// // Set the robot to move 50 pixels forward + /// SetMove(50); + /// + /// // Set the robot to move 100 pixels backward + /// // (overrides the previous order) + /// SetMove(-100); + /// + /// ... + /// // Executes the last SetMove() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The distance to move measured in pixels. + /// If distance > 0 the robot is set to move forward. + /// If distance < 0 the robot is set to move backward. + /// If distance = 0 the robot is set to stop its movement. + /// + void SetMove(double distance); + + /// + /// Sets the robot's body to turn right or left by radians when the next + /// execution takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// or take an action that + /// executes. + ///

+ /// Note that both positive and negative values can be given as input, where + /// positive values means that the robot's body is set to turn right, and + /// negative values means that the robot's body is set to turn left. + /// If 0 is given as input, the robot's body will stop turning. + ///

+ /// + /// + /// // Set the robot's body to turn 180 degrees to the right + /// SetTurnBody(Math.PI); + /// + /// // Set the robot's body to turn 90 degrees to the left instead of right + /// // (overrides the previous order) + /// SetTurnBody(-Math.PI / 2); + /// + /// ... + /// // Executes the last SetTurnBody() + /// Execute(); + /// + /// + /// + /// + /// + /// + /// + ///

+ /// T + /// The amount of radians to turn the robot's body. + /// If radians > 0 the robot's body is set to turn right. + /// If radians < 0 the robot's body is set to turn left. + /// If radians = 0 the robot's body is set to stop turning. + /// + void SetTurnBody(double radians); + + /// + /// Sets the robot's gun to turn right or left by radians when the next + /// execution takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// or take an action that + /// executes. + ///

+ /// Note that both positive and negative values can be given as input, where + /// positive values means that the robot's gun is set to turn right, and + /// negative values means that the robot's gun is set to turn left. + /// If 0 is given as input, the robot's gun will stop turning. + ///

+ /// + /// + /// // Set the robot's gun to turn 180 degrees to the right + /// SetTurnGun(Math.PI); + /// + /// // Set the robot's gun to turn 90 degrees to the left instead of right + /// // (overrides the previous order) + /// SetTurnGun(-Math.PI / 2); + /// + /// ... + /// // Executes the last setTurnFun() + /// Execute(); + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of radians to turn the robot's gun. + /// If radians > 0 the robot's gun is set to turn right. + /// If radians < 0 the robot's gun is set to turn left. + /// If radians = 0 the robot's gun is set to stop turning. + /// + void SetTurnGun(double radians); + + /// + /// Sets the robot's radar to turn right or left by radians when the next + /// execution takes place. + ///

+ /// This call returns immediately, and will not execute until you call + /// or take an action that + /// executes. + ///

+ /// Note that both positive and negative values can be given as input, where + /// positive values means that the robot's radar is set to turn right, and + /// negative values means that the robot's radar is set to turn left. + /// If 0 is given as input, the robot's radar will stop turning. + ///

+ /// + /// + /// // Set the robot's radar to turn 180 degrees to the right + /// SetTurnRadar(Math.PI); + /// + /// // Set the robot's radar to turn 90 degrees to the left instead of right + /// // (overrides the previous order) + /// SetTurnRadar(-Math.PI / 2); + /// + /// ... + /// // Executes the last SetTurnRadar() + /// Execute(); + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of radians to turn the robot's radar. + /// If radians > 0 the robot's radar is set to turn right. + /// If radians < 0 the robot's radar is set to turn left. + /// If radians = 0 the robot's radar is set to stop turning. + /// + void SetTurnRadar(double radians); + + /// + /// Sets the maximum turn rate of the robot measured in degrees if the robot + /// should turn slower than (10 degress/turn). + /// + /// + /// + /// + /// + /// The new maximum turn rate of the robot measured in degrees. + /// Valid values are 0 - + /// + void SetMaxTurnRate(double newMaxTurnRate); + + /// + /// Sets the maximum velocity of the robot measured in pixels/turn if the + /// robot should move slower than (8 pixels/turn). + /// + /// + /// + /// + /// + /// The new maximum turn rate of the robot measured in pixels/turn. + /// Valid values are 0 - + /// + void SetMaxVelocity(double newMaxVelocity); + + /// + /// Does not return until a condition is met, i.e. when a returns true. + ///

+ /// This call executes immediately. + ///

+ /// See the Sample.Crazy robot for how this method can be used. + /// + /// + ///

+ /// The condition that must be met before this call returns + void WaitFor(Condition condition); + + /// + /// Call this during an event handler to allow new events of the same + /// priority to restart the event handler. + ///

+ /// + /// + /// public void OnScannedRobot(ScannedRobotEvent e) + /// { + /// Fire(1); + /// SetInterruptible(true); + /// Move(100); // If you see a robot while moving ahead, + /// // this handler will start from the top + /// // Without SetInterruptible(true), we wouldn't + /// // receive scan events at all! + /// // We'll only get here if we don't see a robot during the move. + /// Out().WriteLine("Ok, I can't see anyone"); + /// } + /// + /// + /// + /// + ///

+ /// + /// true if the event handler should be interrupted if new events of + /// the same priority occurs; false otherwise + /// + void SetInterruptible(bool interruptible); + + /// + /// Sets the priority of a class of events. + ///

+ /// Events are sent to the onXXX handlers in order of priority. + /// Higher priority events can interrupt lower priority events. + /// For events with the same priority, newer events are always sent first. + /// Valid priorities are 0 - 99, where 100 is reserved and 80 is the default + /// priority. + ///

+ /// + /// + /// SetEventPriority("RobotDeathEvent", 15); + /// + ///

+ /// + /// The default priorities are, from highest to lowest: + /// + /// : 100 (reserved) + /// : 100 (reserved) + /// : 100 (reserved) + /// : 99 + /// Key and mouse events: 98 + /// : 80 (default value) + /// : 75 + /// : 70 + /// : 60 + /// : 55 + /// : 50 + /// : 40 + /// : 30 + /// : 20 + /// : 10 + /// : 5 + /// : -1 (reserved) + /// + ///

+ /// Note that you cannot change the priority for events with the special + /// priority value -1 or 100 (reserved) as these event are system events. + /// Also note that you cannot change the priority of CustomEvent. + /// Instead you must change the priority of the condition(s) for your custom + /// event(s). + /// + /// + ///

+ /// The name of the event class (string) to set the priority for + /// The new priority for that event class + void SetEventPriority(string eventClass, int priority); + + /// + /// Returns the current priority of a class of events. + /// An event priority is a value from 0 - 99. The higher value, the higher + /// priority. + ///

+ /// + /// + /// int myHitRobotPriority = GetEventPriority("HitRobotEvent"); + /// + ///

+ /// + /// The default priorities are, from highest to lowest: + /// + /// : 100 (reserved) + /// : 100 (reserved) + /// : 100 (reserved) + /// : 99 + /// Key and mouse events: 98 + /// : 80 (default value) + /// : 75 + /// : 70 + /// : 60 + /// : 55 + /// : 50 + /// : 40 + /// : 30 + /// : 20 + /// : 10 + /// : 5 + /// : -1 (reserved) + /// + /// + ///

+ /// The name of the event class (string) + int GetEventPriority(string eventClass); + + /// + /// Registers a custom event to be called when a condition is met. + /// When you are finished with your condition or just want to remove it you + /// must call . + ///

+ /// + /// + /// AddCustomEvent( + /// new Condition("triggerhit", (c) => + /// { + /// return Energy <= trigger; + /// })); + /// + /// // Add our custom event based on our condition + /// AddCustomEvent(triggerHitCondition); + /// + /// + /// + /// + ///

+ /// The condition that must be met. + void AddCustomEvent(Condition condition); + + /// + /// Removes a custom event that was previously added by calling . + ///

+ /// + /// + /// AddCustomEvent( + /// new Condition("triggerhit", (c) => + /// { + /// return Energy <= trigger; + /// })); + /// + /// // Add our custom event based on our condition + /// AddCustomEvent(triggerHitCondition); + /// ... + /// // do something with your robot + /// ... + /// // Remove the custom event based on our condition + /// RemoveCustomEvent(triggerHitCondition); + /// + /// + /// + /// + ///

+ /// + /// The condition that was previous added and that must be removed now. + /// + void RemoveCustomEvent(Condition condition); + + /// + /// Clears Out any pending events in the robot's event queue immediately. + /// + /// + /// + void clearAllEvents(); + + /// + /// Returns a list containing all events currently in the robot's queue. + /// You might, for example, call this while processing another event. + ///

+ /// + /// + /// foreach (Event evnt in GetAllEvents()) + /// { + /// if (event is HitRobotEvent) + /// { + /// // do something with the event + /// } + /// else if (event is HitByBulletEvent) + /// { + /// // do something with the event + /// } + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ IList GetAllEvents(); + + /// + /// Returns a list containing all StatusEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// foreach (StatusEvent evnt inGetStatusEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ IList GetStatusEvents(); + + /// + /// Returns a list containing all BulletMissedEvents currently in the + /// robot's queue. You might, for example, call this while processing another + /// event. + ///

+ /// + /// + /// foreach (BulletMissedEvent evnt inGetBulletMissedEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ IList GetBulletMissedEvents(); + + /// + /// Returns a list containing all BulletHitBulletEvents currently in the + /// robot's queue. You might, for example, call this while processing another + /// event. + ///

+ /// + /// + /// foreach (BulletHitBulletEvent evnt inGetBulletHitBulletEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ IList GetBulletHitBulletEvents(); + + /// + /// Returns a list containing all BulletHitEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// foreach (BulletHitEvent event: GetBulletHitEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ IList GetBulletHitEvents(); + + /// + /// Returns a list containing all HitByBulletEvents currently in the + /// robot's queue. You might, for example, call this while processing + /// another event. + ///

+ /// + /// + /// foreach (HitByBulletEvent evnt inGetHitByBulletEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ IList GetHitByBulletEvents(); + + /// + /// Returns a list containing all HitRobotEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// foreach (HitRobotEvent evnt inGetHitRobotEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ IList GetHitRobotEvents(); + + /// + /// Returns a list containing all HitWallEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// foreach (HitWallEvent evnt inGetHitWallEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ IList GetHitWallEvents(); + + /// + /// Returns a list containing all RobotDeathEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// foreach (RobotDeathEvent evnt inGetRobotDeathEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ IList GetRobotDeathEvents(); + + /// + /// Returns a list containing all ScannedRobotEvents currently in the + /// robot's queue. You might, for example, call this while processing another + /// event. + ///

+ /// + /// + /// foreach (ScannedRobotEvent evnt inGetScannedRobotEvents()) + /// { + /// // do something with the event + /// } + /// + /// + /// + /// + /// + ///

+ IList GetScannedRobotEvents(); + + /// + /// Returns a file representing a data directory for the robot, which can be + /// written to. + ///

+ /// The system will automatically create the directory for you, so you do not + /// need to create it by yourself. + /// + ///

+ string GetDataDirectory(); + + /// + /// Returns a file in your data directory that you can write to. + ///

+ /// The system will automatically create the directory for you, so you do not + /// need to create it by yourself. + ///

+ /// Please notice that the max. size of your data file is set to 200000 + /// (~195 KB). + ///

+ /// See the Sample.SittingDuck to see an example of how to use this + /// method. + /// + ///

+ /// The file name of the data file for your robot + Stream GetDataFile(string filename); + + /// + /// Returns the data quota available in your data directory, i.e. the amount + /// of bytes left in the data directory for the robot. + /// + /// + /// + long GetDataQuotaAvailable(); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IBasicRobotPeer.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IBasicRobotPeer.cs new file mode 100644 index 0000000..f5b5822 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IBasicRobotPeer.cs @@ -0,0 +1,698 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Drawing; +using Robocode; +using Robocode.RobotInterfaces; + +namespace Robocode.RobotInterfaces.Peer +{ + /// + /// The basic robot peer for all robot types. + ///

+ /// A robot peer is the obj that deals with game mechanics and rules, and + /// makes sure your robot abides by them. + /// + /// + /// + /// + ///

+ public interface IBasicRobotPeer + { + /// + /// Returns the robot's name. + /// + string GetName(); + + /// + /// Returns the game time of the current round, where the time is equal to + /// the current turn in the round. + ///

+ /// A battle consists of multiple rounds. + ///

+ /// Time is reset to 0 at the beginning of every round. + ///

+ long GetTime(); + + /// + /// Returns the robot's current energy. + /// + double GetEnergy(); + + /// + /// Returns the X position of the robot. (0,0) is at the bottom left of the + /// battlefield. + /// + /// + double GetX(); + + /// + /// Returns the Y position of the robot. (0,0) is at the bottom left of the + /// battlefield. + /// + /// + double GetY(); + + /// + /// Returns the velocity of the robot measured in pixels/turn. + ///

+ /// The maximum velocity of a robot is defined by + /// (8 pixels / turn). + /// + ///

+ double GetVelocity(); + + /// + /// Returns the direction that the robot's body is facing, in radians. + /// The value returned will be between 0 and 2 * PI (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// PI / 2 means East, PI means South, and 3 * PI / 2 means West. + /// + /// + ///

+ double GetBodyHeading(); + + /// + /// Returns the direction that the robot's gun is facing, in radians. + /// The value returned will be between 0 and 2 * PI (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// PI / 2 means East, PI means South, and 3 * PI / 2 means West. + /// + /// + ///

+ double GetGunHeading(); + + /// + /// Returns the direction that the robot's radar is facing, in radians. + /// The value returned will be between 0 and 2 * PI (is excluded). + ///

+ /// Note that the heading in Robocode is like a compass, where 0 means North, + /// PI / 2 means East, PI means South, and 3 * PI / 2 means West. + /// + /// + ///

+ double GetRadarHeading(); + + /// + /// Returns the current heat of the gun. The gun cannot Fire unless this is + /// 0. (Calls to Fire will succeed, but will not actually Fire unless + /// GetGunHeat() == 0). + ///

+ /// The amount of gun heat generated when the gun is fired is + /// 1 + (firePower / 5). Each turn the gun heat drops by the amount returned + /// by , which is a battle setup. + ///

+ /// Note that all guns are "hot" at the start of each round, where the gun + /// heat is 3. + /// + /// + ///

+ double GetGunHeat(); + + /// + /// Returns the width of the current battlefield measured in pixels. + /// + double GetBattleFieldWidth(); + + /// + /// Returns the height of the current battlefield measured in pixels. + /// + double GetBattleFieldHeight(); + + /// + /// Returns how many opponents that are left in the current round. + /// + int GetOthers(); + + /// + /// Returns how many sentry robots that are left in the current round. + /// + int GetNumSentries(); + + /// + /// Returns the number of rounds in the current battle. + /// + /// + int GetNumRounds(); + + /// + /// Returns the number of the current round (0 to - 1) + /// in the battle. + /// + /// + int GetRoundNum(); + + /// + /// Returns the sentry border size for a BorderSentry that defines the how + /// far a BorderSentry is allowed to move from the border edges measured in units.
+ /// Hence, the sentry border size defines the width/range of the border area surrounding the battlefield that + /// BorderSentrys cannot leave (sentry robots robots must stay in the border area), but it also define the + /// distance from the border edges where BorderSentrys are allowed/able to make damage to robots entering this + /// border area. + ///
+ int GetSentryBorderSize(); + + /// + /// Returns the rate at which the gun will cool down, i.e. the amount of heat + /// the gun heat will drop per turn. + ///

+ /// The gun cooling rate is default 0.1 / turn, but can be changed by the + /// battle setup. So don't count on the cooling rate being 0.1! + /// + /// + ///

+ double GetGunCoolingRate(); + + /// + /// Returns the distance remaining in the robot's current move measured in + /// pixels. + ///

+ /// This call returns both positive and negative values. Positive values + /// means that the robot is currently moving forwards. Negative values means + /// that the robot is currently moving backwards. If the returned value is 0, + /// the robot currently stands still. + /// + /// + /// + ///

+ double GetDistanceRemaining(); + + /// + /// Returns the angle remaining in the robot's turn, in radians. + ///

+ /// This call returns both positive and negative values. Positive values + /// means that the robot is currently turning to the right. Negative values + /// means that the robot is currently turning to the left. + /// + /// + /// + ///

+ double GetBodyTurnRemaining(); + + /// + /// Returns the angle remaining in the gun's turn, in radians. + ///

+ /// This call returns both positive and negative values. Positive values + /// means that the gun is currently turning to the right. Negative values + /// means that the gun is currently turning to the left. + /// + /// + /// + ///

+ double GetGunTurnRemaining(); + + /// + /// Returns the angle remaining in the radar's turn, in radians. + ///

+ /// This call returns both positive and negative values. Positive values + /// means that the radar is currently turning to the right. Negative values + /// means that the radar is currently turning to the left. + /// + /// + /// + ///

+ double GetRadarTurnRemaining(); + + /// + /// Executes any pending actions, or continues executing actions that are + /// in process. This call returns after the actions have been started. + ///

+ /// Note that advanced robots must call this function in order to + /// Execute pending set* calls like e.g. + /// , etc. + /// Otherwise, these calls will never get executed. + ///

+ /// In this example the robot will move while turning: + /// + /// + /// SetTurnBody(90); + /// SetMove(100); + /// Execute(); + /// + /// while (GetDistanceRemaining() > 0 && GetTurnRemaining() > 0) + /// { + /// Execute(); + /// } + /// + /// + ///

+ void Execute(); + + /// + /// Immediately moves your robot forward or backward by distance measured in + /// pixels. + ///

+ /// This call executes immediately, and does not return until it is complete, + /// i.e. when the remaining distance to move is 0. + ///

+ /// If the robot collides with a wall, the move is complete, meaning that the + /// robot will not move any further. If the robot collides with another + /// robot, the move is complete if you are heading toward the other robot. + ///

+ /// Note that both positive and negative values can be given as input, where + /// positive values means that the robot is set to move forward, and negative + /// values means that the robot is set to move backward. + ///

+ /// + /// + /// // Move the robot 100 pixels forward + /// Ahead(100); + /// + /// // Afterwards, move the robot 50 pixels backward + /// Ahead(-50); + /// + /// + /// + /// + ///

+ /// + /// The distance to move measured in pixels. + /// If distance > 0 the robot is set to move forward. + /// If distance < 0 the robot is set to move backward. + /// If distance = 0 the robot will not move anywhere, but just finish its turn. + /// + void Move(double distance); + + /// + /// Immediately turns the robot's body to the right or left by radians. + /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the body's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, where + /// positive values means that the robot's body is set to turn right, and + /// negative values means that the robot's body is set to turn left. + /// If 0 is given as input, the robot's body will stop turning. + ///

+ /// + /// + /// // Turn the robot's body 180 degrees to the right + /// TurnBody(Math.PI); + /// + /// // Afterwards, turn the robot's body 90 degrees to the left + /// TurnBody(-Math.PI / 2); + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of radians to turn the robot's body. + /// If radians > 0 the robot's body is set to turn right. + /// If radians < 0 the robot's body is set to turn left. + /// If radians = 0 the robot's body is set to stop turning. + /// + void TurnBody(double radians); + + /// + /// Immediately turns the robot's gun to the right or left by radians. + /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the gun's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, where + /// positive values means that the robot's gun is set to turn right, and + /// negative values means that the robot's gun is set to turn left. + /// If 0 is given as input, the robot's gun will stop turning. + ///

+ /// + /// + /// // Turn the robot's gun 180 degrees to the right + /// TurnGun(Math.PI); + /// + /// // Afterwards, turn the robot's gun 90 degrees to the left + /// TurnGun(-Math.PI / 2); + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of radians to turn the robot's gun. + /// If radians > 0 the robot's gun is set to turn right. + /// If radians < 0 the robot's gun is set to turn left. + /// If radians = 0 the robot's gun is set to stop turning. + /// + void TurnGun(double radians); + + /// + /// Immediately fires a bullet. The bullet will travel in the direction the + /// gun is pointing. + ///

+ /// The specified bullet power is an amount of energy that will be taken from + /// the robot's energy. Hence, the more power you want to spend on the + /// bullet, the more energy is taken from your robot. + ///

+ /// The bullet will do (4 * power) damage if it hits another robot. If power + /// is greater than 1, it will do an additional 2 * (power - 1) damage. + /// You will get (3 * power) back if you hit the other robot. You can call + /// for getting the damage that a + /// bullet with a specific bullet power will do. + ///

+ /// The specified bullet power should be between + /// and . + ///

+ /// Note that the gun cannot Fire if the gun is overheated, meaning that + /// returns a value > 0. + ///

+ /// An event is generated when the bullet hits a robot + /// ("/>, wall (), or another + /// bullet (). + ///

+ /// + /// + /// // Fire a bullet with maximum power if the gun is ready + /// if (GetGunHeat() == 0) + /// { + /// Bullet bullet = Fire(Rules.MAX_BULLET_POWER); + /// + /// // Get the velocity of the bullet + /// if (bullet != null) + /// { + /// double bulletVelocity = bullet.Velocity; + /// } + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of energy given to the bullet, and subtracted from the robot's energy. + /// + Bullet Fire(double power); + + /// + /// Sets the gun to Fire a bullet when the next execution takes place. + /// The bullet will travel in the direction the gun is pointing. + ///

+ /// This call returns immediately, and will not execute until you call + /// Execute() or take an action that executes. + ///

+ /// The specified bullet power is an amount of energy that will be taken from + /// the robot's energy. Hence, the more power you want to spend on the + /// bullet, the more energy is taken from your robot. + ///

+ /// The bullet will do (4 * power) damage if it hits another robot. If power + /// is greater than 1, it will do an additional 2 * (power - 1) damage. + /// You will get (3 * power) back if you hit the other robot. You can call + /// for getting the damage that a + /// bullet with a specific bullet power will do. + ///

+ /// The specified bullet power should be between + /// and . + ///

+ /// Note that the gun cannot Fire if the gun is overheated, meaning that + /// returns a value > 0. + ///

+ /// An event is generated when the bullet hits a robot + /// (), wall (), or another + /// bullet (). + ///

+ /// + /// + /// Bullet bullet = null; + /// + /// // Fire a bullet with maximum power if the gun is ready + /// if (GetGunHeat() == 0) + /// { + /// bullet = SetFireBullet(Rules.MAX_BULLET_POWER); + /// } + /// ... + /// Execute(); + /// ... + /// // Get the velocity of the bullet + /// if (bullet != null) + /// { + /// double bulletVelocity = bullet.Velocity; + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of energy given to the bullet, and subtracted from the robot's energy. + /// + Bullet SetFire(double power); + + /// + /// Sets the color of the robot's body. + ///

+ /// A null indicates the default (blue) color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetBodyColor(Color.BLACK); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + /// + /// The new body color + ///

+ void SetBodyColor(Color color); + + /// + /// Returns current color of body + /// + Color GetBodyColor(); + + /// + /// Sets the color of the robot's gun. + ///

+ /// A null indicates the default (blue) color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetGunColor(Color.RED); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The new gun color + void SetGunColor(Color color); + + /// + /// Returns current color of gun + /// + Color GetGunColor(); + + /// + /// Sets the color of the robot's radar. + ///

+ /// A null indicates the default (blue) color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetRadarColor(Color.YELLOW); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The new radar color + void SetRadarColor(Color color); + + /// + /// Returns current color of radar + /// + Color GetRadarColor(); + + /// + /// Sets the color of the robot's bullets. + ///

+ /// A null indicates the default white color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetBulletColor(Color.GREEN); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + ///

+ /// The new bullet color + void SetBulletColor(Color color); + + /// + /// Returns current color of bullet + /// + Color GetBulletColor(); + + /// + /// Sets the color of the robot's scan arc. + ///

+ /// A null indicates the default (blue) color. + ///

+ /// + /// + /// // Don't forget to using System.Drawing at the top... + /// using System.Drawing; + /// ... + /// + /// public void Run() + /// { + /// SetScanColor(Color.WHITE); + /// ... + /// } + /// + /// + /// + /// + /// + /// + /// + ///

+ /// the new scan arc color + void SetScanColor(Color color); + + /// + /// Returns current color of scan beam + /// + Color GetScanColor(); + + /// + /// This call must be made from a robot call to inform the game + /// that the robot made a Get* call like e.g. or + /// . + ///

+ /// This method is used by the game to determine if the robot is inactive or + /// not. Note: You should only make this call once in a Get* method! + /// + ///

+ void GetCall(); + + /// + /// This call must be made from a robot call to inform the game + /// that the robot made a Set* call like e.g. + /// or . + ///

+ /// This method is used by the game to determine if the robot is inactive or + /// not. Note: You should only make this call once in a Set* method! + /// + /// + ///

+ void SetCall(); + + /// + /// Returns a graphics context used for painting graphical items for the robot. + ///

+ /// This method is very useful for debugging your robot. + ///

+ /// Note that the robot will only be painted if the "Paint" is enabled on the + /// robot's console window; otherwise the robot will never get painted (the + /// reason being that all robots might have graphical items that must be + /// painted, and then you might not be able to tell what graphical items that + /// have been painted for your robot). + ///

+ /// Also note that the coordinate system for the graphical context where you + /// paint items fits for the Robocode coordinate system where (0, 0) is at + /// the bottom left corner of the battlefield, where X is towards right and Y + /// is upwards. + /// + ///

+ IGraphics GetGraphics(); + + /// + /// Sets the debug property with the specified key to the specified value. + ///

+ /// This method is very useful when debugging or reviewing your robot as you + /// will be able to see this property displayed in the robot console for your + /// robots under the Debug Properties tab page. + ///

+ /// The name/key of the debug property. + /// + /// The new value of the debug property, where null or the empty string is used + /// for removing this debug property. + /// + void SetDebugProperty(string key, string value); + + /// + /// Rescan for other robots. This method is called automatically by the game, + /// as long as the robot is moving, turning its body, turning its gun, or + /// turning its radar. + ///

+ /// Rescan will cause + /// to be called if you see a robot. + ///

+ /// There are 2 reasons to call Rescan() manually: + ///

    + ///
  1. You want to scan after you stop moving.
  2. + ///
  3. You want to interrupt the OnScannedRobot event. This is more + /// likely. If you are in OnScannedRobot and call Scan(), + /// and you still see a robot, then the system will interrupt your + /// OnScannedRobot event immediately and start it from the top.
  4. + ///
+ ///

+ /// This call executes immediately. + /// + /// + /// + ///

+ void Rescan(); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IJuniorRobotPeer.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IJuniorRobotPeer.cs new file mode 100644 index 0000000..f07e86d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IJuniorRobotPeer.cs @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode.RobotInterfaces.Peer +{ + /// + /// The junior robot peer for junior robot types like . + ///

+ /// A robot peer is the obj that deals with game mechanics and rules, and + /// makes sure your robot abides by them. + /// + /// + /// + /// + ///

+ public interface IJuniorRobotPeer : IBasicRobotPeer + { + /// + /// Moves this robot forward or backwards by pixels and turns this robot + /// right or left by degrees at the same time. The robot will move in a curve + /// that follows a perfect circle, and the moving and turning will end at + /// exactly the same time. + ///

+ /// Note that the max. velocity and max. turn rate is automatically adjusted, + /// which means that the robot will move slower the sharper the turn is + /// compared to the distance. + ///

+ /// Note that both positive and negative values can be given as input: + ///

    + ///
  • If the distance parameter is set to a positive value, it + /// means that the robot is set to move forward, and a negative value means + /// that the robot is set to move backward. If set to 0, the robot will not + /// move, but will be able to turn.
  • + ///
  • If the radians parameter is set to a positive value, it means + /// that the robot is set to turn to the right, and a negative value means + /// that the robot is set to turn to the left. If set to 0, the robot will + /// not turn, but will be able to move.
  • + ///
+ /// + /// + /// + /// + /// + ///
+ /// + /// The distance to move measured in pixels. + /// If distance > 0 the robot is set to move forward. + /// If distance < 0 the robot is set to move backward. + /// If distance = 0 the robot will not move anywhere, but just finish its turn. + /// + /// + /// The amount of radians to turn the robot's body. + /// If radians > 0 the robot's body is set to turn right. + /// If radians < 0 the robot's body is set to turn left. + /// If radians = 0 the robot's body is set to stop turning. + /// + void TurnAndMove(double distance, double radians); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IStandardRobotPeer.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IStandardRobotPeer.cs new file mode 100644 index 0000000..5b785c5 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/IStandardRobotPeer.cs @@ -0,0 +1,248 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode.RobotInterfaces.Peer +{ + /// + /// The standard robot peer for standard robot types like , + /// , and . + ///

+ /// A robot peer is the obj that deals with game mechanics and rules, and + /// makes sure your robot abides by them. + /// + /// + /// + /// + ///

+ public interface IStandardRobotPeer : IBasicRobotPeer + { + /// + /// Immediately stops all movement, and saves it for a call to + /// . If there is already movement saved from a previous + /// stop, you can overwrite it by calling Stop(true). + /// + /// + /// + /// If there is already movement saved from a previous stop, + /// you can overwrite it by calling Stop(true). + /// + void Stop(bool overwrite); + + /// + /// Immediately resumes the movement you stopped by , if any. + ///

+ /// This call executes immediately, and does not return until it is complete. + /// + /// + ///

+ void Resume(); + + /// + /// Immediately turns the robot's radar to the right or left by radians. + /// This call executes immediately, and does not return until it is complete, + /// i.e. when the angle remaining in the radar's turn is 0. + ///

+ /// Note that both positive and negative values can be given as input, where + /// positive values means that the robot's radar is set to turn right, and + /// negative values means that the robot's radar is set to turn left. + /// If 0 is given as input, the robot's radar will stop turning. + ///

+ /// + /// + /// // Turn the robot's radar 180 degrees to the right + /// TurnRadar(Math.PI); + /// + /// // Afterwards, turn the robot's radar 90 degrees to the left + /// TurnRadar(-Math.PI / 2); + /// + /// + /// + /// + /// + ///

+ /// + /// The amount of radians to turn the robot's radar. + /// If radians > 0 the robot's radar is set to turn right. + /// If radians < 0 the robot's radar is set to turn left. + /// If radians = 0 the robot's radar is set to stop turning. + /// + void TurnRadar(double radians); + + /// + /// Sets the gun to turn independent from the robot's turn. + ///

+ /// Ok, so this needs some explanation: The gun is mounted on the robot's + /// body. So, normally, if the robot turns 90 degrees to the right, then the + /// gun will turn with it as it is mounted on top of the robot's body. To + /// compensate for this, you can call IsAdjustGunForBodyTurn(true). + /// When this is set, the gun will turn independent from the robot's turn, + /// i.e. the gun will compensate for the robot's body turn. + ///

+ /// Note: This method is additive until you reach the maximum the gun can + /// turn. The "adjust" is added to the amount you set for turning the robot, + /// then capped by the physics of the game. If you turn infinite, then the + /// adjust is ignored (and hence overridden). + ///

+ /// + /// Assuming both the robot and gun start Out facing up (0 degrees): + /// + /// // Set gun to turn with the robot's turn + /// SetAdjustGunForBodyTurn(false); // This is the default + /// TurnBodyRight(Math.PI / 2); + /// // At this point, both the robot and gun are facing right (90 degrees) + /// TurnBodyLeft(Math.PI / 2); + /// // Both are back to 0 degrees + /// + /// -- or -- + /// + /// // Set gun to turn independent from the robot's turn + /// SetAdjustGunForBodyTurn(true); + /// TurnBodyRight(Math.PI / 2); + /// // At this point, the robot is facing right (90 degrees), but the gun is still facing up. + /// TurnBodyLeft(Math.PI / 2); + /// // Both are back to 0 degrees. + /// + /// + ///

+ /// Note: The gun compensating this way does count as "turning the gun". + /// See for details. + /// + ///

+ /// + /// true if the gun must turn independent from the robot's turn; + /// false if the gun must turn with the robot's turn. + /// + void SetAdjustGunForBodyTurn(bool independent); + + /// + /// Sets the radar to turn independent from the gun's turn. + ///

+ /// Ok, so this needs some explanation: The radar is mounted on the robot's + /// gun. So, normally, if the gun turns 90 degrees to the right, then the + /// radar will turn with it as it is mounted on top of the gun. To compensate + /// for this, you can call IsAdjustRadarForGunTurn(true). When this + /// is set, the radar will turn independent from the robot's turn, i.e. the + /// radar will compensate for the gun's turn. + ///

+ /// Note: This method is additive until you reach the maximum the radar can + /// turn. The "adjust" is added to the amount you set for turning the robot, + /// then capped by the physics of the game. If you turn infinite, then the + /// adjust is ignored (and hence overridden). + ///

+ /// + /// Assuming both the gun and radar start Out facing up (0 degrees): + /// + /// // Set radar to turn with the gun's turn + /// SetAdjustRadarForGunTurn(false); // This is the default + /// TurnGunRight(Math.PI / 2); + /// // At this point, both the radar and gun are facing right (90 degrees); + /// + /// -- or -- + /// + /// // Set radar to turn independent from the gun's turn + /// SetAdjustRadarForGunTurn(true); + /// TurnGunRight(Math.PI / 2); + /// // At this point, the gun is facing right (90 degrees), but the radar is still facing up. + /// + /// + /// Note: Calling IsAdjustRadarForGunTurn(bool) will + /// automatically call with the + /// same value, unless you have already called it earlier. This behavior is + /// primarily for backward compatibility with older Robocode robots. + /// + /// + ///

+ /// + /// true if the radar must turn independent from the gun's turn; + /// false if the radar must turn with the gun's turn. + /// + void SetAdjustRadarForGunTurn(bool independent); + + /// + /// Sets the radar to turn independent from the robot's turn. + ///

+ /// Ok, so this needs some explanation: The radar is mounted on the gun, and + /// the gun is mounted on the robot's body. So, normally, if the robot turns + /// 90 degrees to the right, the gun turns, as does the radar. Hence, if the + /// robot turns 90 degrees to the right, then the gun and radar will turn + /// with it as the radar is mounted on top of the gun. To compensate for + /// this, you can call IsAdjustRadarForBodyTurn(true). When this is + /// set, the radar will turn independent from the robot's turn, i.e. the + /// radar will compensate for the robot's turn. + ///

+ /// Note: This method is additive until you reach the maximum the radar can + /// turn. The "adjust" is added to the amount you set for turning the gun, + /// then capped by the physics of the game. If you turn infinite, then the + /// adjust is ignored (and hence overridden). + ///

+ /// + /// Assuming the robot, gun, and radar all start Out facing up (0 degrees): + /// + /// // Set radar to turn with the robots's turn + /// SetAdjustRadarForBodyTurn(false); // This is the default + /// TurnRight(Math.PI / 2); + /// // At this point, the body, gun, and radar are all facing right (90 degrees); + /// + /// -- or -- + /// + /// // Set radar to turn independent from the robot's turn + /// SetAdjustRadarForBodyTurn(true); + /// TurnRight(Math.PI / 2); + /// // At this point, the robot and gun are facing right (90 degrees), but the radar is still facing up. + /// + /// + /// + /// + ///

+ /// + /// true if the radar must turn independent from the robots's turn; + /// false if the radar must turn with the robot's turn. + /// + void SetAdjustRadarForBodyTurn(bool independent); + + /// + /// Checks if the gun is set to adjust for the robot turning, i.e. to turn + /// independent from the robot's body turn. + ///

+ /// This call returns true if the gun is set to turn independent of + /// the turn of the robot's body. Otherwise, false is returned, + /// meaning that the gun is set to turn with the robot's body turn. + /// + /// + /// + ///

+ bool IsAdjustGunForBodyTurn(); + + /// + /// Checks if the radar is set to adjust for the robot turning, i.e. to turn + /// independent from the robot's body turn. + ///

+ /// This call returns true if the radar is set to turn independent of + /// the turn of the robot. Otherwise, false is returned, meaning that + /// the radar is set to turn with the robot's turn. + /// + /// + /// + ///

+ bool IsAdjustRadarForGunTurn(); + + /// + /// Checks if the radar is set to adjust for the gun turning, i.e. to turn + /// independent from the gun's turn. + ///

+ /// This call returns true if the radar is set to turn independent of + /// the turn of the gun. Otherwise, false is returned, meaning that + /// the radar is set to turn with the gun's turn. + /// + /// + /// + ///

+ bool IsAdjustRadarForBodyTurn(); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/ITeamRobotPeer.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/ITeamRobotPeer.cs new file mode 100644 index 0000000..cdd4872 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/robotinterfaces/peer/ITeamRobotPeer.cs @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Collections.Generic; +using Robocode; + +namespace Robocode.RobotInterfaces.Peer +{ + /// + /// The team robot peer for team robots like . + ///

+ /// A robot peer is the object that deals with game mechanics and rules, and + /// makes sure your robot abides by them. + /// + /// + /// + /// + ///

+ public interface ITeamRobotPeer : IAdvancedRobotPeer + { + /// + /// Returns the names of all teammates, or null there is no teammates. + ///

+ /// + /// + /// public void Run() + /// { + /// // Prints Out all teammates + /// string[] teammates = GetTeammates(); + /// if (teammates != null) + /// { + /// foreach (string member in teammates) + /// { + /// Out.WriteLine(member); + /// } + /// } + /// } + /// + /// + /// + /// + /// + ///

+ string[] GetTeammates(); + + /// + /// Checks if a given robot name is the name of one of your teammates. + ///

+ /// + /// + /// public void OnScannedRobot(ScannedRobotEvent e) + /// { + /// if (IsTeammate(e.Name) + /// { + /// return; + /// } + /// Fire(1); + /// } + /// + /// + /// + /// + /// + /// + ///

+ /// The robot name to check + bool IsTeammate(string name); + + /// + /// Broadcasts a message to all teammates. + ///

+ /// + /// + /// public void Run() + /// { + /// BroadcastMessage("I'm here!"); + /// } + /// + /// + /// + /// + /// + ///

+ /// The message to broadcast to all teammates + void BroadcastMessage(object message); + + /// + /// Sends a message to one (or more) teammates. + ///

+ /// + /// + /// public void Run() + /// { + /// SendMessage("Sample.DroidBot", "I'm here!"); + /// } + /// + /// + /// + /// + /// + ///

+ /// The name of the intended recipient of the message + /// The message to send + void SendMessage(string name, object message); + + /// + /// Returns a list containing all MessageEvents currently in the robot's + /// queue. You might, for example, call this while processing another event. + ///

+ /// + /// + /// foreach (MessageEvent e in GetMessageEvents()) + /// { + /// // do something with e + /// } + /// + /// + /// + /// + ///

+ IList GetMessageEvents(); + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/util/Utils.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/util/Utils.cs new file mode 100644 index 0000000..fa1fdb5 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.api/src/robocode/util/Utils.cs @@ -0,0 +1,206 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.security; + +namespace Robocode.Util +{ + /// + /// Utility class that provide methods for normalizing angles. + /// + public static class Utils + { + private const double TWO_PI = 2*Math.PI; + private const double THREE_PI_OVER_TWO = 3*Math.PI/2; + private const double PI_OVER_TWO = Math.PI/2; + private const double NEAR_DELTA = .00001; + + /// + /// Normalizes an angle to an absolute angle. + /// The normalized angle will be in the range from 0 to 2*PI, where 2*PI + /// itself is not included. + /// + /// the angle in radians to normalize + public static double NormalAbsoluteAngle(double angle) + { + return (angle %= TWO_PI) >= 0 ? angle : (angle + TWO_PI); + } + + /// + /// Normalizes an angle to an absolute angle. + /// The normalized angle will be in the range from 0 to 360, where 360 + /// itself is not included. + /// + /// the angle in degrees to normalize + public static double NormalAbsoluteAngleDegrees(double angle) + { + return (angle %= 360) >= 0 ? angle : (angle + 360); + } + + /// + /// Normalizes an angle to a relative angle. + /// The normalized angle will be in the range from -PI to PI, where PI + /// itself is not included. + /// + /// the angle in radinas to normalize + public static double NormalRelativeAngle(double angle) + { + return (angle %= TWO_PI) >= 0 + ? (angle < Math.PI) ? angle : angle - TWO_PI + : (angle >= -Math.PI) ? angle : angle + TWO_PI; + } + + /// + /// Normalizes an angle to a relative angle. + /// The normalized angle will be in the range from -180 to 180, where 180 + /// itself is not included. + /// + /// the angle to normalize + public static double NormalRelativeAngleDegrees(double angle) + { + return (angle %= 360) >= 0 ? (angle < 180) ? angle : angle - 360 : (angle >= -180) ? angle : angle + 360; + } + + /// + /// Normalizes an angle to be near an absolute angle. + /// The normalized angle will be in the range from 0 to 360, where 360 + /// itself is not included. + /// If the normalized angle is near to 0, 90, 180, 270 or 360, that + /// angle will be returned. The + /// method is used for defining when the angle is near one of angles listed + /// above. + /// + /// + /// + /// the angle to normalize + public static double NormalNearAbsoluteAngleDegrees(double angle) + { + angle = (angle %= 360) >= 0 ? angle : (angle + 360); + + if (IsNear(angle, 180)) + { + return 180; + } + if (angle < 180) + { + if (IsNear(angle, 0)) + { + return 0; + } + if (IsNear(angle, 90)) + { + return 90; + } + } + else + { + if (IsNear(angle, 270)) + { + return 270; + } + if (IsNear(angle, 360)) + { + return 0; + } + } + return angle; + } + + /// + /// Normalizes an angle to be near an absolute angle. + /// The normalized angle will be in the range from 0 to 2*PI, where 2*PI + /// itself is not included. + /// If the normalized angle is near to 0, PI/2, PI, 3*PI/2 or 2*PI, that + /// angle will be returned. The + /// method is used for defining when the angle is near one of angles listed + /// above. + /// + /// + /// + /// the angle to normalize + public static double NormalNearAbsoluteAngle(double angle) + { + angle = (angle %= TWO_PI) >= 0 ? angle : (angle + TWO_PI); + + if (IsNear(angle, Math.PI)) + { + return Math.PI; + } + if (angle < Math.PI) + { + if (IsNear(angle, 0)) + { + return 0; + } + if (IsNear(angle, PI_OVER_TWO)) + { + return PI_OVER_TWO; + } + } + else + { + if (IsNear(angle, THREE_PI_OVER_TWO)) + { + return THREE_PI_OVER_TWO; + } + if (IsNear(angle, TWO_PI)) + { + return 0; + } + } + return angle; + } + + /// + /// Tests if the two double values are near to each other. + /// It is recommended to use this method instead of testing if the two + /// doubles are equal using an this expression: value1 == value2. + /// The reason being, that this expression might never become + /// true due to the precision of double values. + /// Whether or not the specified doubles are near to each other is defined by + /// the following expression: + /// (Math.abs(value1 - value2) < .00001) + /// + /// the first double value + /// the second double value + public static bool IsNear(double value1, double value2) + { + return (Math.Abs(value1 - value2) < NEAR_DELTA); + } + + /// + /// Returns random number generator. It might be configured for repeatable behavior by setting -DRANDOMSEED option. + /// + public static Random GetRandom() + { + return HiddenAccessN.randomHelper.GetRandom(); + } + + /// + /// Conversion from degrees to radians + /// + /// in degrees + /// angle in radians + public static double ToRadians(double angle) + { + return Math.PI*angle/180.0; + } + + /// + /// Conversion from radians to degrees + /// + /// in radians + /// angle in degrees + public static double ToDegrees(double angle) + { + return angle*(180.0/Math.PI); + } + } +} + +//doc \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.classpath b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.classpath new file mode 100644 index 0000000..37239ec --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.project new file mode 100644 index 0000000..70b6969 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.project @@ -0,0 +1,19 @@ + + + robocode.dotnet.content + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.dotnet.host + robocode.dotnet.nhost + robocode.dotnet.api + robocode.dotnet.control.api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..764c3ab --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:34:11 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/test/java=8859_1 +encoding/src/main/resources=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/pom.xml new file mode 100644 index 0000000..f67bbeb --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + robocode.dotnet.content + Robocode .NET Content + + net.sf.robocode + robocode.dotnet + ${robocode.dotnet.version} + + + + net.sf.robocode + robocode.dotnet.host + ${robocode.version} + + + net.sf.robocode + robocode.api + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/robocode.dotnet.content.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/robocode.dotnet.content.iml new file mode 100644 index 0000000..98715be --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/robocode.dotnet.content.iml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/.gitignore b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/.gitignore new file mode 100644 index 0000000..4a3496d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/.gitignore @@ -0,0 +1,3 @@ +obj +Properties +BattleRunnnerSample.suo diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/BattleRunnnerSample.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/BattleRunnnerSample.csproj new file mode 100644 index 0000000..b5fb8dd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/BattleRunnnerSample.csproj @@ -0,0 +1,69 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {9826B19C-0C68-4D4A-B6CE-6F2A80B4B114} + Exe + Properties + BattleRunnner + BattleRunnner + v3.5 + 512 + + + + + 3.5 + + + true + full + false + ..\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + C:\robocode\libs\jni4net.n-0.8.7.0.dll + + + False + C:\robocode\libs\robocode.dll + + + False + C:\robocode\libs\robocode.control.dll + + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/BattleRunnnerSample.sln b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/BattleRunnnerSample.sln new file mode 100644 index 0000000..67b675a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/BattleRunnnerSample.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BattleRunnnerSample", "BattleRunnnerSample.csproj", "{9826B19C-0C68-4D4A-B6CE-6F2A80B4B114}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9826B19C-0C68-4D4A-B6CE-6F2A80B4B114}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9826B19C-0C68-4D4A-B6CE-6F2A80B4B114}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9826B19C-0C68-4D4A-B6CE-6F2A80B4B114}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9826B19C-0C68-4D4A-B6CE-6F2A80B4B114}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/Program.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/Program.cs new file mode 100644 index 0000000..e757cab --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/libs/control/Program.cs @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +// Application that demonstrates how to run two sample robots in Robocode with the RobocodeEngine using the +// Robocode.Control package. +// +// NOTE: this application assumes that Robocode and the .NET plugin has been installed at C:\robocode, and that this +// application is run from the file path C:\robocode\libs\control. If this is not the case, the references for this +// solution must be changed to point at [your robocode dir]\libs directory where these references are located. +// Also note that the application will need some time to start up and initialize Robocode before the battle can begin. +// +// Author: Flemming N. Larsen + +using System; +using Robocode; +using Robocode.Control; +using Robocode.Control.Events; + +class BattleRunner +{ + static void Main(string[] args) + { + // Create the RobocodeEngine + RobocodeEngine engine = new RobocodeEngine("C:\\robocode"); // Run from C:\Robocode + + // Add battle event handlers + engine.BattleCompleted += new BattleCompletedEventHandler(BattleCompleted); + engine.BattleMessage += new BattleMessageEventHandler(BattleMessage); + engine.BattleError += new BattleErrorEventHandler(BattleError); + + // Show the Robocode battle view + engine.Visible = true; + + // Disable log messages from Robocode + RobocodeEngine.LogMessagesEnabled = false; + + // Setup the battle specification + + int numberOfRounds = 5; + BattlefieldSpecification battlefield = new BattlefieldSpecification(800, 600); // 800x600 + RobotSpecification[] selectedRobots = engine.GetLocalRepository("sample.RamFire,sample.Corners"); + + BattleSpecification battleSpec = new BattleSpecification(numberOfRounds, battlefield, selectedRobots); + + // Run our specified battle and let it run till it is over + engine.RunBattle(battleSpec, true /* wait till the battle is over */); + + // Cleanup our RobocodeEngine + engine.Close(); + } + + // Called when the battle is completed successfully with battle results + private static void BattleCompleted(BattleCompletedEvent e) + { + Console.WriteLine("-- Battle has completed --"); + + // Print out the sorted results with the robot names + Console.WriteLine("Battle results:"); + foreach (BattleResults result in e.SortedResults) + { + Console.WriteLine(" " + result.TeamLeaderName + ": " + result.Score); + } + } + + // Called when the game sends out an information message during the battle + private static void BattleMessage(BattleMessageEvent e) + { + Console.WriteLine("Msg> " + e.Message); + } + + // Called when the game sends out an error message during the battle + private static void BattleError(BattleErrorEvent e) + { + Console.WriteLine("Err> " + e.Error); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/robocode.bat b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/robocode.bat new file mode 100644 index 0000000..af55147 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/robocode.bat @@ -0,0 +1,9 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +java -Xmx512M -cp libs/robocode.jar;libs/jni4net.j-0.8.7.0.jar robocode.Robocode %* diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/robots/SamplesCs.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/robots/SamplesCs.csproj new file mode 100644 index 0000000..58786f6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.content/src/main/resources/robots/SamplesCs.csproj @@ -0,0 +1,89 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {80857B97-6397-487B-A9F5-B07026DCB666} + Library + SampleCs + samplescs-1.9.2.4 + v2.0 + 512 + + + + + true + full + false + .\ + obj\ + DEBUG;TRACE + prompt + 4 + false + false + + + pdbonly + true + .\ + obj\ + + + prompt + 4 + true + + + + False + ..\libs\robocode.dll + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/.project new file mode 100644 index 0000000..41b449a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/.project @@ -0,0 +1,10 @@ + + + robocode.dotnet.control.api + .NET Control API for Robocode. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.dotnet.api + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..070758f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +#Tue Nov 27 22:34:10 CET 2012 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 +encoding/src/main/resources=8859_1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/test/resources=8859_1 +encoding/src=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/Content Layout.content b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/Content Layout.content new file mode 100644 index 0000000..31aca23 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/Content Layout.content @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/Introduction.aml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/Introduction.aml new file mode 100644 index 0000000..09788c4 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/Introduction.aml @@ -0,0 +1,113 @@ + + + + Introduction + + The Robocode Control API is used for controlling the Robocode + application from another external application. Basically, it is possible + to run battles between selected robots and retrieve the results. However, + it is also possible to get detailed information as snapshots during the + battles regarding e.g. the positions and headings of the individual robots + and bullets at a specific time during a battle. + + + The main entry class is the Robocode.Control.RobocodeEngine class, which + must be instantiated by the application controlling Robocode. With the + RobocodeEngine, a battle specification must be provided in order to run a + battle. The battle specification specify the size of the battlefield, and + which rules that must be used. In addition, the participant robots must be + selected, which must exist in the robot directory of Robocode in + advantage. + + +
+ Example + + + Here is a simple sample application that runs a battle in Robocode for 5 + rounds on the default battlefield of 800x600 pixels. The robots selected + for the battle are sample.RamFire and sample.Corners. + + + A Visual Studio solution containing this BattleRunner can be found in + [your robocode dir]\lib\control if you have installed Robocode and the + .NET plugin for Robocode, where [your robocode dir] is your Robocode + installation directory, which could be C:\robocode like this example + assumes. + + +// Application that demonstrates how to run two sample robots in Robocode with the RobocodeEngine using the +// Robocode.Control package. +// +// NOTE: this application assumes that Robocode and the .NET plugin has been installed at C:\robocode, and that this +// application is run from the file path C:\robocode\libs\control. If this is not the case, the references for this +// solution must be changed to point at [your robocode dir]\libs directory where these references are located. +// Also note that the application will need some time to start up and initialize Robocode before the battle can begin. +// +// Author: Flemming N. Larsen + +using System; +using Robocode; +using Robocode.Control; +using Robocode.Control.Events; + +class BattleRunner +{ + static void Main(string[] args) + { + // Create the RobocodeEngine + RobocodeEngine engine = new RobocodeEngine("C:\\robocode"); // Run from C:\Robocode + + // Add battle event handlers + engine.BattleCompleted += new BattleCompletedEventHandler(BattleCompleted); + engine.BattleMessage += new BattleMessageEventHandler(BattleMessage); + engine.BattleError += new BattleErrorEventHandler(BattleError); + + // Show the Robocode battle view + engine.Visible = true; + + // Setup the battle specification + + int numberOfRounds = 5; + BattlefieldSpecification battlefield = new BattlefieldSpecification(800, 600); // 800x600 + RobotSpecification[] selectedRobots = engine.GetLocalRepository("sample.RamFire,sample.Corners"); + + BattleSpecification battleSpec = new BattleSpecification(numberOfRounds, battlefield, selectedRobots); + + // Run our specified battle and let it run till it is over + engine.RunBattle(battleSpec, true /* wait till the battle is over */); + + // Cleanup our RobocodeEngine + engine.Close(); + } + + // Called when the battle is completed successfully with battle results + private static void BattleCompleted(BattleCompletedEvent e) + { + Console.WriteLine("-- Battle has completed --"); + + // Print out the sorted results with the robot names + Console.WriteLine("Battle results:"); + foreach (BattleResults result in e.SortedResults) + { + Console.WriteLine(" " + result.TeamLeaderName + ": " + result.Score); + } + } + + // Called when the game sends out an information message during the battle + private static void BattleMessage(BattleMessageEvent e) + { + Console.WriteLine("Msg> " + e.Message); + } + + // Called when the game sends out an error message during the battle + private static void BattleError(BattleErrorEvent e) + { + Console.WriteLine("Err> " + e.Error); + } +} + + +
+
+
\ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/controlAPI.shfbproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/controlAPI.shfbproj new file mode 100644 index 0000000..15f8d16 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/controlAPI.shfbproj @@ -0,0 +1,81 @@ + + + + + Debug + AnyCPU + 2.0 + {90f0d09b-f58d-4f2e-ac8a-164d89979ef1} + 1.9.5.0 + + Documentation + Documentation + Documentation + + .\target\Help\ + ControlAPI + + + + + AutoDocumentCtors, AutoDocumentDispose + Robocode Control API for .NET + .NET Framework 3.5 + HtmlHelp1, Website + + + + + + + InheritedMembers, Protected, SealedProtected + + Control API used for controlling Robocode from an external .NET application. + Control API used for controlling Robocode from an external .NET application. + Control API used for controlling Robocode from an external .NET application. + + Copyright %28c%29 2001-2016 Mathew A. Nelson and Robocode contributors + fnl%40users.sourceforge.net + administator and maintainer of Robocode + Robocode Control API for .NET + vs2010 + + + + + + + + + + + + + + + + + + + + + + + + + + + ..\tools\lib\jni4net.n-0.8.7.0.dll + + + ..\robocode.dotnet.api\target\robocode.dll + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/pom.xml new file mode 100644 index 0000000..81f54e7 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + robocode.dotnet.control.api + Robocode .NET Control API + .NET Control API for Robocode + dotnet:library + + robocode.dotnet + net.sf.robocode + ${robocode.dotnet.version} + + + + net.sf.jni4net + jni4net.n + 0.8.7.0 + dotnet:library + + + net.sf.robocode + robocode.dotnet.api + ${project.version} + dotnet:library + + + + robocode.control + src + + + org.sonatype.nmaven.plugins + maven-dotnet-compiler-plugin + + /unsafe /warn:0 /nowarn:1591 /keyfile:"${basedir}/../tools/keys/robocode.snk" + robocode.control.dll + + + + org.jvnet.maven-antrun-extended-plugin + maven-antrun-extended-plugin + + + process-classes + + + + + + + + + + + run + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/robocode.dotnet.control.api.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/robocode.dotnet.control.api.iml new file mode 100644 index 0000000..64ccd25 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/robocode.dotnet.control.api.iml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/.gitignore b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/.gitignore new file mode 100644 index 0000000..dcb7ccb --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/.gitignore @@ -0,0 +1,3 @@ +/obj +/robocode.dotnet.control.api.sln +/robocode.dotnet.control.api.suo diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/java/util/Random.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/java/util/Random.generated.cs new file mode 100644 index 0000000..6b73e37 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/java/util/Random.generated.cs @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace java.util { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class Random : global::java.lang.Object, global::java.io.Serializable { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_nextInt0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_nextInt1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_nextLong2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_nextDouble3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_nextBoolean4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_nextBytes5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_nextFloat6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_nextGaussian7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setSeed8; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRandom9; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRandom10; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(J)V")] + public Random(long par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::java.util.Random.staticClass, global::java.util.Random.j4n__ctorRandom9, this, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public Random() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::java.util.Random.staticClass, global::java.util.Random.j4n__ctorRandom10, this); + } + } + + protected Random(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::java.util.Random.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::java.util.Random.staticClass = @__class; + global::java.util.Random.j4n_nextInt0 = @__env.GetMethodID(global::java.util.Random.staticClass, "nextInt", "(I)I"); + global::java.util.Random.j4n_nextInt1 = @__env.GetMethodID(global::java.util.Random.staticClass, "nextInt", "()I"); + global::java.util.Random.j4n_nextLong2 = @__env.GetMethodID(global::java.util.Random.staticClass, "nextLong", "()J"); + global::java.util.Random.j4n_nextDouble3 = @__env.GetMethodID(global::java.util.Random.staticClass, "nextDouble", "()D"); + global::java.util.Random.j4n_nextBoolean4 = @__env.GetMethodID(global::java.util.Random.staticClass, "nextBoolean", "()Z"); + global::java.util.Random.j4n_nextBytes5 = @__env.GetMethodID(global::java.util.Random.staticClass, "nextBytes", "([B)V"); + global::java.util.Random.j4n_nextFloat6 = @__env.GetMethodID(global::java.util.Random.staticClass, "nextFloat", "()F"); + global::java.util.Random.j4n_nextGaussian7 = @__env.GetMethodID(global::java.util.Random.staticClass, "nextGaussian", "()D"); + global::java.util.Random.j4n_setSeed8 = @__env.GetMethodID(global::java.util.Random.staticClass, "setSeed", "(J)V"); + global::java.util.Random.j4n__ctorRandom9 = @__env.GetMethodID(global::java.util.Random.staticClass, "", "(J)V"); + global::java.util.Random.j4n__ctorRandom10 = @__env.GetMethodID(global::java.util.Random.staticClass, "", "()V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(I)I")] + public virtual int nextInt(int par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((int)(@__env.CallIntMethod(this, global::java.util.Random.j4n_nextInt0, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int nextInt() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::java.util.Random.j4n_nextInt1))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()J")] + public virtual long nextLong() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((long)(@__env.CallLongMethod(this, global::java.util.Random.j4n_nextLong2))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + public virtual double nextDouble() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::java.util.Random.j4n_nextDouble3))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool nextBoolean() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::java.util.Random.j4n_nextBoolean4))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("([B)V")] + public virtual void nextBytes(byte[] par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::java.util.Random.j4n_nextBytes5, global::net.sf.jni4net.utils.Convertor.ParArrayPrimC2J(@__env, par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()F")] + public virtual float nextFloat() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((float)(@__env.CallFloatMethod(this, global::java.util.Random.j4n_nextFloat6))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + public virtual double nextGaussian() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::java.util.Random.j4n_nextGaussian7))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(J)V")] + public virtual void setSeed(long par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::java.util.Random.j4n_setSeed8, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::java.util.Random(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/BattleSpecification.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/BattleSpecification.generated.cs new file mode 100644 index 0000000..c714d62 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/BattleSpecification.generated.cs @@ -0,0 +1,207 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattleSpecification : global::java.lang.Object, global::java.io.Serializable { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getInactivityTime0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getGunCoolingRate1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getBattlefield2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getNumRounds3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getHideEnemyNames4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getSentryBorderSize5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobots6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getInitialSetups7; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleSpecification8; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleSpecification9; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleSpecification10; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleSpecification11; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleSpecification12; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(IJDLrobocode/control/BattlefieldSpecification;[Lrobocode/control/RobotSpecificat" + + "ion;)V")] + public BattleSpecification(int par0, long par1, double par2, global::robocode.control.BattlefieldSpecification par3, robocode.control.RobotSpecification[] par4) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 20)){ + @__env.NewObject(global::robocode.control.BattleSpecification.staticClass, global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification8, this, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par3), global::net.sf.jni4net.utils.Convertor.ParArrayStrongCp2J(@__env, par4)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(IJDZLrobocode/control/BattlefieldSpecification;[Lrobocode/control/RobotSpecifica" + + "tion;)V")] + public BattleSpecification(int par0, long par1, double par2, bool par3, global::robocode.control.BattlefieldSpecification par4, robocode.control.RobotSpecification[] par5) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 22)){ + @__env.NewObject(global::robocode.control.BattleSpecification.staticClass, global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification9, this, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par3), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par4), global::net.sf.jni4net.utils.Convertor.ParArrayStrongCp2J(@__env, par5)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/BattlefieldSpecification;IJDIZ[Lrobocode/control/RobotSpecific" + + "ation;)V")] + public BattleSpecification(global::robocode.control.BattlefieldSpecification par0, int par1, long par2, double par3, int par4, bool par5, robocode.control.RobotSpecification[] par6) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 24)){ + @__env.NewObject(global::robocode.control.BattleSpecification.staticClass, global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification10, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par3), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par4), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par5), global::net.sf.jni4net.utils.Convertor.ParArrayStrongCp2J(@__env, par6)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/BattlefieldSpecification;IJDIZ[Lrobocode/control/RobotSpecific" + + "ation;[Lrobocode/control/RobotSetup;)V")] + public BattleSpecification(global::robocode.control.BattlefieldSpecification par0, int par1, long par2, double par3, int par4, bool par5, robocode.control.RobotSpecification[] par6, robocode.control.RobotSetup[] par7) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 26)){ + @__env.NewObject(global::robocode.control.BattleSpecification.staticClass, global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification11, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par3), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par4), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par5), global::net.sf.jni4net.utils.Convertor.ParArrayStrongCp2J(@__env, par6), global::net.sf.jni4net.utils.Convertor.ParArrayStrongCp2J(@__env, par7)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(ILrobocode/control/BattlefieldSpecification;[Lrobocode/control/RobotSpecificatio" + + "n;)V")] + public BattleSpecification(int par0, global::robocode.control.BattlefieldSpecification par1, robocode.control.RobotSpecification[] par2) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + @__env.NewObject(global::robocode.control.BattleSpecification.staticClass, global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification12, this, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1), global::net.sf.jni4net.utils.Convertor.ParArrayStrongCp2J(@__env, par2)); + } + } + + protected BattleSpecification(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.BattleSpecification.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.BattleSpecification.staticClass = @__class; + global::robocode.control.BattleSpecification.j4n_getInactivityTime0 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "getInactivityTime", "()J"); + global::robocode.control.BattleSpecification.j4n_getGunCoolingRate1 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "getGunCoolingRate", "()D"); + global::robocode.control.BattleSpecification.j4n_getBattlefield2 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "getBattlefield", "()Lrobocode/control/BattlefieldSpecification;"); + global::robocode.control.BattleSpecification.j4n_getNumRounds3 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "getNumRounds", "()I"); + global::robocode.control.BattleSpecification.j4n_getHideEnemyNames4 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "getHideEnemyNames", "()Z"); + global::robocode.control.BattleSpecification.j4n_getSentryBorderSize5 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "getSentryBorderSize", "()I"); + global::robocode.control.BattleSpecification.j4n_getRobots6 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "getRobots", "()[Lrobocode/control/RobotSpecification;"); + global::robocode.control.BattleSpecification.j4n_getInitialSetups7 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "getInitialSetups", "()[Lrobocode/control/RobotSetup;"); + global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification8 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "", "(IJDLrobocode/control/BattlefieldSpecification;[Lrobocode/control/RobotSpecificat" + + "ion;)V"); + global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification9 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "", "(IJDZLrobocode/control/BattlefieldSpecification;[Lrobocode/control/RobotSpecifica" + + "tion;)V"); + global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification10 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "", "(Lrobocode/control/BattlefieldSpecification;IJDIZ[Lrobocode/control/RobotSpecific" + + "ation;)V"); + global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification11 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "", "(Lrobocode/control/BattlefieldSpecification;IJDIZ[Lrobocode/control/RobotSpecific" + + "ation;[Lrobocode/control/RobotSetup;)V"); + global::robocode.control.BattleSpecification.j4n__ctorBattleSpecification12 = @__env.GetMethodID(global::robocode.control.BattleSpecification.staticClass, "", "(ILrobocode/control/BattlefieldSpecification;[Lrobocode/control/RobotSpecificatio" + + "n;)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()J")] + public virtual long getInactivityTime() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((long)(@__env.CallLongMethod(this, global::robocode.control.BattleSpecification.j4n_getInactivityTime0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + public virtual double getGunCoolingRate() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.BattleSpecification.j4n_getGunCoolingRate1))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/control/BattlefieldSpecification;")] + public virtual global::robocode.control.BattlefieldSpecification getBattlefield() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.BattleSpecification.j4n_getBattlefield2)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getNumRounds() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.BattleSpecification.j4n_getNumRounds3))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool getHideEnemyNames() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.BattleSpecification.j4n_getHideEnemyNames4))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getSentryBorderSize() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.BattleSpecification.j4n_getSentryBorderSize5))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/RobotSpecification;")] + public virtual robocode.control.RobotSpecification[] getRobots() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.BattleSpecification.j4n_getRobots6)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/RobotSetup;")] + public virtual robocode.control.RobotSetup[] getInitialSetups() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.BattleSpecification.j4n_getInitialSetups7)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.BattleSpecification(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/BattlefieldSpecification.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/BattlefieldSpecification.generated.cs new file mode 100644 index 0000000..e7f0867 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/BattlefieldSpecification.generated.cs @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattlefieldSpecification : global::java.lang.Object, global::java.io.Serializable { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getWidth0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getHeight1; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattlefieldSpecification2; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattlefieldSpecification3; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public BattlefieldSpecification() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.control.BattlefieldSpecification.staticClass, global::robocode.control.BattlefieldSpecification.j4n__ctorBattlefieldSpecification2, this); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(II)V")] + public BattlefieldSpecification(int par0, int par1) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.NewObject(global::robocode.control.BattlefieldSpecification.staticClass, global::robocode.control.BattlefieldSpecification.j4n__ctorBattlefieldSpecification3, this, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + protected BattlefieldSpecification(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.BattlefieldSpecification.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.BattlefieldSpecification.staticClass = @__class; + global::robocode.control.BattlefieldSpecification.j4n_getWidth0 = @__env.GetMethodID(global::robocode.control.BattlefieldSpecification.staticClass, "getWidth", "()I"); + global::robocode.control.BattlefieldSpecification.j4n_getHeight1 = @__env.GetMethodID(global::robocode.control.BattlefieldSpecification.staticClass, "getHeight", "()I"); + global::robocode.control.BattlefieldSpecification.j4n__ctorBattlefieldSpecification2 = @__env.GetMethodID(global::robocode.control.BattlefieldSpecification.staticClass, "", "()V"); + global::robocode.control.BattlefieldSpecification.j4n__ctorBattlefieldSpecification3 = @__env.GetMethodID(global::robocode.control.BattlefieldSpecification.staticClass, "", "(II)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getWidth() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.BattlefieldSpecification.j4n_getWidth0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getHeight() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.BattlefieldSpecification.j4n_getHeight1))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.BattlefieldSpecification(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RandomFactory.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RandomFactory.generated.cs new file mode 100644 index 0000000..0309397 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RandomFactory.generated.cs @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RandomFactory : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isDeterministic0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRandom1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setRandom2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_resetDeterministic3; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRandomFactory4; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public RandomFactory() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.control.RandomFactory.staticClass, global::robocode.control.RandomFactory.j4n__ctorRandomFactory4, this); + } + } + + protected RandomFactory(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.RandomFactory.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.RandomFactory.staticClass = @__class; + global::robocode.control.RandomFactory.j4n_isDeterministic0 = @__env.GetMethodID(global::robocode.control.RandomFactory.staticClass, "isDeterministic", "()Z"); + global::robocode.control.RandomFactory.j4n_getRandom1 = @__env.GetStaticMethodID(global::robocode.control.RandomFactory.staticClass, "getRandom", "()Ljava/util/Random;"); + global::robocode.control.RandomFactory.j4n_setRandom2 = @__env.GetStaticMethodID(global::robocode.control.RandomFactory.staticClass, "setRandom", "(Ljava/util/Random;)V"); + global::robocode.control.RandomFactory.j4n_resetDeterministic3 = @__env.GetStaticMethodID(global::robocode.control.RandomFactory.staticClass, "resetDeterministic", "(J)V"); + global::robocode.control.RandomFactory.j4n__ctorRandomFactory4 = @__env.GetMethodID(global::robocode.control.RandomFactory.staticClass, "", "()V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isDeterministic() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.RandomFactory.j4n_isDeterministic0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/util/Random;")] + public static global::java.util.Random getRandom() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.RandomFactory.staticClass, global::robocode.control.RandomFactory.j4n_getRandom1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/util/Random;)V")] + public static void setRandom(global::java.util.Random par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::robocode.control.RandomFactory.staticClass, global::robocode.control.RandomFactory.j4n_setRandom2, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(J)V")] + public static void resetDeterministic(long par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::robocode.control.RandomFactory.staticClass, global::robocode.control.RandomFactory.j4n_resetDeterministic3, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.RandomFactory(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobocodeEngine.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobocodeEngine.generated.cs new file mode 100644 index 0000000..fe32567 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobocodeEngine.generated.cs @@ -0,0 +1,296 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RobocodeEngine : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_close0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVersion1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_addBattleListener2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_removeBattleListener3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setVisible4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getLocalRepository5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getLocalRepository6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_runBattle7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_runBattle8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_runBattle9; + + internal static global::net.sf.jni4net.jni.MethodId j4n_waitTillBattleOver10; + + internal static global::net.sf.jni4net.jni.MethodId j4n_abortCurrentBattle11; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getCurrentWorkingDir12; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobotsDir13; + + internal static global::net.sf.jni4net.jni.MethodId j4n_printRunningThreads14; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setLogMessagesEnabled15; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setLogErrorsEnabled16; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobocodeEngine17; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobocodeEngine18; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobocodeEngine19; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobocodeEngine20; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobocodeEngine21; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/io/File;)V")] + public RobocodeEngine(global::java.io.File par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine17, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/io/File;Lrobocode/control/RobocodeListener;)V")] + public RobocodeEngine(global::java.io.File par0, global::java.lang.Object par1) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.NewObject(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine18, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/RobocodeListener;)V")] + public RobocodeEngine(global::java.lang.Object par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine19, this, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/IBattleListener;)V")] + public RobocodeEngine(global::robocode.control.events.IBattleListener par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine20, this, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public RobocodeEngine() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine21, this); + } + } + + protected RobocodeEngine(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.RobocodeEngine.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.RobocodeEngine.staticClass = @__class; + global::robocode.control.RobocodeEngine.j4n_close0 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "close", "()V"); + global::robocode.control.RobocodeEngine.j4n_getVersion1 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "getVersion", "()Ljava/lang/String;"); + global::robocode.control.RobocodeEngine.j4n_addBattleListener2 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "addBattleListener", "(Lrobocode/control/events/IBattleListener;)V"); + global::robocode.control.RobocodeEngine.j4n_removeBattleListener3 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "removeBattleListener", "(Lrobocode/control/events/IBattleListener;)V"); + global::robocode.control.RobocodeEngine.j4n_setVisible4 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "setVisible", "(Z)V"); + global::robocode.control.RobocodeEngine.j4n_getLocalRepository5 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "getLocalRepository", "()[Lrobocode/control/RobotSpecification;"); + global::robocode.control.RobocodeEngine.j4n_getLocalRepository6 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "getLocalRepository", "(Ljava/lang/String;)[Lrobocode/control/RobotSpecification;"); + global::robocode.control.RobocodeEngine.j4n_runBattle7 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "runBattle", "(Lrobocode/control/BattleSpecification;Z)V"); + global::robocode.control.RobocodeEngine.j4n_runBattle8 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "runBattle", "(Lrobocode/control/BattleSpecification;Ljava/lang/String;Z)V"); + global::robocode.control.RobocodeEngine.j4n_runBattle9 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "runBattle", "(Lrobocode/control/BattleSpecification;)V"); + global::robocode.control.RobocodeEngine.j4n_waitTillBattleOver10 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "waitTillBattleOver", "()V"); + global::robocode.control.RobocodeEngine.j4n_abortCurrentBattle11 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "abortCurrentBattle", "()V"); + global::robocode.control.RobocodeEngine.j4n_getCurrentWorkingDir12 = @__env.GetStaticMethodID(global::robocode.control.RobocodeEngine.staticClass, "getCurrentWorkingDir", "()Ljava/io/File;"); + global::robocode.control.RobocodeEngine.j4n_getRobotsDir13 = @__env.GetStaticMethodID(global::robocode.control.RobocodeEngine.staticClass, "getRobotsDir", "()Ljava/io/File;"); + global::robocode.control.RobocodeEngine.j4n_printRunningThreads14 = @__env.GetStaticMethodID(global::robocode.control.RobocodeEngine.staticClass, "printRunningThreads", "()V"); + global::robocode.control.RobocodeEngine.j4n_setLogMessagesEnabled15 = @__env.GetStaticMethodID(global::robocode.control.RobocodeEngine.staticClass, "setLogMessagesEnabled", "(Z)V"); + global::robocode.control.RobocodeEngine.j4n_setLogErrorsEnabled16 = @__env.GetStaticMethodID(global::robocode.control.RobocodeEngine.staticClass, "setLogErrorsEnabled", "(Z)V"); + global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine17 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "", "(Ljava/io/File;)V"); + global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine18 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "", "(Ljava/io/File;Lrobocode/control/RobocodeListener;)V"); + global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine19 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "", "(Lrobocode/control/RobocodeListener;)V"); + global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine20 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "", "(Lrobocode/control/events/IBattleListener;)V"); + global::robocode.control.RobocodeEngine.j4n__ctorRobocodeEngine21 = @__env.GetMethodID(global::robocode.control.RobocodeEngine.staticClass, "", "()V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public virtual void close() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::robocode.control.RobocodeEngine.j4n_close0); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobocodeEngine.j4n_getVersion1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/IBattleListener;)V")] + public virtual void addBattleListener(global::robocode.control.events.IBattleListener par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.RobocodeEngine.j4n_addBattleListener2, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/IBattleListener;)V")] + public virtual void removeBattleListener(global::robocode.control.events.IBattleListener par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.RobocodeEngine.j4n_removeBattleListener3, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Z)V")] + public virtual void setVisible(bool par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.RobocodeEngine.j4n_setVisible4, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/RobotSpecification;")] + public virtual robocode.control.RobotSpecification[] getLocalRepository() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobocodeEngine.j4n_getLocalRepository5)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)[Lrobocode/control/RobotSpecification;")] + public virtual robocode.control.RobotSpecification[] getLocalRepository(global::java.lang.String par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobocodeEngine.j4n_getLocalRepository6, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/BattleSpecification;Z)V")] + public virtual void runBattle(global::robocode.control.BattleSpecification par0, bool par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::robocode.control.RobocodeEngine.j4n_runBattle7, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/BattleSpecification;Ljava/lang/String;Z)V")] + public virtual void runBattle(global::robocode.control.BattleSpecification par0, global::java.lang.String par1, bool par2) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + @__env.CallVoidMethod(this, global::robocode.control.RobocodeEngine.j4n_runBattle8, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/BattleSpecification;)V")] + public virtual void runBattle(global::robocode.control.BattleSpecification par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.RobocodeEngine.j4n_runBattle9, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public virtual void waitTillBattleOver() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::robocode.control.RobocodeEngine.j4n_waitTillBattleOver10); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public virtual void abortCurrentBattle() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::robocode.control.RobocodeEngine.j4n_abortCurrentBattle11); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/io/File;")] + public static global::java.io.File getCurrentWorkingDir() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n_getCurrentWorkingDir12)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/io/File;")] + public static global::java.io.File getRobotsDir() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n_getRobotsDir13)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public static void printRunningThreads() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallStaticVoidMethod(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n_printRunningThreads14); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Z)V")] + public static void setLogMessagesEnabled(bool par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n_setLogMessagesEnabled15, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Z)V")] + public static void setLogErrorsEnabled(bool par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::robocode.control.RobocodeEngine.staticClass, global::robocode.control.RobocodeEngine.j4n_setLogErrorsEnabled16, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.RobocodeEngine(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotResults.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotResults.generated.cs new file mode 100644 index 0000000..7f246be --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotResults.generated.cs @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RobotResults : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobot0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_convertResults1; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobotResults2; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobotResults3; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/RobotSpecification;Ljava/lang/String;IDDDDDDDIII)V")] + public RobotResults(global::robocode.control.RobotSpecification par0, global::java.lang.String par1, int par2, double par3, double par4, double par5, double par6, double par7, double par8, double par9, int par10, int par11, int par12) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 36)){ + @__env.NewObject(global::robocode.control.RobotResults.staticClass, global::robocode.control.RobotResults.j4n__ctorRobotResults2, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par3), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par4), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par5), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par6), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par7), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par8), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par9), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par10), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par11), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par12)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/RobotSpecification;Lrobocode/BattleResults;)V")] + public RobotResults(global::robocode.control.RobotSpecification par0, global::java.lang.Object par1) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.NewObject(global::robocode.control.RobotResults.staticClass, global::robocode.control.RobotResults.j4n__ctorRobotResults3, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1)); + } + } + + protected RobotResults(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.RobotResults.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.RobotResults.staticClass = @__class; + global::robocode.control.RobotResults.j4n_getRobot0 = @__env.GetMethodID(global::robocode.control.RobotResults.staticClass, "getRobot", "()Lrobocode/control/RobotSpecification;"); + global::robocode.control.RobotResults.j4n_convertResults1 = @__env.GetStaticMethodID(global::robocode.control.RobotResults.staticClass, "convertResults", "([Lrobocode/BattleResults;)[Lrobocode/control/RobotResults;"); + global::robocode.control.RobotResults.j4n__ctorRobotResults2 = @__env.GetMethodID(global::robocode.control.RobotResults.staticClass, "", "(Lrobocode/control/RobotSpecification;Ljava/lang/String;IDDDDDDDIII)V"); + global::robocode.control.RobotResults.j4n__ctorRobotResults3 = @__env.GetMethodID(global::robocode.control.RobotResults.staticClass, "", "(Lrobocode/control/RobotSpecification;Lrobocode/BattleResults;)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/control/RobotSpecification;")] + public virtual global::robocode.control.RobotSpecification getRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotResults.j4n_getRobot0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("([Lrobocode/BattleResults;)[Lrobocode/control/RobotResults;")] + public static robocode.control.RobotResults[] convertResults(java.lang.Object[] par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.RobotResults.staticClass, global::robocode.control.RobotResults.j4n_convertResults1, global::net.sf.jni4net.utils.Convertor.ParArrayStrongCp2J(@__env, par0))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.RobotResults(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotSetup.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotSetup.generated.cs new file mode 100644 index 0000000..38ee1c2 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotSetup.generated.cs @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RobotSetup : global::java.lang.Object, global::java.io.Serializable { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getX0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getY1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getHeading2; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobotSetup3; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/Double;Ljava/lang/Double;Ljava/lang/Double;)V")] + public RobotSetup(global::java.lang.Double par0, global::java.lang.Double par1, global::java.lang.Double par2) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + @__env.NewObject(global::robocode.control.RobotSetup.staticClass, global::robocode.control.RobotSetup.j4n__ctorRobotSetup3, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par2)); + } + } + + protected RobotSetup(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.RobotSetup.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.RobotSetup.staticClass = @__class; + global::robocode.control.RobotSetup.j4n_getX0 = @__env.GetMethodID(global::robocode.control.RobotSetup.staticClass, "getX", "()Ljava/lang/Double;"); + global::robocode.control.RobotSetup.j4n_getY1 = @__env.GetMethodID(global::robocode.control.RobotSetup.staticClass, "getY", "()Ljava/lang/Double;"); + global::robocode.control.RobotSetup.j4n_getHeading2 = @__env.GetMethodID(global::robocode.control.RobotSetup.staticClass, "getHeading", "()Ljava/lang/Double;"); + global::robocode.control.RobotSetup.j4n__ctorRobotSetup3 = @__env.GetMethodID(global::robocode.control.RobotSetup.staticClass, "", "(Ljava/lang/Double;Ljava/lang/Double;Ljava/lang/Double;)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/Double;")] + public virtual global::java.lang.Double getX() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSetup.j4n_getX0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/Double;")] + public virtual global::java.lang.Double getY() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSetup.j4n_getY1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/Double;")] + public virtual global::java.lang.Double getHeading() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSetup.j4n_getHeading2)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.RobotSetup(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotSpecification.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotSpecification.generated.cs new file mode 100644 index 0000000..6978fbc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/RobotSpecification.generated.cs @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RobotSpecification : global::java.lang.Object, global::java.io.Serializable { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getName0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getClassName1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getJarFile2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVersion3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getNameAndVersion4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getDescription5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobocodeVersion6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getWebpage7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getAuthorName8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTeamId9; + + protected RobotSpecification(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.RobotSpecification.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.RobotSpecification.staticClass = @__class; + global::robocode.control.RobotSpecification.j4n_getName0 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getName", "()Ljava/lang/String;"); + global::robocode.control.RobotSpecification.j4n_getClassName1 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getClassName", "()Ljava/lang/String;"); + global::robocode.control.RobotSpecification.j4n_getJarFile2 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getJarFile", "()Ljava/io/File;"); + global::robocode.control.RobotSpecification.j4n_getVersion3 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getVersion", "()Ljava/lang/String;"); + global::robocode.control.RobotSpecification.j4n_getNameAndVersion4 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getNameAndVersion", "()Ljava/lang/String;"); + global::robocode.control.RobotSpecification.j4n_getDescription5 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getDescription", "()Ljava/lang/String;"); + global::robocode.control.RobotSpecification.j4n_getRobocodeVersion6 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getRobocodeVersion", "()Ljava/lang/String;"); + global::robocode.control.RobotSpecification.j4n_getWebpage7 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getWebpage", "()Ljava/lang/String;"); + global::robocode.control.RobotSpecification.j4n_getAuthorName8 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getAuthorName", "()Ljava/lang/String;"); + global::robocode.control.RobotSpecification.j4n_getTeamId9 = @__env.GetMethodID(global::robocode.control.RobotSpecification.staticClass, "getTeamId", "()Ljava/lang/String;"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getName0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getClassName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getClassName1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/io/File;")] + public virtual global::java.io.File getJarFile() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getJarFile2)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getVersion3)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getNameAndVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getNameAndVersion4)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getDescription() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getDescription5)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getRobocodeVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getRobocodeVersion6)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getWebpage() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getWebpage7)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getAuthorName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getAuthorName8)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getTeamId() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.RobotSpecification.j4n_getTeamId9)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.RobotSpecification(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleCompletedEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleCompletedEvent.generated.cs new file mode 100644 index 0000000..025761f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleCompletedEvent.generated.cs @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattleCompletedEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getBattleRules0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getSortedResults1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getIndexedResults2; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleCompletedEvent3; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/BattleRules;[Lrobocode/BattleResults;)V")] + public BattleCompletedEvent(global::java.lang.Object par0, java.lang.Object[] par1) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.NewObject(global::robocode.control.events.BattleCompletedEvent.staticClass, global::robocode.control.events.BattleCompletedEvent.j4n__ctorBattleCompletedEvent3, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParArrayStrongCp2J(@__env, par1)); + } + } + + protected BattleCompletedEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.BattleCompletedEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.BattleCompletedEvent.staticClass = @__class; + global::robocode.control.events.BattleCompletedEvent.j4n_getBattleRules0 = @__env.GetMethodID(global::robocode.control.events.BattleCompletedEvent.staticClass, "getBattleRules", "()Lrobocode/BattleRules;"); + global::robocode.control.events.BattleCompletedEvent.j4n_getSortedResults1 = @__env.GetMethodID(global::robocode.control.events.BattleCompletedEvent.staticClass, "getSortedResults", "()[Lrobocode/BattleResults;"); + global::robocode.control.events.BattleCompletedEvent.j4n_getIndexedResults2 = @__env.GetMethodID(global::robocode.control.events.BattleCompletedEvent.staticClass, "getIndexedResults", "()[Lrobocode/BattleResults;"); + global::robocode.control.events.BattleCompletedEvent.j4n__ctorBattleCompletedEvent3 = @__env.GetMethodID(global::robocode.control.events.BattleCompletedEvent.staticClass, "", "(Lrobocode/BattleRules;[Lrobocode/BattleResults;)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/BattleRules;")] + public virtual global::java.lang.Object getBattleRules() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.events.BattleCompletedEvent.j4n_getBattleRules0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/BattleResults;")] + public virtual java.lang.Object[] getSortedResults() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.events.BattleCompletedEvent.j4n_getSortedResults1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/BattleResults;")] + public virtual java.lang.Object[] getIndexedResults() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.events.BattleCompletedEvent.j4n_getIndexedResults2)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.BattleCompletedEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleErrorEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleErrorEvent.generated.cs new file mode 100644 index 0000000..0b4b42d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleErrorEvent.generated.cs @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattleErrorEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getError0; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleErrorEvent1; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public BattleErrorEvent(global::java.lang.String par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.control.events.BattleErrorEvent.staticClass, global::robocode.control.events.BattleErrorEvent.j4n__ctorBattleErrorEvent1, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + protected BattleErrorEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.BattleErrorEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.BattleErrorEvent.staticClass = @__class; + global::robocode.control.events.BattleErrorEvent.j4n_getError0 = @__env.GetMethodID(global::robocode.control.events.BattleErrorEvent.staticClass, "getError", "()Ljava/lang/String;"); + global::robocode.control.events.BattleErrorEvent.j4n__ctorBattleErrorEvent1 = @__env.GetMethodID(global::robocode.control.events.BattleErrorEvent.staticClass, "", "(Ljava/lang/String;)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getError() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.events.BattleErrorEvent.j4n_getError0)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.BattleErrorEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleEvent.generated.cs new file mode 100644 index 0000000..0698cd0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleEvent.generated.cs @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattleEvent : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + protected BattleEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.BattleEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.BattleEvent.staticClass = @__class; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.BattleEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleFinishedEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleFinishedEvent.generated.cs new file mode 100644 index 0000000..af8c2a8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleFinishedEvent.generated.cs @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattleFinishedEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isAborted0; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleFinishedEvent1; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Z)V")] + public BattleFinishedEvent(bool par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.control.events.BattleFinishedEvent.staticClass, global::robocode.control.events.BattleFinishedEvent.j4n__ctorBattleFinishedEvent1, this, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + protected BattleFinishedEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.BattleFinishedEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.BattleFinishedEvent.staticClass = @__class; + global::robocode.control.events.BattleFinishedEvent.j4n_isAborted0 = @__env.GetMethodID(global::robocode.control.events.BattleFinishedEvent.staticClass, "isAborted", "()Z"); + global::robocode.control.events.BattleFinishedEvent.j4n__ctorBattleFinishedEvent1 = @__env.GetMethodID(global::robocode.control.events.BattleFinishedEvent.staticClass, "", "(Z)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isAborted() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.events.BattleFinishedEvent.j4n_isAborted0))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.BattleFinishedEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleMessageEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleMessageEvent.generated.cs new file mode 100644 index 0000000..27bf827 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleMessageEvent.generated.cs @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattleMessageEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getMessage0; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleMessageEvent1; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public BattleMessageEvent(global::java.lang.String par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.control.events.BattleMessageEvent.staticClass, global::robocode.control.events.BattleMessageEvent.j4n__ctorBattleMessageEvent1, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + protected BattleMessageEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.BattleMessageEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.BattleMessageEvent.staticClass = @__class; + global::robocode.control.events.BattleMessageEvent.j4n_getMessage0 = @__env.GetMethodID(global::robocode.control.events.BattleMessageEvent.staticClass, "getMessage", "()Ljava/lang/String;"); + global::robocode.control.events.BattleMessageEvent.j4n__ctorBattleMessageEvent1 = @__env.GetMethodID(global::robocode.control.events.BattleMessageEvent.staticClass, "", "(Ljava/lang/String;)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + public virtual global::java.lang.String getMessage() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.events.BattleMessageEvent.j4n_getMessage0)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.BattleMessageEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattlePausedEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattlePausedEvent.generated.cs new file mode 100644 index 0000000..4cb8dfd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattlePausedEvent.generated.cs @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattlePausedEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattlePausedEvent0; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public BattlePausedEvent() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.control.events.BattlePausedEvent.staticClass, global::robocode.control.events.BattlePausedEvent.j4n__ctorBattlePausedEvent0, this); + } + } + + protected BattlePausedEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.BattlePausedEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.BattlePausedEvent.staticClass = @__class; + global::robocode.control.events.BattlePausedEvent.j4n__ctorBattlePausedEvent0 = @__env.GetMethodID(global::robocode.control.events.BattlePausedEvent.staticClass, "", "()V"); + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.BattlePausedEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleResumedEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleResumedEvent.generated.cs new file mode 100644 index 0000000..e3de918 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleResumedEvent.generated.cs @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattleResumedEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleResumedEvent0; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public BattleResumedEvent() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.control.events.BattleResumedEvent.staticClass, global::robocode.control.events.BattleResumedEvent.j4n__ctorBattleResumedEvent0, this); + } + } + + protected BattleResumedEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.BattleResumedEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.BattleResumedEvent.staticClass = @__class; + global::robocode.control.events.BattleResumedEvent.j4n__ctorBattleResumedEvent0 = @__env.GetMethodID(global::robocode.control.events.BattleResumedEvent.staticClass, "", "()V"); + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.BattleResumedEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleStartedEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleStartedEvent.generated.cs new file mode 100644 index 0000000..5efc401 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/BattleStartedEvent.generated.cs @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BattleStartedEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getBattleRules0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isReplay1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobotsCount2; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorBattleStartedEvent3; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/BattleRules;IZ)V")] + public BattleStartedEvent(global::java.lang.Object par0, int par1, bool par2) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + @__env.NewObject(global::robocode.control.events.BattleStartedEvent.staticClass, global::robocode.control.events.BattleStartedEvent.j4n__ctorBattleStartedEvent3, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2)); + } + } + + protected BattleStartedEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.BattleStartedEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.BattleStartedEvent.staticClass = @__class; + global::robocode.control.events.BattleStartedEvent.j4n_getBattleRules0 = @__env.GetMethodID(global::robocode.control.events.BattleStartedEvent.staticClass, "getBattleRules", "()Lrobocode/BattleRules;"); + global::robocode.control.events.BattleStartedEvent.j4n_isReplay1 = @__env.GetMethodID(global::robocode.control.events.BattleStartedEvent.staticClass, "isReplay", "()Z"); + global::robocode.control.events.BattleStartedEvent.j4n_getRobotsCount2 = @__env.GetMethodID(global::robocode.control.events.BattleStartedEvent.staticClass, "getRobotsCount", "()I"); + global::robocode.control.events.BattleStartedEvent.j4n__ctorBattleStartedEvent3 = @__env.GetMethodID(global::robocode.control.events.BattleStartedEvent.staticClass, "", "(Lrobocode/BattleRules;IZ)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/BattleRules;")] + public virtual global::java.lang.Object getBattleRules() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.events.BattleStartedEvent.j4n_getBattleRules0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isReplay() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.events.BattleStartedEvent.j4n_isReplay1))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getRobotsCount() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.events.BattleStartedEvent.j4n_getRobotsCount2))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.BattleStartedEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/IBattleListener.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/IBattleListener.generated.cs new file mode 100644 index 0000000..bc05339 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/IBattleListener.generated.cs @@ -0,0 +1,331 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IBattleListener { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/BattleStartedEvent;)V")] + void onBattleStarted(global::robocode.control.events.BattleStartedEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/BattleFinishedEvent;)V")] + void onBattleFinished(global::robocode.control.events.BattleFinishedEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/BattleCompletedEvent;)V")] + void onBattleCompleted(global::robocode.control.events.BattleCompletedEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/BattlePausedEvent;)V")] + void onBattlePaused(global::robocode.control.events.BattlePausedEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/BattleResumedEvent;)V")] + void onBattleResumed(global::robocode.control.events.BattleResumedEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/RoundStartedEvent;)V")] + void onRoundStarted(global::robocode.control.events.RoundStartedEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/RoundEndedEvent;)V")] + void onRoundEnded(global::robocode.control.events.RoundEndedEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/TurnStartedEvent;)V")] + void onTurnStarted(global::robocode.control.events.TurnStartedEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/TurnEndedEvent;)V")] + void onTurnEnded(global::robocode.control.events.TurnEndedEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/BattleMessageEvent;)V")] + void onBattleMessage(global::robocode.control.events.BattleMessageEvent par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/BattleErrorEvent;)V")] + void onBattleError(global::robocode.control.events.BattleErrorEvent par0); + } + #endregion + + #region Component Designer generated code + public partial class IBattleListener_ { + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.@__IBattleListener.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::robocode.control.events.IBattleListener), typeof(global::robocode.control.events.IBattleListener_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::robocode.control.events.IBattleListener), typeof(global::robocode.control.events.IBattleListener_))] + internal sealed partial class @__IBattleListener : global::java.lang.Object, global::robocode.control.events.IBattleListener { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onBattleStarted0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onBattleFinished1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onBattleCompleted2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onBattlePaused3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onBattleResumed4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onRoundStarted5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onRoundEnded6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onTurnStarted7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onTurnEnded8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onBattleMessage9; + + internal static global::net.sf.jni4net.jni.MethodId j4n_onBattleError10; + + private @__IBattleListener(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.@__IBattleListener.staticClass = @__class; + global::robocode.control.events.@__IBattleListener.j4n_onBattleStarted0 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onBattleStarted", "(Lrobocode/control/events/BattleStartedEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onBattleFinished1 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onBattleFinished", "(Lrobocode/control/events/BattleFinishedEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onBattleCompleted2 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onBattleCompleted", "(Lrobocode/control/events/BattleCompletedEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onBattlePaused3 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onBattlePaused", "(Lrobocode/control/events/BattlePausedEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onBattleResumed4 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onBattleResumed", "(Lrobocode/control/events/BattleResumedEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onRoundStarted5 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onRoundStarted", "(Lrobocode/control/events/RoundStartedEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onRoundEnded6 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onRoundEnded", "(Lrobocode/control/events/RoundEndedEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onTurnStarted7 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onTurnStarted", "(Lrobocode/control/events/TurnStartedEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onTurnEnded8 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onTurnEnded", "(Lrobocode/control/events/TurnEndedEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onBattleMessage9 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onBattleMessage", "(Lrobocode/control/events/BattleMessageEvent;)V"); + global::robocode.control.events.@__IBattleListener.j4n_onBattleError10 = @__env.GetMethodID(global::robocode.control.events.@__IBattleListener.staticClass, "onBattleError", "(Lrobocode/control/events/BattleErrorEvent;)V"); + } + + public void onBattleStarted(global::robocode.control.events.BattleStartedEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onBattleStarted0, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onBattleFinished(global::robocode.control.events.BattleFinishedEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onBattleFinished1, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onBattleCompleted(global::robocode.control.events.BattleCompletedEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onBattleCompleted2, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onBattlePaused(global::robocode.control.events.BattlePausedEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onBattlePaused3, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onBattleResumed(global::robocode.control.events.BattleResumedEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onBattleResumed4, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onRoundStarted(global::robocode.control.events.RoundStartedEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onRoundStarted5, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onRoundEnded(global::robocode.control.events.RoundEndedEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onRoundEnded6, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onTurnStarted(global::robocode.control.events.TurnStartedEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onTurnStarted7, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onTurnEnded(global::robocode.control.events.TurnEndedEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onTurnEnded8, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onBattleMessage(global::robocode.control.events.BattleMessageEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onBattleMessage9, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void onBattleError(global::robocode.control.events.BattleErrorEvent par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::robocode.control.events.@__IBattleListener.j4n_onBattleError10, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IBattleListener); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onBattleStarted", "onBattleStarted0", "(Lrobocode/control/events/BattleStartedEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onBattleFinished", "onBattleFinished1", "(Lrobocode/control/events/BattleFinishedEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onBattleCompleted", "onBattleCompleted2", "(Lrobocode/control/events/BattleCompletedEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onBattlePaused", "onBattlePaused3", "(Lrobocode/control/events/BattlePausedEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onBattleResumed", "onBattleResumed4", "(Lrobocode/control/events/BattleResumedEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onRoundStarted", "onRoundStarted5", "(Lrobocode/control/events/RoundStartedEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onRoundEnded", "onRoundEnded6", "(Lrobocode/control/events/RoundEndedEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onTurnStarted", "onTurnStarted7", "(Lrobocode/control/events/TurnStartedEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onTurnEnded", "onTurnEnded8", "(Lrobocode/control/events/TurnEndedEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onBattleMessage", "onBattleMessage9", "(Lrobocode/control/events/BattleMessageEvent;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "onBattleError", "onBattleError10", "(Lrobocode/control/events/BattleErrorEvent;)V")); + return methods; + } + + private static void onBattleStarted0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/BattleStartedEvent;)V + // (Lrobocode/control/events/BattleStartedEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onBattleStarted(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onBattleFinished1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/BattleFinishedEvent;)V + // (Lrobocode/control/events/BattleFinishedEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onBattleFinished(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onBattleCompleted2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/BattleCompletedEvent;)V + // (Lrobocode/control/events/BattleCompletedEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onBattleCompleted(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onBattlePaused3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/BattlePausedEvent;)V + // (Lrobocode/control/events/BattlePausedEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onBattlePaused(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onBattleResumed4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/BattleResumedEvent;)V + // (Lrobocode/control/events/BattleResumedEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onBattleResumed(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onRoundStarted5(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/RoundStartedEvent;)V + // (Lrobocode/control/events/RoundStartedEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onRoundStarted(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onRoundEnded6(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/RoundEndedEvent;)V + // (Lrobocode/control/events/RoundEndedEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onRoundEnded(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onTurnStarted7(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/TurnStartedEvent;)V + // (Lrobocode/control/events/TurnStartedEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onTurnStarted(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onTurnEnded8(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/TurnEndedEvent;)V + // (Lrobocode/control/events/TurnEndedEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onTurnEnded(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onBattleMessage9(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/BattleMessageEvent;)V + // (Lrobocode/control/events/BattleMessageEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onBattleMessage(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void onBattleError10(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lrobocode/control/events/BattleErrorEvent;)V + // (Lrobocode/control/events/BattleErrorEvent;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::robocode.control.events.IBattleListener @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.onBattleError(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.@__IBattleListener(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/RoundEndedEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/RoundEndedEvent.generated.cs new file mode 100644 index 0000000..570931f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/RoundEndedEvent.generated.cs @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RoundEndedEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRound0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTurns1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalTurns2; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRoundEndedEvent3; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(III)V")] + public RoundEndedEvent(int par0, int par1, int par2) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + @__env.NewObject(global::robocode.control.events.RoundEndedEvent.staticClass, global::robocode.control.events.RoundEndedEvent.j4n__ctorRoundEndedEvent3, this, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2)); + } + } + + protected RoundEndedEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.RoundEndedEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.RoundEndedEvent.staticClass = @__class; + global::robocode.control.events.RoundEndedEvent.j4n_getRound0 = @__env.GetMethodID(global::robocode.control.events.RoundEndedEvent.staticClass, "getRound", "()I"); + global::robocode.control.events.RoundEndedEvent.j4n_getTurns1 = @__env.GetMethodID(global::robocode.control.events.RoundEndedEvent.staticClass, "getTurns", "()I"); + global::robocode.control.events.RoundEndedEvent.j4n_getTotalTurns2 = @__env.GetMethodID(global::robocode.control.events.RoundEndedEvent.staticClass, "getTotalTurns", "()I"); + global::robocode.control.events.RoundEndedEvent.j4n__ctorRoundEndedEvent3 = @__env.GetMethodID(global::robocode.control.events.RoundEndedEvent.staticClass, "", "(III)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getRound() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.events.RoundEndedEvent.j4n_getRound0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getTurns() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.events.RoundEndedEvent.j4n_getTurns1))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getTotalTurns() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.events.RoundEndedEvent.j4n_getTotalTurns2))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.RoundEndedEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/RoundStartedEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/RoundStartedEvent.generated.cs new file mode 100644 index 0000000..0ffd0f6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/RoundStartedEvent.generated.cs @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RoundStartedEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRound0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getStartSnapshot1; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRoundStartedEvent2; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/snapshot/ITurnSnapshot;I)V")] + public RoundStartedEvent(global::robocode.control.snapshot.ITurnSnapshot par0, int par1) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.NewObject(global::robocode.control.events.RoundStartedEvent.staticClass, global::robocode.control.events.RoundStartedEvent.j4n__ctorRoundStartedEvent2, this, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + protected RoundStartedEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.RoundStartedEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.RoundStartedEvent.staticClass = @__class; + global::robocode.control.events.RoundStartedEvent.j4n_getRound0 = @__env.GetMethodID(global::robocode.control.events.RoundStartedEvent.staticClass, "getRound", "()I"); + global::robocode.control.events.RoundStartedEvent.j4n_getStartSnapshot1 = @__env.GetMethodID(global::robocode.control.events.RoundStartedEvent.staticClass, "getStartSnapshot", "()Lrobocode/control/snapshot/ITurnSnapshot;"); + global::robocode.control.events.RoundStartedEvent.j4n__ctorRoundStartedEvent2 = @__env.GetMethodID(global::robocode.control.events.RoundStartedEvent.staticClass, "", "(Lrobocode/control/snapshot/ITurnSnapshot;I)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getRound() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.events.RoundStartedEvent.j4n_getRound0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/control/snapshot/ITurnSnapshot;")] + public virtual global::robocode.control.snapshot.ITurnSnapshot getStartSnapshot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.events.RoundStartedEvent.j4n_getStartSnapshot1)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.RoundStartedEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/TurnEndedEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/TurnEndedEvent.generated.cs new file mode 100644 index 0000000..032500a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/TurnEndedEvent.generated.cs @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class TurnEndedEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTurnSnapshot0; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorTurnEndedEvent1; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/snapshot/ITurnSnapshot;)V")] + public TurnEndedEvent(global::robocode.control.snapshot.ITurnSnapshot par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.control.events.TurnEndedEvent.staticClass, global::robocode.control.events.TurnEndedEvent.j4n__ctorTurnEndedEvent1, this, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)); + } + } + + protected TurnEndedEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.TurnEndedEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.TurnEndedEvent.staticClass = @__class; + global::robocode.control.events.TurnEndedEvent.j4n_getTurnSnapshot0 = @__env.GetMethodID(global::robocode.control.events.TurnEndedEvent.staticClass, "getTurnSnapshot", "()Lrobocode/control/snapshot/ITurnSnapshot;"); + global::robocode.control.events.TurnEndedEvent.j4n__ctorTurnEndedEvent1 = @__env.GetMethodID(global::robocode.control.events.TurnEndedEvent.staticClass, "", "(Lrobocode/control/snapshot/ITurnSnapshot;)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/control/snapshot/ITurnSnapshot;")] + public virtual global::robocode.control.snapshot.ITurnSnapshot getTurnSnapshot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.events.TurnEndedEvent.j4n_getTurnSnapshot0)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.TurnEndedEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/TurnStartedEvent.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/TurnStartedEvent.generated.cs new file mode 100644 index 0000000..118276b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/events/TurnStartedEvent.generated.cs @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.events { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class TurnStartedEvent : global::robocode.control.events.BattleEvent { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorTurnStartedEvent0; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public TurnStartedEvent() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.control.events.TurnStartedEvent.staticClass, global::robocode.control.events.TurnStartedEvent.j4n__ctorTurnStartedEvent0, this); + } + } + + protected TurnStartedEvent(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.events.TurnStartedEvent.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.events.TurnStartedEvent.staticClass = @__class; + global::robocode.control.events.TurnStartedEvent.j4n__ctorTurnStartedEvent0 = @__env.GetMethodID(global::robocode.control.events.TurnStartedEvent.staticClass, "", "()V"); + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.events.TurnStartedEvent(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/BulletState.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/BulletState.generated.cs new file mode 100644 index 0000000..6b49adf --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/BulletState.generated.cs @@ -0,0 +1,195 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.snapshot { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BulletState : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_values0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_valueOf1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getValue2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_toState3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isActive4; + + internal static global::net.sf.jni4net.jni.FieldId j4n_FIRED5; + + internal static global::net.sf.jni4net.jni.FieldId j4n_MOVING6; + + internal static global::net.sf.jni4net.jni.FieldId j4n_HIT_VICTIM7; + + internal static global::net.sf.jni4net.jni.FieldId j4n_HIT_BULLET8; + + internal static global::net.sf.jni4net.jni.FieldId j4n_HIT_WALL9; + + internal static global::net.sf.jni4net.jni.FieldId j4n_EXPLODED10; + + internal static global::net.sf.jni4net.jni.FieldId j4n_INACTIVE11; + + protected BulletState(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.snapshot.BulletState.staticClass; + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/BulletState;")] + public static global::robocode.control.snapshot.BulletState FIRED { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_FIRED5)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/BulletState;")] + public static global::robocode.control.snapshot.BulletState MOVING { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_MOVING6)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/BulletState;")] + public static global::robocode.control.snapshot.BulletState HIT_VICTIM { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_HIT_VICTIM7)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/BulletState;")] + public static global::robocode.control.snapshot.BulletState HIT_BULLET { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_HIT_BULLET8)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/BulletState;")] + public static global::robocode.control.snapshot.BulletState HIT_WALL { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_HIT_WALL9)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/BulletState;")] + public static global::robocode.control.snapshot.BulletState EXPLODED { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_EXPLODED10)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/BulletState;")] + public static global::robocode.control.snapshot.BulletState INACTIVE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_INACTIVE11)); + } + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.snapshot.BulletState.staticClass = @__class; + global::robocode.control.snapshot.BulletState.j4n_values0 = @__env.GetStaticMethodID(global::robocode.control.snapshot.BulletState.staticClass, "values", "()[Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.BulletState.j4n_valueOf1 = @__env.GetStaticMethodID(global::robocode.control.snapshot.BulletState.staticClass, "valueOf", "(Ljava/lang/String;)Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.BulletState.j4n_getValue2 = @__env.GetMethodID(global::robocode.control.snapshot.BulletState.staticClass, "getValue", "()I"); + global::robocode.control.snapshot.BulletState.j4n_toState3 = @__env.GetStaticMethodID(global::robocode.control.snapshot.BulletState.staticClass, "toState", "(I)Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.BulletState.j4n_isActive4 = @__env.GetMethodID(global::robocode.control.snapshot.BulletState.staticClass, "isActive", "()Z"); + global::robocode.control.snapshot.BulletState.j4n_FIRED5 = @__env.GetStaticFieldID(global::robocode.control.snapshot.BulletState.staticClass, "FIRED", "Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.BulletState.j4n_MOVING6 = @__env.GetStaticFieldID(global::robocode.control.snapshot.BulletState.staticClass, "MOVING", "Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.BulletState.j4n_HIT_VICTIM7 = @__env.GetStaticFieldID(global::robocode.control.snapshot.BulletState.staticClass, "HIT_VICTIM", "Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.BulletState.j4n_HIT_BULLET8 = @__env.GetStaticFieldID(global::robocode.control.snapshot.BulletState.staticClass, "HIT_BULLET", "Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.BulletState.j4n_HIT_WALL9 = @__env.GetStaticFieldID(global::robocode.control.snapshot.BulletState.staticClass, "HIT_WALL", "Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.BulletState.j4n_EXPLODED10 = @__env.GetStaticFieldID(global::robocode.control.snapshot.BulletState.staticClass, "EXPLODED", "Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.BulletState.j4n_INACTIVE11 = @__env.GetStaticFieldID(global::robocode.control.snapshot.BulletState.staticClass, "INACTIVE", "Lrobocode/control/snapshot/BulletState;"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/snapshot/BulletState;")] + public static robocode.control.snapshot.BulletState[] values() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_values0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)Lrobocode/control/snapshot/BulletState;")] + public static global::robocode.control.snapshot.BulletState valueOf(global::java.lang.String par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_valueOf1, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getValue() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.BulletState.j4n_getValue2))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(I)Lrobocode/control/snapshot/BulletState;")] + public static global::robocode.control.snapshot.BulletState toState(int par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.snapshot.BulletState.staticClass, global::robocode.control.snapshot.BulletState.j4n_toState3, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isActive() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.BulletState.j4n_isActive4))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.snapshot.BulletState(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IBulletSnapshot.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IBulletSnapshot.generated.cs new file mode 100644 index 0000000..6c857ec --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IBulletSnapshot.generated.cs @@ -0,0 +1,431 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.snapshot { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IBulletSnapshot { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/control/snapshot/BulletState;")] + global::robocode.control.snapshot.BulletState getState(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getX(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getY(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getHeading(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getPower(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getPaintX(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getPaintY(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getColor(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getFrame(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isExplosion(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getExplosionImageIndex(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getBulletId(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getVictimIndex(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getOwnerIndex(); + } + #endregion + + #region Component Designer generated code + public partial class IBulletSnapshot_ { + + public static global::java.lang.Class _class { + get { + return global::robocode.control.snapshot.@__IBulletSnapshot.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::robocode.control.snapshot.IBulletSnapshot), typeof(global::robocode.control.snapshot.IBulletSnapshot_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::robocode.control.snapshot.IBulletSnapshot), typeof(global::robocode.control.snapshot.IBulletSnapshot_))] + internal sealed partial class @__IBulletSnapshot : global::java.lang.Object, global::robocode.control.snapshot.IBulletSnapshot { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getState0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getX1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getY2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getHeading3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getPower4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getPaintX5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getPaintY6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getColor7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getFrame8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isExplosion9; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getExplosionImageIndex10; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getBulletId11; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVictimIndex12; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getOwnerIndex13; + + private @__IBulletSnapshot(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.snapshot.@__IBulletSnapshot.staticClass = @__class; + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getState0 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getState", "()Lrobocode/control/snapshot/BulletState;"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getX1 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getX", "()D"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getY2 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getY", "()D"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getHeading3 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getHeading", "()D"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getPower4 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getPower", "()D"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getPaintX5 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getPaintX", "()D"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getPaintY6 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getPaintY", "()D"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getColor7 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getColor", "()I"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getFrame8 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getFrame", "()I"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_isExplosion9 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "isExplosion", "()Z"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getExplosionImageIndex10 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getExplosionImageIndex", "()I"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getBulletId11 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getBulletId", "()I"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getVictimIndex12 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getVictimIndex", "()I"); + global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getOwnerIndex13 = @__env.GetMethodID(global::robocode.control.snapshot.@__IBulletSnapshot.staticClass, "getOwnerIndex", "()I"); + } + + public global::robocode.control.snapshot.BulletState getState() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getState0)); + } + } + + public double getX() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getX1))); + } + } + + public double getY() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getY2))); + } + } + + public double getHeading() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getHeading3))); + } + } + + public double getPower() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getPower4))); + } + } + + public double getPaintX() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getPaintX5))); + } + } + + public double getPaintY() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getPaintY6))); + } + } + + public int getColor() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getColor7))); + } + } + + public int getFrame() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getFrame8))); + } + } + + public bool isExplosion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_isExplosion9))); + } + } + + public int getExplosionImageIndex() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getExplosionImageIndex10))); + } + } + + public int getBulletId() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getBulletId11))); + } + } + + public int getVictimIndex() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getVictimIndex12))); + } + } + + public int getOwnerIndex() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IBulletSnapshot.j4n_getOwnerIndex13))); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IBulletSnapshot); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getState", "getState0", "()Lrobocode/control/snapshot/BulletState;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getX", "getX1", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getY", "getY2", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getHeading", "getHeading3", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getPower", "getPower4", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getPaintX", "getPaintX5", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getPaintY", "getPaintY6", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getColor", "getColor7", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getFrame", "getFrame8", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isExplosion", "isExplosion9", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getExplosionImageIndex", "getExplosionImageIndex10", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getBulletId", "getBulletId11", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getVictimIndex", "getVictimIndex12", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getOwnerIndex", "getOwnerIndex13", "()I")); + return methods; + } + + private static global::net.sf.jni4net.utils.JniHandle getState0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Lrobocode/control/snapshot/BulletState; + // ()Lrobocode/control/snapshot/BulletState; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getState()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getX1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getX())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getY2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getY())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getHeading3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getHeading())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getPower4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getPower())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getPaintX5(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getPaintX())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getPaintY6(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getPaintY())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getColor7(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getColor())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getFrame8(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getFrame())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isExplosion9(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isExplosion())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getExplosionImageIndex10(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getExplosionImageIndex())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getBulletId11(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getBulletId())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getVictimIndex12(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getVictimIndex())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getOwnerIndex13(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IBulletSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getOwnerIndex())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.snapshot.@__IBulletSnapshot(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IDebugProperty.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IDebugProperty.generated.cs new file mode 100644 index 0000000..9b34022 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IDebugProperty.generated.cs @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.snapshot { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IDebugProperty { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getValue(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getKey(); + } + #endregion + + #region Component Designer generated code + public partial class IDebugProperty_ { + + public static global::java.lang.Class _class { + get { + return global::robocode.control.snapshot.@__IDebugProperty.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::robocode.control.snapshot.IDebugProperty), typeof(global::robocode.control.snapshot.IDebugProperty_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::robocode.control.snapshot.IDebugProperty), typeof(global::robocode.control.snapshot.IDebugProperty_))] + internal sealed partial class @__IDebugProperty : global::java.lang.Object, global::robocode.control.snapshot.IDebugProperty { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getValue0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getKey1; + + private @__IDebugProperty(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.snapshot.@__IDebugProperty.staticClass = @__class; + global::robocode.control.snapshot.@__IDebugProperty.j4n_getValue0 = @__env.GetMethodID(global::robocode.control.snapshot.@__IDebugProperty.staticClass, "getValue", "()Ljava/lang/String;"); + global::robocode.control.snapshot.@__IDebugProperty.j4n_getKey1 = @__env.GetMethodID(global::robocode.control.snapshot.@__IDebugProperty.staticClass, "getKey", "()Ljava/lang/String;"); + } + + public global::java.lang.String getValue() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IDebugProperty.j4n_getValue0)); + } + } + + public global::java.lang.String getKey() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IDebugProperty.j4n_getKey1)); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IDebugProperty); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getValue", "getValue0", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getKey", "getKey1", "()Ljava/lang/String;")); + return methods; + } + + private static global::net.sf.jni4net.utils.JniHandle getValue0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IDebugProperty @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getValue()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getKey1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IDebugProperty @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getKey()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.snapshot.@__IDebugProperty(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IRobotSnapshot.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IRobotSnapshot.generated.cs new file mode 100644 index 0000000..d73f872 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IRobotSnapshot.generated.cs @@ -0,0 +1,795 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.snapshot { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IRobotSnapshot { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getName(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/control/snapshot/RobotState;")] + global::robocode.control.snapshot.RobotState getState(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getTeamName(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getX(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getY(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getShortName(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getVeryShortName(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getRobotIndex(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getTeamIndex(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getContestantIndex(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getEnergy(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getVelocity(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getBodyHeading(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getGunHeading(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getRadarHeading(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getGunHeat(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getBodyColor(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getGunColor(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getRadarColor(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getScanColor(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isDroid(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isSentryRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isPaintRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isPaintEnabled(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isSGPaintEnabled(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/snapshot/IDebugProperty;")] + robocode.control.snapshot.IDebugProperty[] getDebugProperties(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getOutputStreamSnapshot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/control/snapshot/IScoreSnapshot;")] + global::robocode.control.snapshot.IScoreSnapshot getScoreSnapshot(); + } + #endregion + + #region Component Designer generated code + public partial class IRobotSnapshot_ { + + public static global::java.lang.Class _class { + get { + return global::robocode.control.snapshot.@__IRobotSnapshot.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::robocode.control.snapshot.IRobotSnapshot), typeof(global::robocode.control.snapshot.IRobotSnapshot_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::robocode.control.snapshot.IRobotSnapshot), typeof(global::robocode.control.snapshot.IRobotSnapshot_))] + internal sealed partial class @__IRobotSnapshot : global::java.lang.Object, global::robocode.control.snapshot.IRobotSnapshot { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getName0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getState1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTeamName2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getX3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getY4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getShortName5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVeryShortName6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobotIndex7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTeamIndex8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getContestantIndex9; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getEnergy10; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVelocity11; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getBodyHeading12; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getGunHeading13; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRadarHeading14; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getGunHeat15; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getBodyColor16; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getGunColor17; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRadarColor18; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getScanColor19; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isDroid20; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isSentryRobot21; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isPaintRobot22; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isPaintEnabled23; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isSGPaintEnabled24; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getDebugProperties25; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getOutputStreamSnapshot26; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getScoreSnapshot27; + + private @__IRobotSnapshot(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.snapshot.@__IRobotSnapshot.staticClass = @__class; + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getName0 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getName", "()Ljava/lang/String;"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getState1 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getState", "()Lrobocode/control/snapshot/RobotState;"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getTeamName2 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getTeamName", "()Ljava/lang/String;"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getX3 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getX", "()D"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getY4 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getY", "()D"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getShortName5 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getShortName", "()Ljava/lang/String;"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getVeryShortName6 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getVeryShortName", "()Ljava/lang/String;"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getRobotIndex7 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getRobotIndex", "()I"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getTeamIndex8 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getTeamIndex", "()I"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getContestantIndex9 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getContestantIndex", "()I"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getEnergy10 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getEnergy", "()D"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getVelocity11 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getVelocity", "()D"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getBodyHeading12 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getBodyHeading", "()D"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getGunHeading13 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getGunHeading", "()D"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getRadarHeading14 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getRadarHeading", "()D"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getGunHeat15 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getGunHeat", "()D"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getBodyColor16 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getBodyColor", "()I"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getGunColor17 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getGunColor", "()I"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getRadarColor18 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getRadarColor", "()I"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getScanColor19 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getScanColor", "()I"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isDroid20 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "isDroid", "()Z"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isSentryRobot21 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "isSentryRobot", "()Z"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isPaintRobot22 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "isPaintRobot", "()Z"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isPaintEnabled23 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "isPaintEnabled", "()Z"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isSGPaintEnabled24 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "isSGPaintEnabled", "()Z"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getDebugProperties25 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getDebugProperties", "()[Lrobocode/control/snapshot/IDebugProperty;"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getOutputStreamSnapshot26 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getOutputStreamSnapshot", "()Ljava/lang/String;"); + global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getScoreSnapshot27 = @__env.GetMethodID(global::robocode.control.snapshot.@__IRobotSnapshot.staticClass, "getScoreSnapshot", "()Lrobocode/control/snapshot/IScoreSnapshot;"); + } + + public global::java.lang.String getName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getName0)); + } + } + + public global::robocode.control.snapshot.RobotState getState() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getState1)); + } + } + + public global::java.lang.String getTeamName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getTeamName2)); + } + } + + public double getX() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getX3))); + } + } + + public double getY() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getY4))); + } + } + + public global::java.lang.String getShortName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getShortName5)); + } + } + + public global::java.lang.String getVeryShortName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getVeryShortName6)); + } + } + + public int getRobotIndex() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getRobotIndex7))); + } + } + + public int getTeamIndex() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getTeamIndex8))); + } + } + + public int getContestantIndex() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getContestantIndex9))); + } + } + + public double getEnergy() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getEnergy10))); + } + } + + public double getVelocity() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getVelocity11))); + } + } + + public double getBodyHeading() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getBodyHeading12))); + } + } + + public double getGunHeading() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getGunHeading13))); + } + } + + public double getRadarHeading() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getRadarHeading14))); + } + } + + public double getGunHeat() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getGunHeat15))); + } + } + + public int getBodyColor() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getBodyColor16))); + } + } + + public int getGunColor() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getGunColor17))); + } + } + + public int getRadarColor() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getRadarColor18))); + } + } + + public int getScanColor() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getScanColor19))); + } + } + + public bool isDroid() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isDroid20))); + } + } + + public bool isSentryRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isSentryRobot21))); + } + } + + public bool isPaintRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isPaintRobot22))); + } + } + + public bool isPaintEnabled() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isPaintEnabled23))); + } + } + + public bool isSGPaintEnabled() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_isSGPaintEnabled24))); + } + } + + public robocode.control.snapshot.IDebugProperty[] getDebugProperties() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayFullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getDebugProperties25)); + } + } + + public global::java.lang.String getOutputStreamSnapshot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getOutputStreamSnapshot26)); + } + } + + public global::robocode.control.snapshot.IScoreSnapshot getScoreSnapshot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IRobotSnapshot.j4n_getScoreSnapshot27)); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IRobotSnapshot); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getName", "getName0", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getState", "getState1", "()Lrobocode/control/snapshot/RobotState;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTeamName", "getTeamName2", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getX", "getX3", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getY", "getY4", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getShortName", "getShortName5", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getVeryShortName", "getVeryShortName6", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRobotIndex", "getRobotIndex7", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTeamIndex", "getTeamIndex8", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getContestantIndex", "getContestantIndex9", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getEnergy", "getEnergy10", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getVelocity", "getVelocity11", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getBodyHeading", "getBodyHeading12", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getGunHeading", "getGunHeading13", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRadarHeading", "getRadarHeading14", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getGunHeat", "getGunHeat15", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getBodyColor", "getBodyColor16", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getGunColor", "getGunColor17", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRadarColor", "getRadarColor18", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getScanColor", "getScanColor19", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isDroid", "isDroid20", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isSentryRobot", "isSentryRobot21", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isPaintRobot", "isPaintRobot22", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isPaintEnabled", "isPaintEnabled23", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isSGPaintEnabled", "isSGPaintEnabled24", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getDebugProperties", "getDebugProperties25", "()[Lrobocode/control/snapshot/IDebugProperty;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getOutputStreamSnapshot", "getOutputStreamSnapshot26", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getScoreSnapshot", "getScoreSnapshot27", "()Lrobocode/control/snapshot/IScoreSnapshot;")); + return methods; + } + + private static global::net.sf.jni4net.utils.JniHandle getName0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getState1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Lrobocode/control/snapshot/RobotState; + // ()Lrobocode/control/snapshot/RobotState; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getState()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getTeamName2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getTeamName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getX3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getX())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getY4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getY())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getShortName5(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getShortName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getVeryShortName6(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getVeryShortName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getRobotIndex7(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getRobotIndex())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getTeamIndex8(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getTeamIndex())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getContestantIndex9(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getContestantIndex())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getEnergy10(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getEnergy())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getVelocity11(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getVelocity())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getBodyHeading12(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getBodyHeading())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getGunHeading13(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getGunHeading())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getRadarHeading14(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getRadarHeading())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getGunHeat15(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getGunHeat())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getBodyColor16(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getBodyColor())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getGunColor17(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getGunColor())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getRadarColor18(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getRadarColor())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getScanColor19(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getScanColor())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isDroid20(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isDroid())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isSentryRobot21(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isSentryRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isPaintRobot22(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isPaintRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isPaintEnabled23(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isPaintEnabled())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isSGPaintEnabled24(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isSGPaintEnabled())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getDebugProperties25(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()[Lrobocode/control/snapshot/IDebugProperty; + // ()[Lrobocode/control/snapshot/IDebugProperty; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.ArrayFullC2J(@__env, @__real.getDebugProperties()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getOutputStreamSnapshot26(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getOutputStreamSnapshot()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getScoreSnapshot27(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Lrobocode/control/snapshot/IScoreSnapshot; + // ()Lrobocode/control/snapshot/IScoreSnapshot; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IRobotSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.FullC2J(@__env, @__real.getScoreSnapshot()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.snapshot.@__IRobotSnapshot(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IScoreSnapshot.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IScoreSnapshot.generated.cs new file mode 100644 index 0000000..374c181 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/IScoreSnapshot.generated.cs @@ -0,0 +1,558 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.snapshot { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IScoreSnapshot : global::java.lang.Comparable { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getName(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getTotalScore(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getTotalSurvivalScore(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getTotalLastSurvivorBonus(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getTotalBulletDamageScore(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getTotalBulletKillBonus(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getTotalRammingDamageScore(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getTotalRammingKillBonus(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getTotalFirsts(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getTotalSeconds(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getTotalThirds(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getCurrentScore(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getCurrentSurvivalScore(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getCurrentSurvivalBonus(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getCurrentBulletDamageScore(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getCurrentBulletKillBonus(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getCurrentRammingDamageScore(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()D")] + double getCurrentRammingKillBonus(); + } + #endregion + + #region Component Designer generated code + public partial class IScoreSnapshot_ { + + public static global::java.lang.Class _class { + get { + return global::robocode.control.snapshot.@__IScoreSnapshot.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::robocode.control.snapshot.IScoreSnapshot), typeof(global::robocode.control.snapshot.IScoreSnapshot_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::robocode.control.snapshot.IScoreSnapshot), typeof(global::robocode.control.snapshot.IScoreSnapshot_))] + internal sealed partial class @__IScoreSnapshot : global::java.lang.Object, global::robocode.control.snapshot.IScoreSnapshot { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_compareTo0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getName1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalScore2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalSurvivalScore3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalLastSurvivorBonus4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalBulletDamageScore5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalBulletKillBonus6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalRammingDamageScore7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalRammingKillBonus8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalFirsts9; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalSeconds10; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTotalThirds11; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getCurrentScore12; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getCurrentSurvivalScore13; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getCurrentSurvivalBonus14; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getCurrentBulletDamageScore15; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getCurrentBulletKillBonus16; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getCurrentRammingDamageScore17; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getCurrentRammingKillBonus18; + + private @__IScoreSnapshot(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.snapshot.@__IScoreSnapshot.staticClass = @__class; + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_compareTo0 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "compareTo", "(Ljava/lang/Object;)I"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getName1 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getName", "()Ljava/lang/String;"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalScore2 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalScore", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalSurvivalScore3 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalSurvivalScore", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalLastSurvivorBonus4 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalLastSurvivorBonus", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalBulletDamageScore5 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalBulletDamageScore", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalBulletKillBonus6 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalBulletKillBonus", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalRammingDamageScore7 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalRammingDamageScore", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalRammingKillBonus8 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalRammingKillBonus", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalFirsts9 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalFirsts", "()I"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalSeconds10 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalSeconds", "()I"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalThirds11 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getTotalThirds", "()I"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentScore12 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getCurrentScore", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentSurvivalScore13 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getCurrentSurvivalScore", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentSurvivalBonus14 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getCurrentSurvivalBonus", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentBulletDamageScore15 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getCurrentBulletDamageScore", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentBulletKillBonus16 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getCurrentBulletKillBonus", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentRammingDamageScore17 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getCurrentRammingDamageScore", "()D"); + global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentRammingKillBonus18 = @__env.GetMethodID(global::robocode.control.snapshot.@__IScoreSnapshot.staticClass, "getCurrentRammingKillBonus", "()D"); + } + + public int compareTo(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_compareTo0, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)))); + } + } + + public global::java.lang.String getName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getName1)); + } + } + + public double getTotalScore() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalScore2))); + } + } + + public double getTotalSurvivalScore() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalSurvivalScore3))); + } + } + + public double getTotalLastSurvivorBonus() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalLastSurvivorBonus4))); + } + } + + public double getTotalBulletDamageScore() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalBulletDamageScore5))); + } + } + + public double getTotalBulletKillBonus() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalBulletKillBonus6))); + } + } + + public double getTotalRammingDamageScore() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalRammingDamageScore7))); + } + } + + public double getTotalRammingKillBonus() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalRammingKillBonus8))); + } + } + + public int getTotalFirsts() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalFirsts9))); + } + } + + public int getTotalSeconds() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalSeconds10))); + } + } + + public int getTotalThirds() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getTotalThirds11))); + } + } + + public double getCurrentScore() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentScore12))); + } + } + + public double getCurrentSurvivalScore() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentSurvivalScore13))); + } + } + + public double getCurrentSurvivalBonus() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentSurvivalBonus14))); + } + } + + public double getCurrentBulletDamageScore() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentBulletDamageScore15))); + } + } + + public double getCurrentBulletKillBonus() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentBulletKillBonus16))); + } + } + + public double getCurrentRammingDamageScore() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentRammingDamageScore17))); + } + } + + public double getCurrentRammingKillBonus() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((double)(@__env.CallDoubleMethod(this, global::robocode.control.snapshot.@__IScoreSnapshot.j4n_getCurrentRammingKillBonus18))); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IScoreSnapshot); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "compareTo", "compareTo0", "(Ljava/lang/Object;)I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getName", "getName1", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalScore", "getTotalScore2", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalSurvivalScore", "getTotalSurvivalScore3", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalLastSurvivorBonus", "getTotalLastSurvivorBonus4", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalBulletDamageScore", "getTotalBulletDamageScore5", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalBulletKillBonus", "getTotalBulletKillBonus6", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalRammingDamageScore", "getTotalRammingDamageScore7", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalRammingKillBonus", "getTotalRammingKillBonus8", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalFirsts", "getTotalFirsts9", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalSeconds", "getTotalSeconds10", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTotalThirds", "getTotalThirds11", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getCurrentScore", "getCurrentScore12", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getCurrentSurvivalScore", "getCurrentSurvivalScore13", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getCurrentSurvivalBonus", "getCurrentSurvivalBonus14", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getCurrentBulletDamageScore", "getCurrentBulletDamageScore15", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getCurrentBulletKillBonus", "getCurrentBulletKillBonus16", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getCurrentRammingDamageScore", "getCurrentRammingDamageScore17", "()D")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getCurrentRammingKillBonus", "getCurrentRammingKillBonus18", "()D")); + return methods; + } + + private static int compareTo0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Ljava/lang/Object;)I + // (Ljava/lang/Object;)I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(((global::java.lang.Comparable)(@__real)).compareTo(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0)))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getName1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getTotalScore2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getTotalScore())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getTotalSurvivalScore3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getTotalSurvivalScore())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getTotalLastSurvivorBonus4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getTotalLastSurvivorBonus())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getTotalBulletDamageScore5(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getTotalBulletDamageScore())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getTotalBulletKillBonus6(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getTotalBulletKillBonus())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getTotalRammingDamageScore7(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getTotalRammingDamageScore())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getTotalRammingKillBonus8(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getTotalRammingKillBonus())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getTotalFirsts9(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getTotalFirsts())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getTotalSeconds10(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getTotalSeconds())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getTotalThirds11(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getTotalThirds())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getCurrentScore12(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getCurrentScore())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getCurrentSurvivalScore13(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getCurrentSurvivalScore())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getCurrentSurvivalBonus14(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getCurrentSurvivalBonus())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getCurrentBulletDamageScore15(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getCurrentBulletDamageScore())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getCurrentBulletKillBonus16(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getCurrentBulletKillBonus())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getCurrentRammingDamageScore17(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getCurrentRammingDamageScore())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static double getCurrentRammingKillBonus18(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()D + // ()D + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + double @__return = default(double); + try { + global::robocode.control.snapshot.IScoreSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((double)(@__real.getCurrentRammingKillBonus())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.snapshot.@__IScoreSnapshot(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/ITurnSnapshot.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/ITurnSnapshot.generated.cs new file mode 100644 index 0000000..417e14f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/ITurnSnapshot.generated.cs @@ -0,0 +1,249 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.snapshot { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface ITurnSnapshot { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/snapshot/IRobotSnapshot;")] + robocode.control.snapshot.IRobotSnapshot[] getRobots(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/snapshot/IBulletSnapshot;")] + robocode.control.snapshot.IBulletSnapshot[] getBullets(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getTPS(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getRound(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getTurn(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/snapshot/IScoreSnapshot;")] + robocode.control.snapshot.IScoreSnapshot[] getSortedTeamScores(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/snapshot/IScoreSnapshot;")] + robocode.control.snapshot.IScoreSnapshot[] getIndexedTeamScores(); + } + #endregion + + #region Component Designer generated code + public partial class ITurnSnapshot_ { + + public static global::java.lang.Class _class { + get { + return global::robocode.control.snapshot.@__ITurnSnapshot.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::robocode.control.snapshot.ITurnSnapshot), typeof(global::robocode.control.snapshot.ITurnSnapshot_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::robocode.control.snapshot.ITurnSnapshot), typeof(global::robocode.control.snapshot.ITurnSnapshot_))] + internal sealed partial class @__ITurnSnapshot : global::java.lang.Object, global::robocode.control.snapshot.ITurnSnapshot { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobots0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getBullets1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTPS2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRound3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTurn4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getSortedTeamScores5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getIndexedTeamScores6; + + private @__ITurnSnapshot(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.snapshot.@__ITurnSnapshot.staticClass = @__class; + global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getRobots0 = @__env.GetMethodID(global::robocode.control.snapshot.@__ITurnSnapshot.staticClass, "getRobots", "()[Lrobocode/control/snapshot/IRobotSnapshot;"); + global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getBullets1 = @__env.GetMethodID(global::robocode.control.snapshot.@__ITurnSnapshot.staticClass, "getBullets", "()[Lrobocode/control/snapshot/IBulletSnapshot;"); + global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getTPS2 = @__env.GetMethodID(global::robocode.control.snapshot.@__ITurnSnapshot.staticClass, "getTPS", "()I"); + global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getRound3 = @__env.GetMethodID(global::robocode.control.snapshot.@__ITurnSnapshot.staticClass, "getRound", "()I"); + global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getTurn4 = @__env.GetMethodID(global::robocode.control.snapshot.@__ITurnSnapshot.staticClass, "getTurn", "()I"); + global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getSortedTeamScores5 = @__env.GetMethodID(global::robocode.control.snapshot.@__ITurnSnapshot.staticClass, "getSortedTeamScores", "()[Lrobocode/control/snapshot/IScoreSnapshot;"); + global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getIndexedTeamScores6 = @__env.GetMethodID(global::robocode.control.snapshot.@__ITurnSnapshot.staticClass, "getIndexedTeamScores", "()[Lrobocode/control/snapshot/IScoreSnapshot;"); + } + + public robocode.control.snapshot.IRobotSnapshot[] getRobots() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayFullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getRobots0)); + } + } + + public robocode.control.snapshot.IBulletSnapshot[] getBullets() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayFullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getBullets1)); + } + } + + public int getTPS() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getTPS2))); + } + } + + public int getRound() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getRound3))); + } + } + + public int getTurn() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getTurn4))); + } + } + + public robocode.control.snapshot.IScoreSnapshot[] getSortedTeamScores() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayFullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getSortedTeamScores5)); + } + } + + public robocode.control.snapshot.IScoreSnapshot[] getIndexedTeamScores() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayFullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::robocode.control.snapshot.@__ITurnSnapshot.j4n_getIndexedTeamScores6)); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__ITurnSnapshot); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRobots", "getRobots0", "()[Lrobocode/control/snapshot/IRobotSnapshot;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getBullets", "getBullets1", "()[Lrobocode/control/snapshot/IBulletSnapshot;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTPS", "getTPS2", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRound", "getRound3", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getTurn", "getTurn4", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getSortedTeamScores", "getSortedTeamScores5", "()[Lrobocode/control/snapshot/IScoreSnapshot;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getIndexedTeamScores", "getIndexedTeamScores6", "()[Lrobocode/control/snapshot/IScoreSnapshot;")); + return methods; + } + + private static global::net.sf.jni4net.utils.JniHandle getRobots0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()[Lrobocode/control/snapshot/IRobotSnapshot; + // ()[Lrobocode/control/snapshot/IRobotSnapshot; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.ITurnSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.ArrayFullC2J(@__env, @__real.getRobots()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getBullets1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()[Lrobocode/control/snapshot/IBulletSnapshot; + // ()[Lrobocode/control/snapshot/IBulletSnapshot; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.ITurnSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.ArrayFullC2J(@__env, @__real.getBullets()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getTPS2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.ITurnSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getTPS())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getRound3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.ITurnSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getRound())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getTurn4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::robocode.control.snapshot.ITurnSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getTurn())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getSortedTeamScores5(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()[Lrobocode/control/snapshot/IScoreSnapshot; + // ()[Lrobocode/control/snapshot/IScoreSnapshot; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.ITurnSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.ArrayFullC2J(@__env, @__real.getSortedTeamScores()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getIndexedTeamScores6(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()[Lrobocode/control/snapshot/IScoreSnapshot; + // ()[Lrobocode/control/snapshot/IScoreSnapshot; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::robocode.control.snapshot.ITurnSnapshot @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.ArrayFullC2J(@__env, @__real.getIndexedTeamScores()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.snapshot.@__ITurnSnapshot(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/RobotState.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/RobotState.generated.cs new file mode 100644 index 0000000..532ad1b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/generated/robocode/control/snapshot/RobotState.generated.cs @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.control.snapshot { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RobotState : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_values0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_valueOf1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getValue2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isAlive3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_toState4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isDead5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isHitRobot6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isHitWall7; + + internal static global::net.sf.jni4net.jni.FieldId j4n_ACTIVE8; + + internal static global::net.sf.jni4net.jni.FieldId j4n_HIT_WALL9; + + internal static global::net.sf.jni4net.jni.FieldId j4n_HIT_ROBOT10; + + internal static global::net.sf.jni4net.jni.FieldId j4n_DEAD11; + + protected RobotState(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.control.snapshot.RobotState.staticClass; + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/RobotState;")] + public static global::robocode.control.snapshot.RobotState ACTIVE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.RobotState.staticClass, global::robocode.control.snapshot.RobotState.j4n_ACTIVE8)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/RobotState;")] + public static global::robocode.control.snapshot.RobotState HIT_WALL { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.RobotState.staticClass, global::robocode.control.snapshot.RobotState.j4n_HIT_WALL9)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/RobotState;")] + public static global::robocode.control.snapshot.RobotState HIT_ROBOT { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.RobotState.staticClass, global::robocode.control.snapshot.RobotState.j4n_HIT_ROBOT10)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lrobocode/control/snapshot/RobotState;")] + public static global::robocode.control.snapshot.RobotState DEAD { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::robocode.control.snapshot.RobotState.staticClass, global::robocode.control.snapshot.RobotState.j4n_DEAD11)); + } + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.control.snapshot.RobotState.staticClass = @__class; + global::robocode.control.snapshot.RobotState.j4n_values0 = @__env.GetStaticMethodID(global::robocode.control.snapshot.RobotState.staticClass, "values", "()[Lrobocode/control/snapshot/RobotState;"); + global::robocode.control.snapshot.RobotState.j4n_valueOf1 = @__env.GetStaticMethodID(global::robocode.control.snapshot.RobotState.staticClass, "valueOf", "(Ljava/lang/String;)Lrobocode/control/snapshot/RobotState;"); + global::robocode.control.snapshot.RobotState.j4n_getValue2 = @__env.GetMethodID(global::robocode.control.snapshot.RobotState.staticClass, "getValue", "()I"); + global::robocode.control.snapshot.RobotState.j4n_isAlive3 = @__env.GetMethodID(global::robocode.control.snapshot.RobotState.staticClass, "isAlive", "()Z"); + global::robocode.control.snapshot.RobotState.j4n_toState4 = @__env.GetStaticMethodID(global::robocode.control.snapshot.RobotState.staticClass, "toState", "(I)Lrobocode/control/snapshot/RobotState;"); + global::robocode.control.snapshot.RobotState.j4n_isDead5 = @__env.GetMethodID(global::robocode.control.snapshot.RobotState.staticClass, "isDead", "()Z"); + global::robocode.control.snapshot.RobotState.j4n_isHitRobot6 = @__env.GetMethodID(global::robocode.control.snapshot.RobotState.staticClass, "isHitRobot", "()Z"); + global::robocode.control.snapshot.RobotState.j4n_isHitWall7 = @__env.GetMethodID(global::robocode.control.snapshot.RobotState.staticClass, "isHitWall", "()Z"); + global::robocode.control.snapshot.RobotState.j4n_ACTIVE8 = @__env.GetStaticFieldID(global::robocode.control.snapshot.RobotState.staticClass, "ACTIVE", "Lrobocode/control/snapshot/RobotState;"); + global::robocode.control.snapshot.RobotState.j4n_HIT_WALL9 = @__env.GetStaticFieldID(global::robocode.control.snapshot.RobotState.staticClass, "HIT_WALL", "Lrobocode/control/snapshot/RobotState;"); + global::robocode.control.snapshot.RobotState.j4n_HIT_ROBOT10 = @__env.GetStaticFieldID(global::robocode.control.snapshot.RobotState.staticClass, "HIT_ROBOT", "Lrobocode/control/snapshot/RobotState;"); + global::robocode.control.snapshot.RobotState.j4n_DEAD11 = @__env.GetStaticFieldID(global::robocode.control.snapshot.RobotState.staticClass, "DEAD", "Lrobocode/control/snapshot/RobotState;"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Lrobocode/control/snapshot/RobotState;")] + public static robocode.control.snapshot.RobotState[] values() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.snapshot.RobotState.staticClass, global::robocode.control.snapshot.RobotState.j4n_values0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)Lrobocode/control/snapshot/RobotState;")] + public static global::robocode.control.snapshot.RobotState valueOf(global::java.lang.String par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.snapshot.RobotState.staticClass, global::robocode.control.snapshot.RobotState.j4n_valueOf1, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getValue() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::robocode.control.snapshot.RobotState.j4n_getValue2))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isAlive() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.RobotState.j4n_isAlive3))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(I)Lrobocode/control/snapshot/RobotState;")] + public static global::robocode.control.snapshot.RobotState toState(int par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::robocode.control.snapshot.RobotState.staticClass, global::robocode.control.snapshot.RobotState.j4n_toState4, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isDead() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.RobotState.j4n_isDead5))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isHitRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.RobotState.j4n_isHitRobot6))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isHitWall() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::robocode.control.snapshot.RobotState.j4n_isHitWall7))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.control.snapshot.RobotState(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/glue/robocode/control/RandomFactory.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/glue/robocode/control/RandomFactory.cs new file mode 100644 index 0000000..971149f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/glue/robocode/control/RandomFactory.cs @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using net.sf.robocode.security; + +namespace robocode.control +{ + partial class RandomFactory : IHiddenRandomHelper + { + private RandomRedirect rr; + + public RandomFactory(bool fakeInstance) + { + } + + #region IHiddenRandomHelper Members + + public Random GetRandom() + { + if (isDeterministic()) + { + if (rr == null) + { + rr = new RandomRedirect(getRandom()); + } + return rr; + } + return new Random(); + } + + #endregion + } + + public class RandomRedirect : Random + { + private java.util.Random r; + + public RandomRedirect(java.util.Random r) + { + this.r = r; + } + + public override int Next() + { + return r.nextInt(); + } + + public override int Next(int maxValue) + { + return r.nextInt(maxValue); + } + + public override int Next(int minValue, int maxValue) + { + return minValue + r.nextInt(maxValue - minValue); + } + + public override void NextBytes(byte[] buffer) + { + throw new NotImplementedException(); + } + + public override double NextDouble() + { + return r.nextDouble(); + } + } + +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/glue/robocode/control/RobocodeEngine.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/glue/robocode/control/RobocodeEngine.cs new file mode 100644 index 0000000..e6e2ca2 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/glue/robocode/control/RobocodeEngine.cs @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.IO; +using net.sf.jni4net; +using File = java.io.File; + +namespace robocode.control +{ + public partial class RobocodeEngine + { + public static void Init(string robocodeHome) + { + BridgeSetup bridgeSetup = new BridgeSetup(); + bridgeSetup.BindStatic = true; + bridgeSetup.BindNative = true; + bridgeSetup.AddAllJarsClassPath(Path.Combine(robocodeHome, "libs")); + Bridge.CreateJVM(bridgeSetup); + Bridge.LoadAndRegisterAssemblyByName(typeof(RobocodeEngine).Assembly.FullName); + //Bridge.Setup.BindNative = true; + Bridge.Setup.BindStatic = true; + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/BattleSpecification.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/BattleSpecification.cs new file mode 100644 index 0000000..0401ff0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/BattleSpecification.cs @@ -0,0 +1,257 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control +{ + /// + /// A BattleSpecification defines a battle configuration used by the . + /// + [Serializable] + public class BattleSpecification + { + private readonly int battlefieldWidth; + private readonly int battlefieldHeight; + private readonly int numRounds; + private readonly double gunCoolingRate; + private readonly long inactivityTime; + private readonly bool hideEnemyNames; + private readonly int sentryBorderSize; + private readonly RobotSpecification[] robots; + private readonly RobotSetup[] initialSetups; + + /// + /// Creates a new BattleSpecification with the given number of rounds, + /// battlefield size, and robots. Inactivity time for the robots defaults to + /// 450, and the gun cooling rate defaults to 0.1. + /// + /// The number of rounds in this battle. + /// The battlefield size. + /// The robots participating in this battle. + public BattleSpecification(int numRounds, BattlefieldSpecification battlefieldSize, RobotSpecification[] robots) : + this(numRounds, 450, .1, battlefieldSize, robots) + { + } + + /// + /// Creates a new BattleSpecification with the given settings. + /// + /// The number of rounds in this battle. + /// The inactivity time allowed for the robots before + /// they will loose energy. + /// The gun cooling rate for the robots. + /// The battlefield size. + /// The robots participating in this battle. + public BattleSpecification(int numRounds, long inactivityTime, double gunCoolingRate, BattlefieldSpecification battlefieldSize, RobotSpecification[] robots) : + this(numRounds, inactivityTime, gunCoolingRate, false, battlefieldSize, robots) + { + } + + /// + /// Creates a new BattleSpecification with the given settings. + /// + /// The number of rounds in this battle. + /// The inactivity time allowed for the robots before + /// they will loose energy. + /// The gun cooling rate for the robots. + /// Flag specifying if enemy names are hidden from robots. + /// The battlefield size. + /// The robots participating in this battle. + public BattleSpecification(int numRounds, long inactivityTime, double gunCoolingRate, bool hideEnemyNames, BattlefieldSpecification battlefieldSize, RobotSpecification[] robots) : + this(battlefieldSize, numRounds, inactivityTime, gunCoolingRate, 100, hideEnemyNames, robots) + { + } + + /// + /// Creates a new BattleSpecification with the given settings. + /// + /// The battlefield size. + /// The number of rounds in this battle. + /// The inactivity time allowed for the robots before + /// they will loose energy. + /// The gun cooling rate for the robots. + /// The sentry border size for a BorderSentry. + /// Flag specifying if enemy names are hidden from robots. + /// The robots participating in this battle. + public BattleSpecification(BattlefieldSpecification battlefieldSize, int numRounds, long inactivityTime, double gunCoolingRate, int sentryBorderSize, bool hideEnemyNames, RobotSpecification[] robots) : + this(battlefieldSize, numRounds, inactivityTime, gunCoolingRate, 100, hideEnemyNames, robots, null) + { + } + + /// + /// Creates a new BattleSpecification with the given settings. + /// + /// The battlefield size. + /// The number of rounds in this battle. + /// The inactivity time allowed for the robots before + /// they will loose energy. + /// The gun cooling rate for the robots. + /// The sentry border size for a BorderSentry. + /// Flag specifying if enemy names are hidden from robots. + /// The robots participating in this battle. + /// The initial position and heading of the robots, where the indices matches the indices from the . + public BattleSpecification(BattlefieldSpecification battlefieldSize, int numRounds, long inactivityTime, double gunCoolingRate, int sentryBorderSize, bool hideEnemyNames, RobotSpecification[] robots, RobotSetup[] initialSetups) + { + if (battlefieldSize == null) + { + throw new ArgumentException("battlefieldSize cannot be null"); + } + if (robots == null) + { + throw new ArgumentException("robots cannot be null"); + } + if (robots.Length < 1) + { + throw new ArgumentException("robots.Length must be > 0"); + } + if (initialSetups != null && initialSetups.Length != robots.Length) + { + throw new ArgumentException("initialSetups.Length must be == robots.Length"); + } + if (numRounds < 1) + { + throw new ArgumentException("numRounds must be >= 1"); + } + if (inactivityTime < 1) + { + throw new ArgumentException("inactivityTime must be >= 1"); + } + if (gunCoolingRate < 0.1) + { + throw new ArgumentException("inactivityTime must be >= 0.1"); + } + if (sentryBorderSize < 50) + { + throw new ArgumentException("sentryBorderSize must be >= 50"); + } + this.battlefieldWidth = battlefieldSize.Width; + this.battlefieldHeight = battlefieldSize.Height; + this.numRounds = numRounds; + this.inactivityTime = inactivityTime; + this.gunCoolingRate = gunCoolingRate; + this.sentryBorderSize = sentryBorderSize; + this.hideEnemyNames = hideEnemyNames; + this.robots = robots; + this.initialSetups = initialSetups; + } + + /// + /// Contains the allowed inactivity time for the robots in this battle. + /// + /// + /// The allowed inactivity time for the robots in this battle. + /// + public long InactivityTime + { + get { return inactivityTime; } + } + + /// + /// Contains the gun cooling rate of the robots in this battle. + /// + /// + /// The gun cooling rate of the robots in this battle. + /// + public double GunCoolingRate + { + get { return gunCoolingRate; } + } + + /// + /// Contains the battlefield size for this battle. + /// + /// + /// The battlefield size for this battle. + /// + public BattlefieldSpecification Battlefield + { + get { return new BattlefieldSpecification(battlefieldWidth, battlefieldHeight); } + } + + /// + /// Contains the number of rounds in this battle. + /// + /// + /// The number of rounds in this battle. + /// + public int NumRounds + { + get { return numRounds; } + } + + /// + /// Flag specifying if the enemy names must be hidden from events sent to robots. + /// + /// + /// true if the enemy names must be hidden; false otherwise. + /// + public bool HideEnemyNames + { + get { return hideEnemyNames; } + } + + /// + /// Returns the sentry border size for a BorderSentry that defines the how + /// far a BorderSentry is allowed to move from the border edges measured in units. + ///

+ /// Hence, the sentry border size defines the width/range of the border area surrounding the battlefield that + /// border sentry robots cannot leave (they must stay in the border area), but it also define the + /// distance from the border edges where border sentry robots are allowed/able to make damage to robots entering this + /// border area. + ///

+ public int SentryBorderSize + { + get { return sentryBorderSize; } + } + + /// + /// Contains the specifications of the robots participating in this battle. + /// + /// + /// An array of instances - one entry for each robot. + /// + /// + public RobotSpecification[] Robots + { + get + { + if (robots == null) + return null; + + RobotSpecification[] copy = new RobotSpecification[robots.Length]; + robots.CopyTo(copy, 0); + return copy; + } + } + + /// + /// Contains the initial position and heading of each robot participating in this battle. + /// + /// + /// An array of instances - one entry for each robot. + /// The the indices of this array matches the array indices from the robot specifications (see ). + /// + /// + public RobotSetup[] InitialSetups + { + get + { + if (initialSetups == null) + return null; + + RobotSetup[] copy = new RobotSetup[initialSetups.Length]; + initialSetups.CopyTo(copy, 0); + return copy; + } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/BattlefieldSpecification.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/BattlefieldSpecification.cs new file mode 100644 index 0000000..d59dab6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/BattlefieldSpecification.cs @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control +{ + /// + /// Defines the size of a battlefield, which is a part of the . + /// + /// + /// + /// + [Serializable] + public class BattlefieldSpecification + { + private readonly int width; + private readonly int height; + + /// + /// Creates a standard 800 x 600 battlefield. + /// + public BattlefieldSpecification() + : this(800, 600) + { + } + + /// + /// Creates a battlefield of the specified width and height. + /// + /// The width of the battlefield, where 400 <= width <= 5000. + /// The height of the battlefield, where 400 <= height <= 5000. + /// Thrown when the width or height is < 400 or > 5000. + /// + public BattlefieldSpecification(int width, int height) + { + if (width < 400 || width > 5000) + throw new ArgumentException("width must be: 400 <= width <= 5000"); + + if (height < 400 || height > 5000) + throw new ArgumentException("height must be: 400 <= height <= 5000"); + + this.width = width; + this.height = height; + } + + /// + /// Contains the width of this battlefield. + /// + /// + /// The width of this battlefield. + /// + public int Width + { + get { return width; } + } + + /// + /// Contains the height of this battlefield. + /// + /// + /// The height of this battlefield. + /// + public int Height + { + get { return height; } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/IRobocodeEngine.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/IRobocodeEngine.cs new file mode 100644 index 0000000..b87d8cc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/IRobocodeEngine.cs @@ -0,0 +1,237 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; +using Robocode.Control.Events; // for the XML documentation + +namespace Robocode.Control +{ + /// + /// Event handler for the . + /// + /// The event. + public delegate void BattleStartedEventHandler(Robocode.Control.Events.BattleStartedEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void BattleFinishedEventHandler(Robocode.Control.Events.BattleFinishedEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void BattleCompletedEventHandler(Robocode.Control.Events.BattleCompletedEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void BattlePausedEventHandler(Robocode.Control.Events.BattlePausedEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void BattleResumedEventHandler(Robocode.Control.Events.BattleResumedEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void RoundStartedEventHandler(Robocode.Control.Events.RoundStartedEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void RoundEndedEventHandler(Robocode.Control.Events.RoundEndedEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void TurnStartedEventHandler(Robocode.Control.Events.TurnStartedEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void TurnEndedEventHandler(Robocode.Control.Events.TurnEndedEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void BattleMessageEventHandler(Robocode.Control.Events.BattleMessageEvent evnt); + + /// + /// Event handler for the . + /// + /// The event. + public delegate void BattleErrorEventHandler(Robocode.Control.Events.BattleErrorEvent evnt); + + /// + /// Interface for a RobocodeEngine. + /// + public interface IRobocodeEngine + { + /// + /// Occurs when a new battle is started. + /// + event BattleStartedEventHandler BattleStarted; + + /// + /// Occurs when the battle is finished, where the battle can be either completed or aborted. + /// + event BattleFinishedEventHandler BattleFinished; + + /// + /// Occurs when the battle is completed successfully and results are available. + /// + event BattleCompletedEventHandler BattleCompleted; + + /// + /// Occurs when the battle is paused. + /// + event BattlePausedEventHandler BattlePaused; + + /// + /// Occurs when the battle is resumed after having been paused. + /// + event BattleResumedEventHandler BattleResumed; + + /// + /// Occurs when a new round is started. + /// + event RoundStartedEventHandler RoundStarted; + + /// + /// Occurs when a round has ended. + /// + event RoundEndedEventHandler RoundEnded; + + /// + /// Occurs when a new turn is started. + /// + event TurnStartedEventHandler TurnStarted; + + /// + /// Occurs when a new turn is ended. + /// + event TurnEndedEventHandler TurnEnded; + + /// + /// Occurs when a message from the battle is sent from the game. + /// + event BattleMessageEventHandler BattleMessage; + + /// + /// Occurs when an error message from the battle is sent from the game. + /// + event BattleErrorEventHandler BattleError; + + /// + /// Closes the RobocodeEngine and releases any allocated resources it holds. + /// You should call this when you have finished using the RobocodeEngine. + /// This method automatically disposes the Robocode window if it open. + /// + void Close(); + + /// + /// Contains the installed version of Robocode controlled by this RobocodeEngine. + /// + /// + /// The installed version of Robocode controlled by this RobocodeEngine. + /// + string Version { get; } + + /// + /// Contains the visible state of the Robocode window. + /// + /// + /// Sets/gets the visible state of the Robocode window, where + /// true means that the window is visible, and + /// false means that the window is hidden. + /// + bool Visible { get; set; } + + /// + /// Returns all robots available from the local robot repository of Robocode. + /// These robots must exists in the \robocode\robots directory, and must be + /// compiled in advance, before these robot are returned with this method. + /// + /// + /// An array of all available robots from the local robot repository. + /// + RobotSpecification[] GetLocalRepository(); + + /// + /// Returns a selection of robots available from the local robot repository + /// of Robocode. These robots must exists in the \robocode\robots directory, + /// and must be compiled in advance, before these robot are returned with this method. + ///

+ /// Notice: If a specified robot cannot be found in the repository, it will + /// not be returned in the array of robots returned by this method. + ///

+ /// A comma or space separated list of robots to return. + /// The full class name must be used for specifying the individual robot, e.g. + /// "sample.Corners, sample.Crazy". + /// + /// An array containing the available robots from the local robot repository based on + /// the selected robots specified with the selectedRobotList parameter. + /// + RobotSpecification[] GetLocalRepository(String selectedRobotList); + + /// + /// Runs the specified battle. + /// + /// The specification of the battle to run + /// including the participation robots. + /// + void RunBattle(BattleSpecification battleSpecification); + + /// + /// Runs the specified battle. + /// + /// The specification of the battle to run + /// including the participating robots. + /// Will block caller till end of battle if set. + /// + void RunBattle(BattleSpecification battleSpecification, bool waitTillOver); + + /// + /// Runs the specified battle. + /// + /// The specification of the battle to run + /// including the participating robots. + /// A comma or space separated list like: + /// x1,y1,heading1, x2,y2,heading2, which are the coordinates and heading of + /// robot #1 and #2. So e.g. 0,0,180, 50,80,270 means that robot #1 has position + /// (0,0) and heading 180, and robot #2 has position (50,80) and heading 270. + /// Will block caller till end of battle if set. + /// + void RunBattle(BattleSpecification battleSpecification, string initialPositions, bool waitTillOver); + + /// + /// Will block caller until current battle is over. + /// + /// + void WaitTillBattleOver(); + + /// + /// Aborts the current battle if it is running. + /// + /// + void AbortCurrentBattle(); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobocodeEngine.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobocodeEngine.cs new file mode 100644 index 0000000..956f270 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobocodeEngine.cs @@ -0,0 +1,1682 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using Robocode.Control.Events; +using Robocode.Control.Snapshot; +using net.sf.robocode.security; + +namespace Robocode.Control +{ + /// + /// The RobocodeEngine is the interface provided for external applications + /// in order to let these applications run battles within the Robocode application, + /// and to get the results from these battles. + ///

+ /// This class in the main entry class of the namespace. + ///

+ /// The RobocodeEngine is used by e.g. RoboRumble@Home client, which is integrated in + /// Robocode. In addition, the RobocodeEngine is also used by the test units for + /// testing the Robocode application itself. + ///

+ public class RobocodeEngine : IRobocodeEngine + { + /// + public event BattleStartedEventHandler BattleStarted; + /// + public event BattleFinishedEventHandler BattleFinished; + /// + public event BattleCompletedEventHandler BattleCompleted; + /// + public event BattlePausedEventHandler BattlePaused; + /// + public event BattleResumedEventHandler BattleResumed; + /// + public event RoundStartedEventHandler RoundStarted; + /// + public event RoundEndedEventHandler RoundEnded; + /// + public event TurnStartedEventHandler TurnStarted; + /// + public event TurnEndedEventHandler TurnEnded; + /// + public event BattleMessageEventHandler BattleMessage; + /// + public event BattleErrorEventHandler BattleError; + + // The internal hidden engine that has been generated based on the Java version of the engine + private robocode.control.RobocodeEngine engine; + // The internal robocode.control.events.IBattleListener + private BattleObserver battleObserver; + // Flag specifying if the Robocode window is currently visible + private bool isVisible; + + #region Public API + + /// + /// Creates a new RobocodeEngine for controlling Robocode. + /// In order for this constructor to work, the current working directory must be the + /// home directory directory of Robocode, e.g. C:\Robocode + /// + /// + public RobocodeEngine() : + this(AppDomain.CurrentDomain.BaseDirectory) + { + } + + /// + /// Creates a new RobocodeEngine for controlling Robocode, where the home directory + /// of Robocode is specified. + /// + /// The root directory of Robocode, e.g. "C:\Robocode". + /// + public RobocodeEngine(string robocodeHome) + { + robocode.control.RobocodeEngine.Init(robocodeHome); + engine = new robocode.control.RobocodeEngine(new java.io.File(robocodeHome)); + battleObserver = new BattleObserver(this); + engine.addBattleListener(battleObserver); + } + + ~RobocodeEngine() + { + // Make sure Close() is called to prevent memory leaks + Close(); + } + + /// + public void Close() + { + engine.close(); + } + + /// + public string Version + { + get { return engine.getVersion(); } + } + + /// + /// Returns the current working directory for Robocode. + /// + /// + /// The name of the current working directory. + /// + public static string CurrentWorkingDir + { + get { return robocode.control.RobocodeEngine.getCurrentWorkingDir().getAbsolutePath(); } + } + + /// + /// Returns the directory containing the robots. + /// + /// + /// The name of the robot directory containing all robots. + /// + public static string RobotsDir + { + get { return robocode.control.RobocodeEngine.getRobotsDir().getAbsolutePath(); } + } + + /// + public bool Visible + { + set + { + isVisible = value; + engine.setVisible(value); + } + get + { + return isVisible; + } + } + + /// + public RobotSpecification[] GetLocalRepository() + { + return MapRobotSpecifications(engine.getLocalRepository()); + } + + /// + public RobotSpecification[] GetLocalRepository(string selectedRobots) + { + return MapRobotSpecifications(engine.getLocalRepository(selectedRobots)); + } + + /// + public void RunBattle(BattleSpecification battleSpecification) + { + RunBattle(battleSpecification, null, false); + } + + /// + public void RunBattle(BattleSpecification battleSpecification, bool waitTillOver) + { + RunBattle(battleSpecification, "", waitTillOver); + } + + /// + public void RunBattle(BattleSpecification battleSpecification, string initialPositions, bool waitTillOver) + { + engine.runBattle(MapBattleSpecification(battleSpecification), initialPositions, waitTillOver); + } + + /// + public void WaitTillBattleOver() + { + engine.waitTillBattleOver(); + } + + /// + public void AbortCurrentBattle() + { + engine.abortCurrentBattle(); + } + + /// + /// Prints out all running threads to standard system out. + /// + public static void PrintRunningThreads() + { + robocode.control.RobocodeEngine.printRunningThreads(); + } + + /// + /// Enables or disables messages and warnings logged to Console.Out. + /// + /// + /// true means that log messages must be enabled, and + /// false means that log messages must be disabled. + /// + /// + public static bool LogMessagesEnabled + { + set + { + robocode.control.RobocodeEngine.setLogMessagesEnabled(value); + } + } + + /// + /// Enables or disables errors logged to Console.Error. + /// + /// + /// true means that log errors must be enabled, and + /// false means that log errors must be disabled. + /// + /// + public static bool LogErrorsEnabled + { + set + { + robocode.control.RobocodeEngine.setLogErrorsEnabled(value); + } + } + + #endregion + + #region Event dispatchers + + private void OnBattleStarted(BattleStartedEvent e) + { + if (BattleStarted != null) + BattleStarted(e); + } + + private void OnBattleFinished(BattleFinishedEvent e) + { + if (BattleFinished != null) + BattleFinished(e); + } + + private void OnBattleCompleted(BattleCompletedEvent e) + { + if (BattleCompleted != null) + BattleCompleted(e); + } + + private void OnBattlePaused(BattlePausedEvent e) + { + if (BattlePaused != null) + BattlePaused(e); + } + + private void OnBattleResumed(BattleResumedEvent e) + { + if (BattleResumed != null) + BattleResumed(e); + } + + private void OnRoundStarted(RoundStartedEvent e) + { + if (RoundStarted != null) + RoundStarted(e); + } + + private void OnRoundEnded(Robocode.Control.Events.RoundEndedEvent e) + { + if (RoundEnded != null) + RoundEnded(e); + } + + private void OnTurnStarted(TurnStartedEvent e) + { + if (TurnStarted != null) + TurnStarted(e); + } + + private void OnTurnEnded(TurnEndedEvent e) + { + if (TurnEnded != null) + TurnEnded(e); + } + + private void OnBattleMessage(BattleMessageEvent e) + { + if (BattleMessage != null) + BattleMessage(e); + } + + private void OnBattleError(BattleErrorEvent e) + { + if (BattleError != null) + BattleError(e); + } + + #endregion + + #region Specification mappers + + private RobotSpecification[] MapRobotSpecifications(robocode.control.RobotSpecification[] specifications) + { + if (specifications == null) + { + return null; + } + + RobotSpecification[] mappedSpecifications = new RobotSpecification[specifications.Length]; + + for (int i = 0; i < specifications.Length; i++) + { + mappedSpecifications[i] = MapRobotSpecification(specifications[i]); + } + return mappedSpecifications; + } + + private RobotSpecification MapRobotSpecification(robocode.control.RobotSpecification spec) + { + return new RobotSpecification(spec); + } + + private robocode.control.RobotSpecification[] MapRobotSpecifications(RobotSpecification[] specifications) + { + if (specifications == null) + { + return null; + } + + robocode.control.RobotSpecification[] mappedSpecifications = new robocode.control.RobotSpecification[specifications.Length]; + + for (int i = 0; i < specifications.Length; i++) + { + mappedSpecifications[i] = MapRobotSpecification(specifications[i]); + } + return mappedSpecifications; + } + + private robocode.control.RobotSpecification MapRobotSpecification(RobotSpecification spec) + { + return spec.robotSpecification; + } + + private robocode.control.BattleSpecification MapBattleSpecification(BattleSpecification spec) + { + robocode.control.BattlefieldSpecification battlefieldSpec = new robocode.control.BattlefieldSpecification(spec.Battlefield.Width, spec.Battlefield.Height); + robocode.control.RobotSpecification[] robotSpecs = MapRobotSpecifications(spec.Robots); + robocode.control.RobotSetup[] initialSetups = MapInitialSetups(spec.InitialSetups); + + return new robocode.control.BattleSpecification(battlefieldSpec, spec.NumRounds, spec.InactivityTime, + spec.GunCoolingRate, spec.SentryBorderSize, spec.HideEnemyNames, robotSpecs, initialSetups); + } + + private robocode.control.RobotSetup[] MapInitialSetups(RobotSetup[] setups) + { + if (setups == null) + { + return null; + } + + robocode.control.RobotSetup[] mappedSetups = new robocode.control.RobotSetup[setups.Length]; + + for (int i = 0; i < setups.Length; i++) + { + mappedSetups[i] = MapRobotSetup(setups[i]); + } + return mappedSetups; + } + + private robocode.control.RobotSetup MapRobotSetup(RobotSetup setup) + { + return new robocode.control.RobotSetup(setup.X, setup.Y, setup.Heading); + } + #endregion + + #region Battle observer (internal engine events -> Robocode.Control.Events) + + private class BattleObserver : robocode.control.events.IBattleListener + { + RobocodeEngine engine; + + public BattleObserver(RobocodeEngine engine) + { + this.engine = engine; + } + + public void onBattleStarted(robocode.control.events.BattleStartedEvent evnt) + { + engine.OnBattleStarted(MapEvent(evnt)); + } + + public void onBattleFinished(robocode.control.events.BattleFinishedEvent evnt) + { + engine.OnBattleFinished(MapEvent(evnt)); + } + + public void onBattleCompleted(robocode.control.events.BattleCompletedEvent evnt) + { + engine.OnBattleCompleted(MapEvent(evnt)); + } + + public void onBattlePaused(robocode.control.events.BattlePausedEvent evnt) + { + engine.OnBattlePaused(new BattlePausedEvent()); + } + + public void onBattleResumed(robocode.control.events.BattleResumedEvent evnt) + { + engine.OnBattleResumed(new BattleResumedEvent()); + } + + public void onRoundStarted(robocode.control.events.RoundStartedEvent evnt) + { + engine.OnRoundStarted(MapEvent(evnt)); + } + + public void onRoundEnded(robocode.control.events.RoundEndedEvent evnt) + { + engine.OnRoundEnded(MapEvent(evnt)); + } + + public void onTurnStarted(robocode.control.events.TurnStartedEvent evnt) + { + engine.OnTurnStarted(new TurnStartedEvent()); + } + + public void onTurnEnded(robocode.control.events.TurnEndedEvent evnt) + { + engine.OnTurnEnded(MapEvent(evnt)); + } + + public void onBattleMessage(robocode.control.events.BattleMessageEvent evnt) + { + engine.OnBattleMessage(MapEvent(evnt)); + } + + public void onBattleError(robocode.control.events.BattleErrorEvent evnt) + { + engine.OnBattleError(MapEvent(evnt)); + } + } + + #endregion + + #region Event mappers (generated events -> Robocode.Control.Events) + + private static BattleStartedEvent MapEvent(robocode.control.events.BattleStartedEvent evnt) + { + return new BattleStartedEvent(MapBattleRules(evnt.getBattleRules()), evnt.getRobotsCount(), evnt.isReplay()); + } + + private static BattleFinishedEvent MapEvent(robocode.control.events.BattleFinishedEvent evnt) + { + return new BattleFinishedEvent(evnt.isAborted()); + } + + private static BattleCompletedEvent MapEvent(robocode.control.events.BattleCompletedEvent evnt) + { + return new BattleCompletedEvent(MapBattleRules(evnt.getBattleRules()), MapBattleResults(evnt.getIndexedResults())); + } + + private static BattleMessageEvent MapEvent(robocode.control.events.BattleMessageEvent evnt) + { + return new BattleMessageEvent(evnt.getMessage()); + } + + private static BattleErrorEvent MapEvent(robocode.control.events.BattleErrorEvent evnt) + { + return new BattleErrorEvent(evnt.getError()); + } + + private static RoundStartedEvent MapEvent(robocode.control.events.RoundStartedEvent evnt) + { + return new RoundStartedEvent(MapTurnSnapshot(evnt.getStartSnapshot()), evnt.getRound()); + } + + private static Robocode.Control.Events.RoundEndedEvent MapEvent(robocode.control.events.RoundEndedEvent evnt) + { + return new Robocode.Control.Events.RoundEndedEvent(evnt.getRound(), evnt.getTurns(), evnt.getTotalTurns()); + } + + private static TurnEndedEvent MapEvent(robocode.control.events.TurnEndedEvent evnt) + { + return new TurnEndedEvent(MapTurnSnapshot(evnt.getTurnSnapshot())); + } + + private static BattleCompletedEvent[] MapEvents(robocode.control.events.BattleCompletedEvent[] events) + { + if (events == null) + { + return null; + } + + BattleCompletedEvent[] mappedEvents = new BattleCompletedEvent[events.Length]; + + for (int i = 0; i < events.Length; i++) + { + mappedEvents[i] = MapEvent(events[i]); + } + return mappedEvents; + } + + private static BattleResults[] MapBattleResults(java.lang.Object[] results) + { + if (results == null) + { + return null; + } + + BattleResults[] mappedResults = new BattleResults[results.Length]; + + for (int i = 0; i < results.Length; i++) + { + mappedResults[i] = MapBattleResults(results[i]); + } + return mappedResults; + } + + private static BattleRules MapBattleRules(java.lang.Object obj) + { + int battlefieldWidth = obj.Invoke("getBattlefieldWidth", "()I", new object[] { }); + int battlefieldHeight = obj.Invoke("getBattlefieldHeight", "()I", new object[] { }); + int numRounds = obj.Invoke("getNumRounds", "()I", new object[] { }); + double gunCoolingRate = obj.Invoke("getGunCoolingRate", "()D", new object[] { }); + long inactivityTime = obj.Invoke("getInactivityTime", "()J", new object[] { }); + bool hideEnemyNames = obj.Invoke("getHideEnemyNames", "()Z", new object[] { }); + int sentryBorderSize = obj.Invoke("getSentryBorderSize", "()I", new object[] { }); + + MethodInfo method = typeof(BattleRules).GetMethod("createHiddenHelper", BindingFlags.Static | BindingFlags.NonPublic); + IHiddenRulesHelper rulesHelper = (IHiddenRulesHelper)method.Invoke(null, null); + + return rulesHelper.createRules(battlefieldWidth, battlefieldHeight, numRounds, gunCoolingRate, inactivityTime, hideEnemyNames, sentryBorderSize); + } + + private static BattleResults MapBattleResults(java.lang.Object obj) + { + string teamLeaderName = obj.Invoke("getTeamLeaderName", "()Ljava/lang/String;", new object[] { }); + int rank = obj.Invoke("getRank", "()I", new object[] { }); + int score = obj.Invoke("getScore", "()I", new object[] { }); + int survival = obj.Invoke("getSurvival", "()I", new object[] { }); + int lastSurvivorBonus = obj.Invoke("getLastSurvivorBonus", "()I", new object[] { }); + int bulletDamage = obj.Invoke("getBulletDamage", "()I", new object[] { }); + int bulletDamageBonus = obj.Invoke("getBulletDamageBonus", "()I", new object[] { }); + int ramDamage = obj.Invoke("getRamDamage", "()I", new object[] { }); + int ramDamageBonus = obj.Invoke("getRamDamageBonus", "()I", new object[] { }); + int firsts = obj.Invoke("getFirsts", "()I", new object[] { }); + int seconds = obj.Invoke("getSeconds", "()I", new object[] { }); + int thirds = obj.Invoke("getThirds", "()I", new object[] { }); + + return new BattleResults(teamLeaderName, rank, score, survival, lastSurvivorBonus, + bulletDamage, bulletDamageBonus, ramDamage, ramDamageBonus, firsts, seconds, thirds); + } + + #endregion + + #region Snapshot mappers (generated snapshots -> Robocode.Control.Snapshot) + + private static ITurnSnapshot MapTurnSnapshot(robocode.control.snapshot.ITurnSnapshot turnSnapshot) + { + return new TurnSnapshot(turnSnapshot); + } + + private static IRobotSnapshot[] MapRobotSnapshots(robocode.control.snapshot.IRobotSnapshot[] robotSnapshots) + { + if (robotSnapshots == null) + { + return null; + } + + IRobotSnapshot[] mappedSnapshots = new IRobotSnapshot[robotSnapshots.Length]; + + for (int i = 0; i < robotSnapshots.Length; i++) + { + mappedSnapshots[i] = MapRobotSnapshot(robotSnapshots[i]); + } + return mappedSnapshots; + } + + private static IRobotSnapshot MapRobotSnapshot(robocode.control.snapshot.IRobotSnapshot robotSnapshot) + { + return new RobotSnapshot(robotSnapshot); + } + + private static IScoreSnapshot[] MapScoreSnapshots(robocode.control.snapshot.IScoreSnapshot[] bulletSnapshots) + { + if (bulletSnapshots == null) + { + return null; + } + + IScoreSnapshot[] mappedSnapshots = new IScoreSnapshot[bulletSnapshots.Length]; + + for (int i = 0; i < bulletSnapshots.Length; i++) + { + mappedSnapshots[i] = MapScoreSnapshot(bulletSnapshots[i]); + } + return mappedSnapshots; + } + + private static IScoreSnapshot MapScoreSnapshot(robocode.control.snapshot.IScoreSnapshot scoreSnapshot) + { + return new ScoreSnapshot(scoreSnapshot); + } + + private static IBulletSnapshot[] MapBulletSnapshots(robocode.control.snapshot.IBulletSnapshot[] bulletSnapshots) + { + if (bulletSnapshots == null) + { + return null; + } + + IBulletSnapshot[] mappedSnapshots = new IBulletSnapshot[bulletSnapshots.Length]; + + for (int i = 0; i < bulletSnapshots.Length; i++) + { + mappedSnapshots[i] = MapBulletSnapshot(bulletSnapshots[i]); + } + return mappedSnapshots; + } + + private static IBulletSnapshot MapBulletSnapshot(robocode.control.snapshot.IBulletSnapshot bulletSnapshot) + { + return new BulletSnapshot(bulletSnapshot); + } + + private static IDebugProperty[] MapDebugProperties(robocode.control.snapshot.IDebugProperty[] debugProperties) + { + if (debugProperties == null) + { + return null; + } + + IDebugProperty[] mappedProperties = new IDebugProperty[debugProperties.Length]; + + for (int i = 0; i < debugProperties.Length; i++) + { + mappedProperties[i] = MapDebugProperty(debugProperties[i]); + } + return mappedProperties; + } + + private static IDebugProperty MapDebugProperty(robocode.control.snapshot.IDebugProperty debugProperty) + { + return new DebugProperty(debugProperty.getKey(), debugProperty.getValue()); + } + + private static RobotState MapRobotState(robocode.control.snapshot.RobotState robotState) + { + switch (robotState.getValue()) + { + case 0: + return RobotState.Active; + case 1: + return RobotState.HitWall; + case 2: + return RobotState.HitRobot; + case 3: + default: + return RobotState.Dead; + } + } + + private static BulletState MapBulletState(robocode.control.snapshot.BulletState bulletState) + { + switch (bulletState.getValue()) + { + case 0: + return BulletState.Fired; + case 1: + return BulletState.Moving; + case 2: + return BulletState.HitVictim; + case 3: + return BulletState.HitBullet; + case 4: + return BulletState.HitWall; + case 5: + return BulletState.Exploded; + case 6: + default: + return BulletState.Inactive; + } + } + + #endregion + + #region Robocode.Control.Snapshot implementations + + private class TurnSnapshot : ITurnSnapshot + { + // The real snapshot + private readonly robocode.control.snapshot.ITurnSnapshot turnSnapshot; + + // Cached values created, when needed + private IRobotSnapshot[] robots; + private IBulletSnapshot[] bullets; + private int? tps; + private int? round; + private int? turn; + private IScoreSnapshot[] sortedTeamScores; + private IScoreSnapshot[] indexedTeamScores; + + public TurnSnapshot(robocode.control.snapshot.ITurnSnapshot turnSnapshot) + { + this.turnSnapshot = turnSnapshot; + } + + public IRobotSnapshot[] Robots + { + get + { + if (robots == null) + { + robots = MapRobotSnapshots(turnSnapshot.getRobots()); + } + return robots; + } + } + + public IBulletSnapshot[] Bullets + { + get + { + if (bullets == null) + { + bullets = MapBulletSnapshots(turnSnapshot.getBullets()); + } + return bullets; + } + } + + public int TPS + { + get + { + if (tps == null) + { + tps = turnSnapshot.getTPS(); + } + return tps.Value; + } + } + + public int Round + { + get + { + if (round == null) + { + round = turnSnapshot.getRound(); + } + return round.Value; + } + } + + public int Turn + { + get + { + if (turn == null) + { + turn = turnSnapshot.getTurn(); + } + return turn.Value; + } + } + + public IScoreSnapshot[] SortedTeamScores + { + get + { + if (sortedTeamScores == null) + { + sortedTeamScores = MapScoreSnapshots(turnSnapshot.getSortedTeamScores()); + } + return sortedTeamScores; + } + } + + public IScoreSnapshot[] IndexedTeamScores + { + get + { + if (indexedTeamScores == null) + { + indexedTeamScores = MapScoreSnapshots(turnSnapshot.getIndexedTeamScores()); + } + return indexedTeamScores; + } + } + } + + private class RobotSnapshot : IRobotSnapshot + { + // The real snapshot + private readonly robocode.control.snapshot.IRobotSnapshot robotSnapshot; + + // Cached values created, when needed + private string name; + private string shortName; + private string veryShortName; + private string teamName; + private int? robotIndex; + private int? teamIndex; + private RobotState? state; + private double? energy; + private double? velocity; + private double? bodyHeading; + private double? gunHeading; + private double? radarHeading; + private double? gunHeat; + private double? x; + private double? y; + private int? bodyColor; + private int? gunColor; + private int? radarColor; + private int? scanColor; + private bool? isDroid; + private bool? isPaintRobot; + private bool? isPaintEnabled; + private bool? isSGPaintEnabled; + private IDebugProperty[] debugProperties; + private string outputStreamSnapshot; + private IScoreSnapshot scoreSnapshot; + + public RobotSnapshot(robocode.control.snapshot.IRobotSnapshot robotSnapshot) + { + this.robotSnapshot = robotSnapshot; + } + + public string Name + { + get + { + if (name == null) + { + name = robotSnapshot.getName(); + } + return name; + } + } + + public string ShortName + { + get + { + if (shortName == null) + { + shortName = robotSnapshot.getShortName(); + } + return shortName; + } + } + + public string VeryShortName + { + get + { + if (veryShortName == null) + { + veryShortName = robotSnapshot.getVeryShortName(); + } + return veryShortName; + } + } + + public string TeamName + { + get + { + if (teamName == null) + { + teamName = robotSnapshot.getTeamName(); + } + return teamName; + } + } + + public int RobotIndex + { + get + { + if (robotIndex == null) + { + robotIndex = robotSnapshot.getRobotIndex(); + } + return robotIndex.Value; + } + } + + public int TeamIndex + { + get + { + if (teamIndex == null) + { + teamIndex = robotSnapshot.getTeamIndex(); + } + return teamIndex.Value; + } + } + + public int ContestantIndex + { + get + { + return TeamIndex >= 0 ? TeamIndex : RobotIndex; + } + } + + public RobotState State + { + get + { + if (state == null) + { + state = MapRobotState(robotSnapshot.getState()); + } + return state.Value; + } + } + + public double Energy + { + get + { + if (energy == null) + { + energy = robotSnapshot.getEnergy(); + } + return energy.Value; + } + } + + public double Velocity + { + get + { + if (velocity == null) + { + velocity = robotSnapshot.getVelocity(); + } + return velocity.Value; + } + } + + public double BodyHeading + { + get + { + if (bodyHeading == null) + { + bodyHeading = robotSnapshot.getBodyHeading(); + } + return bodyHeading.Value; + } + } + + public double GunHeading + { + get + { + if (gunHeading == null) + { + gunHeading = robotSnapshot.getGunHeading(); + } + return gunHeading.Value; + } + } + + public double RadarHeading + { + get + { + if (radarHeading == null) + { + radarHeading = robotSnapshot.getRadarHeading(); + } + return radarHeading.Value; + } + } + + public double GunHeat + { + get + { + if (gunHeat == null) + { + gunHeat = robotSnapshot.getGunHeat(); + } + return gunHeat.Value; + } + } + + public double X + { + get + { + if (x == null) + { + x = robotSnapshot.getX(); + } + return x.Value; + } + } + + public double Y + { + get + { + if (y == null) + { + y = robotSnapshot.getY(); + } + return y.Value; + } + } + + public int BodyColor + { + get + { + if (bodyColor == null) + { + bodyColor = robotSnapshot.getBodyColor(); + } + return bodyColor.Value; + } + } + + public int GunColor + { + get + { + if (gunColor == null) + { + gunColor = robotSnapshot.getGunColor(); + } + return gunColor.Value; + } + } + + public int RadarColor + { + get + { + if (radarColor == null) + { + radarColor = robotSnapshot.getRadarColor(); + } + return radarColor.Value; + } + } + + public int ScanColor + { + get + { + if (scanColor == null) + { + scanColor = robotSnapshot.getScanColor(); + } + return scanColor.Value; + } + } + + public bool IsDroid + { + get + { + if (isDroid == null) + { + isDroid = robotSnapshot.isDroid(); + } + return isDroid.Value; + } + } + + public bool IsPaintRobot + { + get + { + if (isPaintRobot == null) + { + isPaintRobot = robotSnapshot.isPaintRobot(); + } + return isPaintRobot.Value; + } + } + + public bool IsPaintEnabled + { + get + { + if (isPaintEnabled == null) + { + isPaintEnabled = robotSnapshot.isPaintEnabled(); + } + return isPaintEnabled.Value; + } + } + + public bool IsSGPaintEnabled + { + get + { + if (isSGPaintEnabled == null) + { + isSGPaintEnabled = robotSnapshot.isSGPaintEnabled(); + } + return isSGPaintEnabled.Value; + } + } + + public IDebugProperty[] DebugProperties + { + get + { + if (debugProperties == null) + { + debugProperties = MapDebugProperties(robotSnapshot.getDebugProperties()); + } + return debugProperties; + } + } + + public string OutputStreamSnapshot + { + get + { + if (outputStreamSnapshot == null) + { + outputStreamSnapshot = robotSnapshot.getOutputStreamSnapshot(); + } + return outputStreamSnapshot; + } + } + + public IScoreSnapshot ScoreSnapshot + { + get + { + if (scoreSnapshot == null) + { + scoreSnapshot = MapScoreSnapshot(robotSnapshot.getScoreSnapshot()); + } + return scoreSnapshot; + } + } + } + + private class BulletSnapshot : IBulletSnapshot + { + // The real snapshot + private readonly robocode.control.snapshot.IBulletSnapshot bulletSnapshot; + + // Cached values created, when needed + private BulletState? state; + private double? power; + private double? x; + private double? y; + private double? paintX; + private double? paintY; + private int? color; + private int? frame; + private bool? isExplosion; + private int? explosionImageIndex; + private int? bulletId; + + public BulletSnapshot(robocode.control.snapshot.IBulletSnapshot bulletSnapshot) + { + this.bulletSnapshot = bulletSnapshot; + } + + public BulletState State + { + get + { + if (state == null) + { + state = MapBulletState(bulletSnapshot.getState()); + } + return state.Value; + } + } + + public double Power + { + get + { + if (power == null) + { + power = bulletSnapshot.getPower(); + } + return power.Value; + } + } + + public double X + { + get + { + if (x == null) + { + x = bulletSnapshot.getX(); + } + return x.Value; + } + } + + public double Y + { + get + { + if (y == null) + { + y = bulletSnapshot.getY(); + } + return y.Value; + } + } + + public double PaintX + { + get + { + if (paintX == null) + { + paintX = bulletSnapshot.getPaintX(); + } + return paintX.Value; + } + } + + public double PaintY + { + get + { + if (paintY == null) + { + paintY = bulletSnapshot.getPaintY(); + } + return paintY.Value; + } + } + + public int Color + { + get + { + if (color == null) + { + color = bulletSnapshot.getColor(); + } + return color.Value; + } + } + + public int Frame + { + get + { + if (frame == null) + { + frame = bulletSnapshot.getFrame(); + } + return frame.Value; + } + } + + public bool IsExplosion + { + get + { + if (isExplosion == null) + { + isExplosion = bulletSnapshot.isExplosion(); + } + return isExplosion.Value; + } + } + + public int ExplosionImageIndex + { + get + { + if (explosionImageIndex == null) + { + explosionImageIndex = bulletSnapshot.getExplosionImageIndex(); + } + return explosionImageIndex.Value; + } + } + + public int BulletId + { + get + { + if (bulletId == null) + { + bulletId = bulletSnapshot.getBulletId(); + } + return bulletId.Value; + } + } + } + + private class ScoreSnapshot : IScoreSnapshot + { + // The real snapshot + private readonly robocode.control.snapshot.IScoreSnapshot scoreSnapshot; + + // Cached values created, when needed + private string name; + private double? totalScore; + private double? totalSurvivalScore; + private double? totalLastSurvivorBonus; + private double? totalBulletDamageScore; + private double? totalBulletKillBonus; + private double? totalRammingDamageScore; + private double? totalRammingKillBonus; + private int? totalFirsts; + private int? totalSeconds; + private int? totalThirds; + private double? currentScore; + private double? currentSurvivalScore; + private double? currentSurvivalBonus; + private double? currentBulletDamageScore; + private double? currentBulletKillBonus; + private double? currentRammingDamageScore; + private double? currentRammingKillBonus; + + public ScoreSnapshot(robocode.control.snapshot.IScoreSnapshot scoreSnapshot) + { + this.scoreSnapshot = scoreSnapshot; + } + + public int CompareTo(IScoreSnapshot snapshot) + { + double myScore = TotalScore + CurrentScore; + double hisScore = snapshot.TotalScore + snapshot.CurrentScore; + + if (myScore < hisScore) + { + return -1; + } + if (myScore > hisScore) + { + return 1; + } + return 0; + } + + public string Name + { + get + { + if (name == null) + { + name = scoreSnapshot.getName(); + } + return name; + } + } + + public double TotalScore + { + get + { + if (totalScore == null) + { + totalScore = scoreSnapshot.getTotalScore(); + } + return totalScore.Value; + } + } + + public double TotalSurvivalScore + { + get + { + if (totalSurvivalScore == null) + { + totalSurvivalScore = scoreSnapshot.getTotalSurvivalScore(); + } + return totalSurvivalScore.Value; + } + } + + public double TotalLastSurvivorBonus + { + get + { + if (totalLastSurvivorBonus == null) + { + totalLastSurvivorBonus = scoreSnapshot.getTotalLastSurvivorBonus(); + } + return totalLastSurvivorBonus.Value; + } + } + + public double TotalBulletDamageScore + { + get + { + if (totalBulletDamageScore == null) + { + totalBulletDamageScore = scoreSnapshot.getTotalBulletDamageScore(); + } + return totalBulletDamageScore.Value; + } + } + + public double TotalBulletKillBonus + { + get + { + if (totalBulletKillBonus == null) + { + totalBulletKillBonus = scoreSnapshot.getTotalBulletKillBonus(); + } + return totalBulletKillBonus.Value; + } + } + + public double TotalRammingDamageScore + { + get + { + if (totalRammingDamageScore == null) + { + totalRammingDamageScore = scoreSnapshot.getTotalRammingDamageScore(); + } + return totalRammingDamageScore.Value; + } + } + + public double TotalRammingKillBonus + { + get + { + if (totalRammingKillBonus == null) + { + totalRammingKillBonus = scoreSnapshot.getTotalRammingKillBonus(); + } + return totalRammingKillBonus.Value; + } + } + + public int TotalFirsts + { + get + { + if (totalFirsts == null) + { + totalFirsts = scoreSnapshot.getTotalFirsts(); + } + return totalFirsts.Value; + } + } + + public int TotalSeconds + { + get + { + if (totalSeconds == null) + { + totalSeconds = scoreSnapshot.getTotalSeconds(); + } + return totalSeconds.Value; + } + } + + public int TotalThirds + { + get + { + if (totalThirds == null) + { + totalThirds = scoreSnapshot.getTotalThirds(); + } + return totalThirds.Value; + } + } + + public double CurrentScore + { + get + { + if (currentScore == null) + { + currentScore = scoreSnapshot.getCurrentScore(); + } + return currentScore.Value; + } + } + + public double CurrentSurvivalScore + { + get + { + if (currentSurvivalScore == null) + { + currentSurvivalScore = scoreSnapshot.getCurrentSurvivalScore(); + } + return currentSurvivalScore.Value; + } + } + + public double CurrentSurvivalBonus + { + get + { + if (currentSurvivalBonus == null) + { + currentSurvivalBonus = scoreSnapshot.getCurrentSurvivalBonus(); + } + return currentSurvivalBonus.Value; + } + } + + public double CurrentBulletDamageScore + { + get + { + if (currentBulletDamageScore == null) + { + currentBulletDamageScore = scoreSnapshot.getCurrentBulletDamageScore(); + } + return currentBulletDamageScore.Value; + } + } + + public double CurrentBulletKillBonus + { + get + { + if (currentBulletKillBonus == null) + { + currentBulletKillBonus = scoreSnapshot.getCurrentBulletKillBonus(); + } + return currentBulletKillBonus.Value; + } + } + + public double CurrentRammingDamageScore + { + get + { + if (currentRammingDamageScore == null) + { + currentRammingDamageScore = scoreSnapshot.getCurrentBulletKillBonus(); + } + return currentRammingDamageScore.Value; + } + } + + public double CurrentRammingKillBonus + { + get + { + if (currentRammingKillBonus == null) + { + currentRammingKillBonus = scoreSnapshot.getCurrentRammingKillBonus(); + } + return currentRammingKillBonus.Value; + } + } + } + + private class DebugProperty : IDebugProperty + { + private readonly string key; + private readonly string value; + + public DebugProperty(string key, string value) + { + this.key = key; + this.value = value; + } + + public string Key + { + get { return key; } + } + + public string Value + { + get { return value; } + } + } + + #endregion + + #region robocode.control.RobotSpecification wrapper + + private class RobotSpecificationWrapper : robocode.control.RobotSpecification + { + private readonly string name; + private readonly string author; + private readonly string webpage; + private readonly string version; + private readonly string robocodeVersion; + private readonly string archiveFilePath; + private readonly string fullClassName; + private readonly string description; + private readonly string teamId; + + public RobotSpecificationWrapper(string name, string author, string webpage, string version, + string robocodeVersion, string archiveFilePath, string fullClassName, string description, string teamId) + : base(null) + { + this.name = name; + this.author = author; + this.webpage = webpage; + this.version = version; + this.robocodeVersion = robocodeVersion; + this.archiveFilePath = archiveFilePath; + this.fullClassName = fullClassName; + this.description = description; + this.teamId = teamId; + } + + public override java.lang.String getName() + { + return name; + } + + public override java.lang.String getVersion() + { + return version; + } + + public override java.lang.String getNameAndVersion() + { + string nameAndVersion = getName(); + string version = getVersion(); + + if (version != null && version.Trim().Length > 0) + { + nameAndVersion += ' ' + version.Trim(); + } + return nameAndVersion; + } + + public override java.lang.String getClassName() + { + return fullClassName; + } + + public override java.io.File getJarFile() + { + return new java.io.File(archiveFilePath); + } + + public override java.lang.String getDescription() + { + return description; + } + + public override java.lang.String getRobocodeVersion() + { + return robocodeVersion; + } + + public override java.lang.String getWebpage() + { + return webpage; + } + + public override java.lang.String getAuthorName() + { + return author; + } + + public override java.lang.String getTeamId() + { + return teamId; + } + } + + #endregion + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobotSetup.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobotSetup.cs new file mode 100644 index 0000000..28b4299 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobotSetup.cs @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; + +namespace Robocode.Control +{ + /// + /// Contains the initial position and heading for a robot. + /// + [Serializable] + public class RobotSetup + { + private readonly Double x; + private readonly Double y; + private readonly Double heading; + + /// + /// Constructs a new RobotSetup. + /// + /// The x coordinate, where null means random. + /// The y coordinate, where null means random. + /// The heading in degrees of the body, gun, and radar, where null means random. + public RobotSetup(Double x, Double y, Double heading) + { + this.x = x; + this.y = y; + this.heading = heading; + } + + /// + /// Contains the x coordinate. + /// + /// + /// The x coordinate, where null means unspecified (random). + /// + public Double X + { + get { return x; } + } + + /// + /// Contains the y coordinate. + /// + /// + /// The y coordinate, where null means unspecified (random). + /// + public Double Y + { + get { return y; } + } + + /// + /// Contains the body, gun, and radar heading (in degrees). + /// + /// + /// The heading (in degrees), where null means unspecified (random). + /// + public Double Heading + { + get { return heading; } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobotSpecification.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobotSpecification.cs new file mode 100644 index 0000000..77d6eff --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/RobotSpecification.cs @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Robocode.Control +{ + /// + /// Defines the properties of a robot, which is returned from + /// . + /// + [Serializable] + public class RobotSpecification + { + internal readonly robocode.control.RobotSpecification robotSpecification; + + internal RobotSpecification(robocode.control.RobotSpecification robotSpecification) + { + this.robotSpecification = robotSpecification; + } + + /// + /// Contains the name of this robot or team. + /// + /// + /// The name of this robot or team. + /// + /// + /// + public string Name + { + get { return robotSpecification.getName(); } + } + + /// + /// Contains the version of this robot or team. + /// + /// + /// The version of this robot or team. + /// + /// + /// + public string Version + { + get { return robotSpecification.getVersion(); } + } + + /// + /// Contains the name and version of this robot or team. + /// + /// + /// The name and version of this robot or team. + /// + /// + /// + private string NameAndVersion + { + get { return robotSpecification.getNameAndVersion(); } + } + + /// + /// Contains the full class name of this robot or team. + /// + /// + /// The full class name of this robot or team. + /// + public string ClassName + { + get { return robotSpecification.getClassName(); } + } + + /// + /// Contains the path of the archive file containing this robot or team. + /// + /// + /// The path of the archive file containing this robot or team or null + /// if it does not come from an archive file (could be class files instead). + /// + public string ArchiveFilePath + { + get { return robotSpecification.getJarFile().getAbsolutePath(); } + } + + /// + /// Contains the description provided by the author of this robot or team. + /// + /// + /// The description provided by the author of this robot or team. + /// + public string Description + { + get { return robotSpecification.getDescription(); } + } + + /// + /// Contains the version of Robocode this robot or team was build with. + /// + /// + /// The version of Robocode this robot or team was build with. + /// + public string RobocodeVersion + { + get { return robotSpecification.getRobocodeVersion(); } + } + + /// + /// Contains the link to the web page for this robot or team. + /// + /// + /// The link to the web page for this robot or team. + /// + public string Webpage + { + get { return robotSpecification.getWebpage(); } + } + + /// + /// Contains the name of the author of this robot or team. + /// + /// + /// The name of the author of this robot or team. + /// + public string AuthorName + { + get { return robotSpecification.getAuthorName(); } + } + + /// + /// Contains the id of the robot team. + /// + /// + /// The id of the robot team. + /// + public string TeamId + { + get { return robotSpecification.getTeamId(); } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleCompletedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleCompletedEvent.cs new file mode 100644 index 0000000..5f5e156 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleCompletedEvent.cs @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when a battle has completed successfully where results are available. + /// This event will not occur if the battle is terminated or aborted by the user before the + /// battle is completed. + /// + /// + /// + public class BattleCompletedEvent : BattleEvent + { + private readonly BattleRules battleRules; + private readonly BattleResults[] results; + + // Called by the game to create an instance of this event. + // Note: This constructor should not be available in the API. + internal BattleCompletedEvent(BattleRules battleRules, BattleResults[] results) + : base() + { + this.battleRules = battleRules; + this.results = results; + } + + /// + /// Contains the rules used in the battle. + /// + /// + /// The rules used in the battle. + /// + public BattleRules BattleRules + { + get { return battleRules; } + } + + /// + /// Contains the battle results sorted on score. + /// Note that the robot index cannot be used to determine the score with the sorted results. + /// + /// + /// An array of sorted BattleResults, where the results with the bigger score are placed first in the list. + /// + /// + public BattleResults[] SortedResults + { + get + { + List copy = new List(results); + copy.Sort(); + copy.Reverse(); + return copy.ToArray(); + } + } + + /// + /// Contains the battle results that can be used to determine the score for the individual robot based + /// on the robot index. + /// + /// + /// An array of indexed BattleResults, where each index matches an index of a specific robot. + /// + /// + public BattleResults[] IndexedResults + { + get + { + BattleResults[] copy = new BattleResults[results.Length]; + results.CopyTo(copy, 0); + return copy; + } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleErrorEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleErrorEvent.cs new file mode 100644 index 0000000..58ab08c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleErrorEvent.cs @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when an error message is sent from the game in the during the battle. + /// + /// + public class BattleErrorEvent : BattleEvent + { + private readonly string error; + + // Called by the game to create an instance of this event. + // Note: This constructor should not be available in the API. + internal BattleErrorEvent(string error) + : base() + { + this.error = error; + } + + /// + /// Contains the error message. + /// + /// + /// The error message that was sent from the game during the battle. + /// + public string Error + { + get { return error; } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleEvent.cs new file mode 100644 index 0000000..630c309 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleEvent.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// This is the base class of all battle events. + /// + public abstract class BattleEvent + { + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleFinishedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleFinishedEvent.cs new file mode 100644 index 0000000..032783c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleFinishedEvent.cs @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when the battle is finished. This event is always sent as the last battle event, + /// both when the battle is completed successfully, terminated due to an error, or aborted by the user. + /// Hence, this events is well-suited for cleanup after the battle. + /// + /// + /// + public class BattleFinishedEvent : BattleEvent + { + private readonly bool isAborted; + + // Called by the game to create an instance of this event. + // Note: This constructor should not be available in the API. + internal BattleFinishedEvent(bool isAborted) + : base() + { + this.isAborted = isAborted; + } + + /// + /// Flag specifying if the battle was aborted. + /// + /// + /// true if the battle was aborted; false otherwise. + /// + public bool IsAborted + { + get { return isAborted; } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleMessageEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleMessageEvent.cs new file mode 100644 index 0000000..944f159 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleMessageEvent.cs @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when an informal message is sent from the game in the during the battle. + /// + /// + public class BattleMessageEvent : BattleEvent + { + private readonly string message; + + // Called by the game to create an instance of this event. + // Note: This constructor should not be available in the API. + internal BattleMessageEvent(string message) + : base() + { + this.message = message; + } + + /// + /// Contains the informal message. + /// + /// + /// The informal message that was sent from the game during the battle. + /// + public string Message + { + get { return message; } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattlePausedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattlePausedEvent.cs new file mode 100644 index 0000000..14a247c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattlePausedEvent.cs @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when a battle has been paused. + /// + /// + public class BattlePausedEvent : BattleEvent + { + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleResumedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleResumedEvent.cs new file mode 100644 index 0000000..2f267a8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleResumedEvent.cs @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when a battle has been resumed (after having been paused). + /// + /// + public class BattleResumedEvent : BattleEvent + { + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleStartedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleStartedEvent.cs new file mode 100644 index 0000000..49d81d3 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/BattleStartedEvent.cs @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when a new battle is started. + /// + /// + /// + public class BattleStartedEvent : BattleEvent + { + private readonly BattleRules battleRules; + private readonly bool isReplay; + private readonly int robotsCount; + + // Called by the game to create an instance of this event. + // Note: This constructor should not be available in the API. + internal BattleStartedEvent(BattleRules battleRules, int robotsCount, bool isReplay) + : base() + { + this.battleRules = battleRules; + this.isReplay = isReplay; + this.robotsCount = robotsCount; + } + + /// + /// Contains the rules that will be used in the battle. + /// + /// + /// The rules that will be used in the battle. + /// + public BattleRules BattleRules + { + get { return battleRules; } + } + + /// + /// Contains the number of robots participating in the battle. + /// + /// + /// The number of robots participating in the battle. + /// + public int RobotsCount + { + get { return robotsCount; } + } + + /// + /// Flag specifying if this battle is a replay or a new battle. + /// + /// + /// true if the battle is a replay; false otherwise. + /// + public bool IsReplay + { + get { return isReplay; } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/RoundEndedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/RoundEndedEvent.cs new file mode 100644 index 0000000..5bbad5f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/RoundEndedEvent.cs @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when the current round of a battle has ended. + /// + /// + public class RoundEndedEvent : BattleEvent + { + private readonly int round; + private readonly int turns; + private readonly int totalTurns; + + // Called by the game to create an instance of this event. + // Note: This constructor should not be available in the API. + internal RoundEndedEvent(int round, int turns, int totalTurns) + : base() + { + this.round = round; + this.turns = turns; + this.totalTurns = totalTurns; + } + + /// + /// Contains the round number that has ended. + /// + /// + /// The round number that has ended, which is zero indexed. + /// + public int Round + { + get { return round; } + } + + /// + /// Contains the number of turns that this round reached. + /// + /// + /// The number of turns that this round reached. + /// + /// + public int Turns + { + get { return turns; } + } + + /// + /// Contains the total number of turns reached in the battle when this round ended. + /// + /// + /// The total number of turns reached in the battle when this round ended. + /// + /// + public int TotalTurns + { + get { return totalTurns; } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/RoundStartedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/RoundStartedEvent.cs new file mode 100644 index 0000000..f8e1530 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/RoundStartedEvent.cs @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; +using Robocode.Control.Snapshot; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when a new round in a battle is started. + /// + /// + public class RoundStartedEvent : BattleEvent + { + private readonly ITurnSnapshot startSnapshot; + private readonly int round; + + // Called by the game to create an instance of this event. + // Note: This constructor should not be available in the API. + internal RoundStartedEvent(ITurnSnapshot startSnapshot, int round) + : base() + { + this.startSnapshot = startSnapshot; + this.round = round; + } + + /// + /// Contains the start snapshot of the participating robots, initial starting positions etc. + /// + /// + /// A that serves as the start snapshot of the round. + /// + public ITurnSnapshot StartSnapshot + { + get { return startSnapshot; } + } + + /// + /// Contains the round number. + /// + /// + /// The round number, which is zero indexed. + /// + public int Round + { + get { return round; } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/TurnEndedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/TurnEndedEvent.cs new file mode 100644 index 0000000..a97ab93 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/TurnEndedEvent.cs @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; +using Robocode.Control.Snapshot; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when when the current turn in a battle round is ended. + /// + /// + public class TurnEndedEvent : BattleEvent + { + private readonly ITurnSnapshot turnSnapshot; + + // Called by the game to create an instance of this event. + // Note: This constructor should not be available in the API. + internal TurnEndedEvent(ITurnSnapshot turnSnapshot) + : base() + { + this.turnSnapshot = turnSnapshot; + } + + /// + /// Contains a snapshot of the turn that has ended. + /// + /// + /// A snapshot of the turn that has ended. + /// + public ITurnSnapshot TurnSnapshot + { + get { return turnSnapshot; } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/TurnStartedEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/TurnStartedEvent.cs new file mode 100644 index 0000000..b6c0284 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/events/TurnStartedEvent.cs @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Events +{ + /// + /// Contains information about a event that is + /// triggered when a new turn in a battle round is started. + /// + /// + public class TurnStartedEvent : BattleEvent + { + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/BulletState.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/BulletState.cs new file mode 100644 index 0000000..bc1ebfd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/BulletState.cs @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Snapshot +{ + /// + /// Defines a bullet state, which can be: just fired, moving somewhere, hitting a victim, + /// hitting another bullet, hitting the wall, exploded, or inactive. + /// + public enum BulletState + { + /// + /// The bullet has just been fired this turn and hence just been created. + /// This state only last one turn. + /// + Fired = 0, + + /// + /// The bullet is now moving across the battlefield, but has not hit anything yet. + /// + Moving = 1, + + /// + /// The bullet has hit a robot victim. + /// + HitVictim = 2, + + /// + /// The bullet has hit another bullet. + /// + HitBullet = 3, + + /// + /// The bullet has the wall, i.e. one of the four borders of the battlefield. + /// + HitWall = 4, + + /// + /// The bullet currently represents a robot explosion, i.e. a robot death. + /// + Exploded = 5, + + /// + /// The bullet is currently inactive. Hence, it is not active or visible on the battlefield. + /// + Inactive = 6 + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IBulletSnapshot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IBulletSnapshot.cs new file mode 100644 index 0000000..2a5406f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IBulletSnapshot.cs @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Snapshot +{ + /// + /// Interface of a bullet snapshot at a specific time in a battle. + /// + public interface IBulletSnapshot + { + /// + /// Contains the bullet state. + /// + /// + /// The bullet state. + /// + BulletState State { get; } + + /// + /// Contains the bullet power. + /// + /// + /// The bullet power. + /// + double Power { get; } + + /// + /// Contains the X position of the bullet. + /// + /// + /// The X position of the bullet. + /// + double X { get; } + + /// + /// Contains the Y position of the bullet. + /// + /// + /// The Y position of the bullet. + /// + double Y { get; } + + /// + /// Contains the X painting position of the bullet. + /// Note that this is not necessarily equal to the X position of the bullet, even though + /// it will be in most cases. The painting position of the bullet is needed as the bullet + /// will "stick" to its victim when it has been hit, but only visually. + /// + /// + /// The X painting position of the bullet. + /// + double PaintX { get; } + + /// + /// Contains the Y painting position of the bullet. + /// Note that this is not necessarily equal to the Y position of the bullet, even though + /// it will be in most cases. The painting position of the bullet is needed as the bullet + /// will "stick" to its victim when it has been hit, but only visually. + /// + /// + /// The Y painting position of the bullet. + /// + double PaintY { get; } + + /// + /// Contains the color of the bullet. + /// + /// + /// An ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + /// + int Color { get; } + + /// + /// Contains the current frame number to display, i.e. when the bullet explodes. + /// + /// + /// The current frame number. + /// + /// + /// + int Frame { get; } + + /// + /// Flag specifying if the bullet has become an explosion. + /// + /// + /// true if the bullet is an explosion; false otherwise. + /// + /// + /// + bool IsExplosion { get; } + + /// + /// Contains the explosion image index, which is different depending on the type of explosion. + /// E.g. if it is a small explosion on a robot that has been hit by this bullet, + /// or a big explosion when a robot dies. + /// + /// + /// The explosion image index. + /// + /// + /// + int ExplosionImageIndex { get; } + + /// + /// Contains the ID of the bullet used for identifying the bullet in a collection of bullets. + /// + /// + /// The ID of the bullet. + /// + int BulletId { get; } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IDebugProperty.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IDebugProperty.cs new file mode 100644 index 0000000..5be249e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IDebugProperty.cs @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Snapshot +{ + /// + /// Interface of a debug property, which is a key-value pair. + /// + public interface IDebugProperty + { + /// + /// Contains the key of the property. + /// + /// + /// The key of the property. + /// + string Key { get; } + + /// + /// Contains the value of the property. + /// + /// + /// The value of the property. + /// + string Value { get; } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IRobotSnapshot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IRobotSnapshot.cs new file mode 100644 index 0000000..82ab270 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IRobotSnapshot.cs @@ -0,0 +1,248 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Snapshot +{ + /// + /// Interface of a robot snapshot at a specific time in a battle. + /// + public interface IRobotSnapshot + { + /// + /// Contains the name of the robot. + /// + /// + /// The name of the robot. + /// + string Name { get; } + + /// + /// Contains the short name of the robot. + /// + /// + /// The short name of the robot. + /// + string ShortName { get; } + + /// + /// Contains the very short name of the robot. + /// + /// + /// The very short name of the robot. + /// + string VeryShortName { get; } + + /// + /// Contains the name of the team, which can be the name of a robot if the contestant is not a team, but a robot. + /// + /// + /// The name of the team. + /// + string TeamName { get; } + + /// + /// Contains the index of the robot, which is unique for the specific robot and constant during a battle. + /// Since: 1.7.4.0 + /// + /// + /// The robot index. + /// + /// + int RobotIndex { get; } + + /// + /// Contains the index of the team that this robot is a member of, which is unique for the specific team and constant + /// during a battle. + /// Since: 1.7.4.0 + /// + /// + /// The team index or -1 if the robot is not a member of a team. + /// + /// + int TeamIndex { get; } + + /// + /// Contains the contestant index, which is unique for each robot or team participating in a battle. + /// Note: If a team of robots is participating in a battle, this method will return the team index (see + /// ); otherwise the robot index (see ) is used instead. + /// This method is used for the battle results as scores are calculated for either a team of robots or individual + /// robot. + /// + /// + /// The contestant index of the robot or team. + /// + /// + /// + int ContestantIndex { get; } + + /// + /// Contains the robot state. + /// + /// + /// The robot state. + /// + RobotState State { get; } + + /// + /// Contains the energy level of the robot. + /// + /// + /// The energy level of the robot. + /// + double Energy { get; } + + /// + /// Contains the velocity of the robot. + /// + /// + /// The velocity of the robot. + /// + double Velocity { get; } + + /// + /// Contains the body heading of the robot in radians. + /// + /// + /// The body heading of the robot in radians. + /// + double BodyHeading { get; } + + /// + /// Contains the gun heading of the robot in radians. + /// + /// + /// The gun heading of the robot in radians. + /// + double GunHeading { get; } + + /// + /// Contains the radar heading of the robot in radians. + /// + /// + /// The radar heading of the robot in radians. + /// + double RadarHeading { get; } + + /// + /// Contains the gun heat of the robot. + /// + /// + /// The gun heat of the robot. + /// + double GunHeat { get; } + + /// + /// Contains the X position of the robot. + /// + /// + /// The X position of the robot. + /// + double X { get; } + + /// + /// Contains the Y position of the robot. + /// + /// + /// The Y position of the robot. + /// + double Y { get; } + + /// + /// Contains the color of the body. + /// + /// + /// An ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + /// + int BodyColor { get; } + + /// + /// Contains the color of the gun. + /// + /// + /// An ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + /// + int GunColor { get; } + + /// + /// Contains the color of the radar. + /// + /// + /// An ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + /// + int RadarColor { get; } + + /// + /// Contains the color of the scan arc. + /// + /// + /// An ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + /// + int ScanColor { get; } + + /// + /// Flag specifying if this robot is an . + /// + /// + /// true if this robot is an ; false otherwise. + /// + bool IsDroid { get; } + + /// + /// Flag specifying if this robot is an . + /// + /// + /// true if this robot is an ; false otherwise. + /// + bool IsPaintRobot { get; } + + /// + /// Flag specifying if painting is enabled for this robot. + /// + /// + /// true if painting is enabled for this robot; false otherwise. + /// + bool IsPaintEnabled { get; } + + /// + /// Flag specifying if RobocodeSG painting (the point (0,0) is in the upper left corner) is enabled for this robot. + /// + /// + /// true if RobocodeSG painting is enabled for this robot; false otherwise. + /// + bool IsSGPaintEnabled { get; } + + /// + /// Contains a snapshot of debug properties. + /// + /// + /// A snapshot of debug properties. + /// + IDebugProperty[] DebugProperties { get; } + + /// + /// Contains a snapshot of the output print stream for this robot. + /// + /// + /// A string containing the snapshot of the output print stream. + /// + string OutputStreamSnapshot { get; } + + /// + /// Contains a snapshot of the current score for this robot. + /// + /// + /// A snapshot of the current score for this robot. + /// + IScoreSnapshot ScoreSnapshot { get; } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IScoreSnapshot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IScoreSnapshot.cs new file mode 100644 index 0000000..8e050e8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/IScoreSnapshot.cs @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Snapshot +{ + /// + /// Interface of a bullet snapshot at a specific time in a battle. + /// + public interface IScoreSnapshot : IComparable + { + /// + /// Contains the name of the contestant, i.e. a robot or team. + /// + /// + /// The name of the contestant, i.e. a robot or team. + /// + string Name { get; } + + /// + /// Contains the total score. + /// + /// + /// The total score. + /// + double TotalScore { get; } + + /// + /// Contains the total survival score. + /// + /// + /// The total survival score. + /// + double TotalSurvivalScore { get; } + + /// + /// Contains the total last survival score. + /// + /// + /// The total last survival score. + /// + double TotalLastSurvivorBonus { get; } + + /// + /// Contains the total bullet damage score. + /// + /// + /// The total bullet damage score. + /// + double TotalBulletDamageScore { get; } + + /// + /// Contains the total bullet kill bonus. + /// + /// + /// The total bullet kill bonus. + /// + double TotalBulletKillBonus { get; } + + /// + /// Contains the total ramming damage score. + /// + /// + /// The total ramming damage score. + /// + double TotalRammingDamageScore { get; } + + /// + /// Contains the total ramming kill bonus. + /// + /// + /// The total ramming kill bonus. + /// + double TotalRammingKillBonus { get; } + + /// + /// Contains the total number of first places. + /// + /// + /// The total number of first places. + /// + int TotalFirsts { get; } + + /// + /// Contains the total number of second places. + /// + /// + /// The total number of second places. + /// + int TotalSeconds { get; } + + /// + /// Contains the total number of third places. + /// + /// + /// The total number of third places. + /// + int TotalThirds { get; } + + /// + /// Contains the current score. + /// + /// + /// The current score. + /// + double CurrentScore { get; } + + /// + /// Contains the current survival score. + /// + /// + /// The current survival score. + /// + double CurrentSurvivalScore { get; } + + /// + /// Contains the current survival bonus. + /// + /// + /// The current survival bonus. + /// + double CurrentSurvivalBonus { get; } + + /// + /// Contains the current bullet damage score. + /// + /// + /// The current bullet damage score. + /// + double CurrentBulletDamageScore { get; } + + /// + /// Contains the current bullet kill bonus. + /// + /// + /// The current bullet kill bonus. + /// + double CurrentBulletKillBonus { get; } + + /// + /// Contains the current ramming damage score. + /// + /// + /// The current ramming damage score. + /// + double CurrentRammingDamageScore { get; } + + /// + /// Contains the current ramming kill bonus. + /// + /// + /// The current ramming kill bonus. + /// + double CurrentRammingKillBonus { get; } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/ITurnSnapshot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/ITurnSnapshot.cs new file mode 100644 index 0000000..855969f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/ITurnSnapshot.cs @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Snapshot +{ + /// + /// Interface of a battle turn snapshot at a specific time in a battle. + /// + public interface ITurnSnapshot + { + /// + /// Contains a list of snapshots for the robots participating in the battle. + /// + /// + /// A list of snapshots for the robots participating in the battle. + /// + IRobotSnapshot[] Robots { get; } + + /// + /// Contains a list of snapshots for the bullets that are currently on the battlefield. + /// + /// + /// A list of snapshots for the bullets that are currently on the battlefield. + /// + IBulletSnapshot[] Bullets { get; } + + /// + /// Contains the current TPS (turns per second) rate. + /// + /// + /// The current TPS (turns per second) rate. + /// + int TPS { get; } + + /// + /// Contains the current round of the battle. + /// + /// + /// The current round of the battle. + /// + int Round { get; } + + /// + /// Contains the current turn in the battle round. + /// + /// + /// The current turn in the battle round. + /// + int Turn { get; } + + /// + /// Contains an array of sorted scores grouped by teams, ordered by position. + /// Note that the team index cannot be used to determine the score with the sorted scores. + /// + /// + /// An array of sorted IScoreSnapshots, where the bigger scores are placed first in the list. + /// + /// + IScoreSnapshot[] SortedTeamScores { get; } + + /// + /// Contains an array of indexed scores grouped by teams that can be used to determine the score + /// for the individual team based on the team index. + /// + /// + /// An array of indexed IScoreSnapshots, where each index matches an index of a specific team. + /// + /// + IScoreSnapshot[] IndexedTeamScores { get; } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/RobotState.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/RobotState.cs new file mode 100644 index 0000000..c60d2ce --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/implementation/robocode/control/snapshot/RobotState.cs @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Robocode.Control.Snapshot +{ + /// + /// Defines a robot state, which can be: active on the battlefield, hitting a wall or robot this turn, or dead. + /// + public enum RobotState + { + /// + /// The robot is active on the battlefield and has not hit the wall or a robot at this turn. + /// + Active = 0, + + /// + /// The robot has hit a wall, i.e. one of the four borders, at this turn. This state only last one turn. + /// + HitWall = 1, + + /// + /// The robot has hit another robot at this turn. This state only last one turn. + /// + HitRobot = 2, + + /// + /// The robot is dead. + /// + Dead = 3 + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/robocode.dotnet.control.api.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/robocode.dotnet.control.api.csproj new file mode 100644 index 0000000..3ac19b0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/robocode.dotnet.control.api.csproj @@ -0,0 +1,200 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {674AED55-B9EC-4C7D-8E0B-1B2471C578B2} + Library + Robocode.Control + robocode.control + v3.5 + 512 + true + ..\..\tools\keys\robocode.snk + + + robocode.ico + + + 3.5 + + + + true + full + false + ..\target\ + ..\target\obj\ + DEBUG;TRACE + prompt + 4 + false + true + + + pdbonly + true + ..\target\ + ..\target\obj\ + + + prompt + 4 + true + + + + False + ..\..\tools\lib\jni4net.n-0.8.7.0.dll + + + + + + + + implementation\robocode\AssemblyInfo.cs + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {7E0900D3-6E8F-48EB-86DB-AA767AA90B84} + robocode.dotnet.api + + + + + + + + + if not exist $(OutDir)\build-sources\generated-sources\META-INF mkdir $(OutDir)\build-sources\generated-sources\META-INF\ +echo [assembly: System.Reflection.AssemblyVersion("1.9.2.4")] > $(OutDir)\build-sources\generated-sources\META-INF\AssemblyInfo.cs + + copy "$(TargetPath)" "$(SolutionDir)\robocode.dotnet.host\target" +copy "$(SolutionDir)\tools\lib\*.dll" "$(TargetDir)" +copy "$(SolutionDir)\tools\lib\*.jar" "$(TargetDir)" +copy "$(SolutionDir)\tools\lib\*.dll" "$(SolutionDir)\robocode.dotnet.host\target" + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/robocode.ico b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.control.api/src/robocode.ico new file mode 100644 index 0000000000000000000000000000000000000000..bbd6ef5791df03f733539e843b43296b8aae5324 GIT binary patch literal 25214 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 A!~g&Q literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.classpath b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.classpath new file mode 100644 index 0000000..90e2c30 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.classpath @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.project new file mode 100644 index 0000000..86e4817 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.project @@ -0,0 +1,22 @@ + + + robocode.dotnet.distribution + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.dotnet.api + robocode.dotnet.control.api + robocode.dotnet.installer + robocode.dotnet.content + robocode.dotnet.host + robocode.dotnet.nhost + robocode.dotnet.samples + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..90b2716 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:34:11 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/dotnet-setup.asm.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/dotnet-setup.asm.xml new file mode 100644 index 0000000..6dbb158 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/dotnet-setup.asm.xml @@ -0,0 +1,119 @@ + + + setup + + dir + jar + + false + + + + + net.sf.robocode:robocode.dotnet.api + + libs + false + robocode.${artifact.extension} + + + + + net.sf.robocode:robocode.dotnet.control.api + + libs + false + robocode.control.${artifact.extension} + + + + + net.sf.robocode:robocode.dotnet.* + net.sf.jni4net:* + + + + net.sf.robocode:robocode.dotnet.distribution + + net.sf.robocode:robocode.dotnet.installer + net.sf.robocode:robocode.dotnet.content + net.sf.robocode:robocode.dotnet.samples + + net.sf.robocode:robocode.dotnet.api + + net.sf.robocode:robocode.dotnet.control.api + + libs + false + + + + + net.sf.robocode:robocode.dotnet.installer + net.sf.robocode:robocode.dotnet.content + + true + + + **/META-INF/** + + + + + + + net.sf.robocode:robocode.dotnet.samples + + false + robots + samplescs-${project.version}.${artifact.extension} + + + + + + **/*.csproj + **/*.iws + **/*.user + **/*.bak + **/Thumbs.db + **/~* + **/.* + **/_svn/** + **/.svn/** + **/.git/** + **/.metadata/** + **/bin/** + **/target/** + **/lib/** + **/obj/** + + ../robocode.dotnet.samples/src + robots + + + + + ../robocode.dotnet.api/target/robocode.xml + libs + + + ../robocode.dotnet.api/target/Help/RobotAPI.chm + + + ../robocode.dotnet.control.api/target/robocode.control.xml + libs + + + ../robocode.dotnet.control.api/target/Help/ControlAPI.chm + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/pom.xml new file mode 100644 index 0000000..8b3150f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + robocode.dotnet.distribution + Robocode .NET Distribution + + net.sf.robocode + robocode.dotnet + ${robocode.dotnet.version} + + + + net.sf.robocode + robocode.dotnet.api + ${project.version} + dotnet:library + + + net.sf.robocode + robocode.dotnet.control.api + ${project.version} + dotnet:library + + + net.sf.robocode + robocode.dotnet.installer + ${project.version} + jar + + + net.sf.robocode + robocode.dotnet.content + ${project.version} + jar + + + net.sf.robocode + robocode.dotnet.samples + ${project.version} + dotnet:library + + + + + + org.sonatype.nmaven.plugins + maven-dotnet-compiler-plugin + + + maven-assembly-plugin + + ${project.parent.artifactId}-${robocode.version} + true + + dotnet-setup.asm.xml + + + + net.sf.robocode.installer.AutoExtract + + + + + + make-assembly + package + + single + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/robocode.dotnet.distribution.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/robocode.dotnet.distribution.iml new file mode 100644 index 0000000..7e826aa --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.distribution/robocode.dotnet.distribution.iml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.classpath b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.classpath new file mode 100644 index 0000000..c447aff --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.project new file mode 100644 index 0000000..158bb23 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.project @@ -0,0 +1,18 @@ + + + robocode.dotnet.host + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.dotnet.nhost + robocode.dotnet.api + robocode.dotnet.control.api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..15519c1 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:34:10 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/test/java=8859_1 +encoding/src/main/resources=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/pom.xml new file mode 100644 index 0000000..1e5b88d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/pom.xml @@ -0,0 +1,164 @@ + + + 4.0.0 + robocode.dotnet.host + Robocode .NET Host + ${robocode.version} + + net.sf.robocode + robocode.dotnet + ${robocode.dotnet.version} + + + + net.sf.robocode + robocode.host + ${robocode.version} + + + net.sf.robocode + robocode.repository + ${robocode.version} + + + net.sf.robocode + robocode.dotnet.nhost + ${robocode.dotnet.version} + dotnet:library + + + net.sf.jni4net + jni4net.j + 0.8.7.0 + + + net.sf.jni4net + jni4net.n + 0.8.7.0 + dotnet:library + + + net.sf.jni4net + jni4net.n.w32.v20 + 0.8.7.0 + dotnet:library + + + net.sf.jni4net + jni4net.n.w64.v20 + 0.8.7.0 + dotnet:library + + + net.sf.jni4net + jni4net.n.w32.v40 + 0.8.7.0 + dotnet:library + + + net.sf.jni4net + jni4net.n.w64.v40 + 0.8.7.0 + dotnet:library + + + junit + junit + 4.11 + test + + + + + + org.jvnet.maven-antrun-extended-plugin + maven-antrun-extended-plugin + + + process-classes + + + + + + + + + + + + + + + + + + + + + + run + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/robocode.dotnet.host.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/robocode.dotnet.host.iml new file mode 100644 index 0000000..3fdf0ce --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/robocode.dotnet.host.iml @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/java_/util/Random_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/java_/util/Random_.java new file mode 100644 index 0000000..56d7c37 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/java_/util/Random_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package java_.util; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class Random_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return java_.util.Random_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + java_.util.Random_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/core/ContainerBase_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/core/ContainerBase_.java new file mode 100644 index 0000000..752fc5b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/core/ContainerBase_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.core; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class ContainerBase_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.core.ContainerBase_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.core.ContainerBase_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/DotNetHost.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/DotNetHost.java new file mode 100644 index 0000000..5c26c80 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/host/DotNetHost.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.dotnet.host; + +@net.sf.jni4net.attributes.ClrType +public class DotNetHost extends system.Object implements net.sf.robocode.host.IHost { + + // + private static system.Type staticType; + + protected DotNetHost(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrConstructor("()V") + public DotNetHost() { + super(((net.sf.jni4net.inj.INJEnv)(null)), 0); + net.sf.robocode.dotnet.host.DotNetHost.__ctorDotNetHost0(this); + } + + @net.sf.jni4net.attributes.ClrMethod("()V") + private native static void __ctorDotNetHost0(net.sf.jni4net.inj.IClrProxy thiz); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/host/IHostManager;Lrobocode/control/RobotSpecification;Lnet/sf/robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostingRobotProxy;") + public native net.sf.robocode.host.proxies.IHostingRobotProxy createRobotProxy(net.sf.robocode.host.IHostManager par0, robocode.control.RobotSpecification par1, net.sf.robocode.peer.IRobotStatics par2, net.sf.robocode.peer.IRobotPeer par3); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;") + public native java.lang.String[] getReferencedClasses(net.sf.robocode.repository.IRobotItem par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;") + public native net.sf.robocode.repository.RobotType getRobotType(net.sf.robocode.repository.IRobotItem par0, boolean par1, boolean par2); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/host/IHostManager;Ljava/lang/Object;Lnet/sf/robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostingRobotProxy;") + public native net.sf.robocode.host.proxies.IHostingRobotProxy createRobotProxy(net.sf.robocode.host.IHostManager hostManager, java.lang.Object robotSpecification, net.sf.robocode.peer.IRobotStatics statics, net.sf.robocode.peer.IRobotPeer peer); + + public static system.Type typeof() { + return net.sf.robocode.dotnet.host.DotNetHost.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.dotnet.host.DotNetHost.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/nhost/ModuleN.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/nhost/ModuleN.java new file mode 100644 index 0000000..f5d9c0b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/nhost/ModuleN.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.dotnet.nhost; + +@net.sf.jni4net.attributes.ClrType +public class ModuleN extends system.Object { + + // + private static system.Type staticType; + + protected ModuleN(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrConstructor("()V") + public ModuleN() { + super(((net.sf.jni4net.inj.INJEnv)(null)), 0); + net.sf.robocode.dotnet.nhost.ModuleN.__ctorModuleN0(this); + } + + @net.sf.jni4net.attributes.ClrMethod("()V") + private native static void __ctorModuleN0(net.sf.jni4net.inj.IClrProxy thiz); + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native static void InitN(); + + public static system.Type typeof() { + return net.sf.robocode.dotnet.nhost.ModuleN.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.dotnet.nhost.ModuleN.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/items/DotNetRobotItem.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/items/DotNetRobotItem.java new file mode 100644 index 0000000..bf1c457 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/items/DotNetRobotItem.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.dotnet.repository.items; + + +import net.sf.robocode.repository.items.RobotItem; +import net.sf.robocode.repository.root.IRepositoryRoot; + +import java.net.URL; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class DotNetRobotItem extends RobotItem { + private static final long serialVersionUID = 1L; + + public DotNetRobotItem(IRepositoryRoot root, URL itemURL) { + super(itemURL, root); + + properties.setProperty(ROBOT_PLATFORM, "DotNet"); // instead of ".NET", as it is used for class names etc. + isPropertiesLoaded = true; + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/items/handlers/DotNetPropertiesHandler.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/items/handlers/DotNetPropertiesHandler.java new file mode 100644 index 0000000..e89c439 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/items/handlers/DotNetPropertiesHandler.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.dotnet.repository.items.handlers; + + +import net.sf.robocode.repository.items.handlers.PropertiesHandler; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.items.RobotItem; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.dotnet.repository.items.DotNetRobotItem; +import net.sf.robocode.dotnet.repository.root.DllRoot; + +import java.net.URL; +import java.io.File; + + +/** + * @author Pavel Savara (original) + */ +public class DotNetPropertiesHandler extends PropertiesHandler { + + /** + * {@inheritDoc} + */ + @Override + protected IRepositoryItem acceptItem(URL itemURL, IRepositoryRoot root, IRepository repository) { + // Accept and register the item if it is a .NET properties file + String name = itemURL.toString().toLowerCase(); + if (name.contains(".dll!/")) { + return register(itemURL, root, repository); + } + return null; + } + + private IRepositoryItem register(URL itemURL, IRepositoryRoot root, IRepository repository) { + RobotItem item = (RobotItem) repository.getItem(itemURL.toString()); + if (item == null) { + item = createItem(itemURL, root, repository); + } + repository.addOrUpdateItem(item); + return item; + } + + protected RobotItem createItem(URL itemURL, IRepositoryRoot root, IRepository repository) { + File file = new File(itemURL.toString().replace(".properties", ".dll")); + DotNetRobotItem item = new DotNetRobotItem(new DllRoot(repository, file), itemURL); + + item.setClassURL(itemURL); + return item; + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/DllRoot.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/DllRoot.java new file mode 100644 index 0000000..527f029 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/DllRoot.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.dotnet.repository.root; + + +import net.sf.robocode.repository.root.BaseRoot; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.items.RobotItem; +import net.sf.robocode.repository.items.handlers.ItemHandler; +import net.sf.robocode.io.Logger; + +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.MalformedURLException; +import java.io.File; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.List; +import java.lang.String; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public final class DllRoot extends BaseRoot implements IRepositoryRoot { + private static final long serialVersionUID = 1L; + + private final String dllPath; + private final URL dllUrl; + + private long lastModified; + + public DllRoot(IRepository repository, File rootPath) { + super(repository, rootPath); + String dllPath = null; + URL dllUrl = null; + try { + dllPath = rootPath.toURI().toString(); + dllUrl = new URL(dllPath + "!/"); + dllPath = URLDecoder.decode(dllPath, "UTF8"); + } catch (MalformedURLException e) { + Logger.logError(e); + } catch (UnsupportedEncodingException e) { + Logger.logError(e); + } + this.dllPath = dllPath; + this.dllUrl = dllUrl; + } + + /** + * {@inheritDoc} + */ + public void updateItems(boolean force) { + setStatus("Updating DLL: " + rootPath.toString()); + + long lastModified = rootPath.lastModified(); + + if (lastModified > this.lastModified) { + repository.removeItemsFromRoot(this); + this.lastModified = lastModified; + + List repositoryItems = new ArrayList(); + + visitItems(repositoryItems); + for (IRepositoryItem repositoryItem : repositoryItems) { + repositoryItem.update(lastModified, force); + } + } + } + + private void visitItems(List items) { + String[] dllItems = DllRootHelper.findItems(dllPath); + + for (String url : dllItems) { + createItem(items, dllUrl, url); + } + } + + private void createItem(List items, URL root, String url) { + try { + IRepositoryItem item = ItemHandler.registerItem(new URL(url), DllRoot.this, repository); + if (item != null) { + if (item instanceof RobotItem) { + ((RobotItem) item).setClassPathURL(root); + } + items.add(item); + } + } catch (MalformedURLException e) { + Logger.logError(e); + } + } + + public void updateItem(IRepositoryItem item, boolean force) { + item.update(rootPath.lastModified(), force); + } + + public boolean isChanged(IRepositoryItem item) { + return rootPath.lastModified() > lastModified; + } + + public URL getRootUrl() { + return dllUrl; + } + + public boolean isDevelopmentRoot() { + return false; + } + + public boolean isJAR() { + return true; + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/DllRootHelper.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/DllRootHelper.java new file mode 100644 index 0000000..4e485d6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/DllRootHelper.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.dotnet.repository.root; + +@net.sf.jni4net.attributes.ClrType +public class DllRootHelper extends system.Object { + + // + private static system.Type staticType; + + protected DllRootHelper(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + protected DllRootHelper() { + super(((net.sf.jni4net.inj.INJEnv)(null)), 0); + } + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native static void Open(); + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native static void Close(); + + @net.sf.jni4net.attributes.ClrMethod("(LSystem/String;)[LSystem/String;") + public native static java.lang.String[] findItems(java.lang.String dllPath); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/repository/IRobotItem;)Lnet/sf/robocode/repository/RobotType;") + public native static net.sf.robocode.repository.RobotType GetRobotType(net.sf.robocode.repository.IRobotItem robotItem); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/repository/IRobotItem;)LSystem/String;") + public native static java.lang.String GetDllFileName(net.sf.robocode.repository.IRobotItem robotItem); + + public static system.Type typeof() { + return net.sf.robocode.dotnet.repository.root.DllRootHelper.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.dotnet.repository.root.DllRootHelper.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/handlers/DllHandler.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/handlers/DllHandler.java new file mode 100644 index 0000000..9e8502d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/dotnet/repository/root/handlers/DllHandler.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.dotnet.repository.root.handlers; + + +import net.sf.robocode.dotnet.repository.root.DllRootHelper; +import net.sf.robocode.dotnet.repository.root.DllRoot; +import net.sf.robocode.repository.root.handlers.RootHandler; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.repository.IRepository; + +import java.io.File; +import java.io.FileFilter; +import java.util.Map; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class DllHandler extends RootHandler { + + public void open() { + DllRootHelper.Open(); + } + + public void close() { + DllRootHelper.Close(); + } + + public void visitDirectory(File dir, boolean isDevel, Map newRoots, IRepository repository, boolean force) { + // find dll files + final File[] dlls = dir.listFiles(new FileFilter() { + public boolean accept(File pathname) { + String path = pathname.toString().toLowerCase(); + return pathname.isFile() && path.endsWith(".dll") && !path.equalsIgnoreCase("robocode.dll") + && !path.contains("jni4net"); + } + }); + + if (dlls != null) { + // update DLL files + for (File dll : dlls) { + String key = dll.toURI().toString(); + IRepositoryRoot root = repository.getRoots().get(key); + if (root == null) { + root = new DllRoot(repository, dll); + } else { + repository.removeRoot(key); + } + + root.updateItems(force); + newRoots.put(dll.toURI().toString(), root); + } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/IHostManager_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/IHostManager_.java new file mode 100644 index 0000000..53456b8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/IHostManager_.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.host; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IHostManager_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.host.IHostManager_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.host.IHostManager_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IHostManager extends system.Object implements net.sf.robocode.host.IHostManager { + + protected __IHostManager(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void cleanup(); + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/lang/Object;Ljava/lang/Object;Lnet/sf/robocode/peer/IRobotPeer;)Ljava/lang/Object;") + public native java.lang.Object createRobotProxy(robocode.control.RobotSpecification par0, net.sf.robocode.host.RobotStatics par1, net.sf.robocode.peer.IRobotPeer par2); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;") + public native java.lang.String[] getReferencedClasses(net.sf.robocode.repository.IRobotItem par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;") + public native net.sf.robocode.repository.RobotType getRobotType(net.sf.robocode.repository.IRobotItem par0, boolean par1, boolean par2); + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void initSecurity(); + + @net.sf.jni4net.attributes.ClrMethod("()J") + public native long getRobotFilesystemQuota(); + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void resetThreadManager(); + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/lang/Object;)V") + public native void addSafeThread(java.lang.Thread par0); + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/lang/Object;)V") + public native void removeSafeThread(java.lang.Thread par0); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/io/PrintStream;") + public native java.io.PrintStream getRobotOutputStream(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/IHost_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/IHost_.java new file mode 100644 index 0000000..b1752e3 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/IHost_.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.host; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IHost_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.host.IHost_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.host.IHost_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IHost extends system.Object implements net.sf.robocode.host.IHost { + + protected __IHost(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/host/IHostManager;Ljava/lang/Object;Lnet/sf/robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostingRobotProxy;") + public native net.sf.robocode.host.proxies.IHostingRobotProxy createRobotProxy(net.sf.robocode.host.IHostManager par0, robocode.control.RobotSpecification par1, net.sf.robocode.peer.IRobotStatics par2, net.sf.robocode.peer.IRobotPeer par3); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;") + public native java.lang.String[] getReferencedClasses(net.sf.robocode.repository.IRobotItem par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;") + public native net.sf.robocode.repository.RobotType getRobotType(net.sf.robocode.repository.IRobotItem par0, boolean par1, boolean par2); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/RobotStatics_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/RobotStatics_.java new file mode 100644 index 0000000..f0e0348 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/RobotStatics_.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.host; + + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RobotStatics_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.host.RobotStatics_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.host.RobotStatics_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/proxies/IHostingRobotProxy_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/proxies/IHostingRobotProxy_.java new file mode 100644 index 0000000..5bf220e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/host/proxies/IHostingRobotProxy_.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.host.proxies; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IHostingRobotProxy_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.host.proxies.IHostingRobotProxy_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.host.proxies.IHostingRobotProxy_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IHostingRobotProxy extends system.Object implements net.sf.robocode.host.proxies.IHostingRobotProxy { + + protected __IHostingRobotProxy(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void cleanup(); + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/lang/Object;Ljava/lang/Object;)V") + public native void startRound(net.sf.robocode.peer.ExecCommands par0, robocode.RobotStatus par1); + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void forceStopThread(); + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void waitForStopThread(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/io/Logger_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/io/Logger_.java new file mode 100644 index 0000000..c010fde --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/io/Logger_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.io; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class Logger_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.io.Logger_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.io.Logger_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/manager/IVersionManagerBase_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/manager/IVersionManagerBase_.java new file mode 100644 index 0000000..cded2c3 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/manager/IVersionManagerBase_.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.manager; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IVersionManagerBase_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.manager.IVersionManagerBase_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.manager.IVersionManagerBase_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IVersionManagerBase extends system.Object implements net.sf.robocode.manager.IVersionManagerBase { + + protected __IVersionManagerBase(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getVersionAsInt(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getVersionN(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isLastRunVersionChanged(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/BadBehavior_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/BadBehavior_.java new file mode 100644 index 0000000..e44a81b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/BadBehavior_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.peer; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BadBehavior_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.peer.BadBehavior_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.peer.BadBehavior_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/IRobotPeer_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/IRobotPeer_.java new file mode 100644 index 0000000..58f7867 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/IRobotPeer_.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.peer; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IRobotPeer_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.peer.IRobotPeer_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.peer.IRobotPeer_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IRobotPeer extends system.Object implements net.sf.robocode.peer.IRobotPeer { + + protected __IRobotPeer(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void drainEnergy(); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/peer/BadBehavior;)V") + public native void punishBadBehavior(net.sf.robocode.peer.BadBehavior par0); + + @net.sf.jni4net.attributes.ClrMethod("(Z)V") + public native void setRunning(boolean par0); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isRunning(); + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/lang/Object;)Ljava/lang/Object;") + public native net.sf.robocode.peer.ExecResults waitForBattleEndImpl(net.sf.robocode.peer.ExecCommands par0); + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/lang/Object;)Ljava/lang/Object;") + public native net.sf.robocode.peer.ExecResults executeImpl(net.sf.robocode.peer.ExecCommands par0); + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/nio/ByteBuffer;)V") + public native void setupBuffer(java.nio.ByteBuffer par0); + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void executeImplSerial(); + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void waitForBattleEndImplSerial(); + + @net.sf.jni4net.attributes.ClrMethod("()V") + public native void setupThread(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/IRobotStatics_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/IRobotStatics_.java new file mode 100644 index 0000000..3fbbe89 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/peer/IRobotStatics_.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.peer; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IRobotStatics_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.peer.IRobotStatics_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.peer.IRobotStatics_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IRobotStatics extends system.Object implements net.sf.robocode.peer.IRobotStatics { + + protected __IRobotStatics(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isAdvancedRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isTeamRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isInteractiveRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isPaintRobot(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/IRobotItem_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/IRobotItem_.java new file mode 100644 index 0000000..217ce55 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/IRobotItem_.java @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.repository; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IRobotItem_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.repository.IRobotItem_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.repository.IRobotItem_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IRobotItem extends system.Object implements net.sf.robocode.repository.IRobotItem { + + protected __IRobotItem(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/lang/Object;)I") + public native int compareTo(java.lang.Object par0); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isValid(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isTeam(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isInJAR(); + + @net.sf.jni4net.attributes.ClrMethod("(Z)V") + public native void setValid(boolean par0); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getDescription(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getAuthorName(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/net/URL;") + public native java.net.URL getWebpage(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean getIncludeSource(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean getIncludeData(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isSourceIncluded(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getRootPath(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/net/URL;") + public native java.net.URL getItemURL(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isDevelopmentVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getRobocodeVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getFullPackage(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getRelativePath(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getRootPackage(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getFullClassNameWithVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getUniqueFullClassName(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getUniqueFullClassNameWithVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getUniqueShortClassNameWithVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getUniqueVeryShortClassNameWithVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getFullClassName(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getShortClassName(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/Object;") + public native robocode.control.RobotSpecification createRobotSpecification(); + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/io/OutputStream;Ljava/lang/Object;)V") + public native void storeProperties(java.io.OutputStream par0, net.sf.robocode.repository.RobotProperties par1); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getPlatform(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isJuniorRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isStandardRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isAdvancedRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isTeamRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isDroid(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isSentryRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isInteractiveRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isPaintRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/net/URL;") + public native java.net.URL getClassPathURL(); + + @net.sf.jni4net.attributes.ClrMethod("()[Ljava/net/URL;") + public native java.net.URL[] getSourcePathURLs(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getWritableDirectory(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getReadableDirectory(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/IRobotSpecItem_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/IRobotSpecItem_.java new file mode 100644 index 0000000..1dabc34 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/IRobotSpecItem_.java @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.repository; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IRobotSpecItem_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.repository.IRobotSpecItem_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.repository.IRobotSpecItem_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IRobotSpecItem extends system.Object implements net.sf.robocode.repository.IRobotSpecItem { + + protected __IRobotSpecItem(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/lang/Object;)I") + public native int compareTo(java.lang.Object par0); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isValid(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isTeam(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isInJAR(); + + @net.sf.jni4net.attributes.ClrMethod("(Z)V") + public native void setValid(boolean par0); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getDescription(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getAuthorName(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/net/URL;") + public native java.net.URL getWebpage(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean getIncludeSource(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean getIncludeData(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isSourceIncluded(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getRootPath(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/net/URL;") + public native java.net.URL getItemURL(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isDevelopmentVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getRobocodeVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getFullPackage(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getRelativePath(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getRootPackage(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getFullClassNameWithVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getUniqueFullClassName(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getUniqueFullClassNameWithVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getUniqueShortClassNameWithVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getUniqueVeryShortClassNameWithVersion(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getFullClassName(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getShortClassName(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/Object;") + public native robocode.control.RobotSpecification createRobotSpecification(); + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/io/OutputStream;Ljava/lang/Object;)V") + public native void storeProperties(java.io.OutputStream par0, net.sf.robocode.repository.RobotProperties par1); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/RobotType_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/RobotType_.java new file mode 100644 index 0000000..3c0292d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/repository/RobotType_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.repository; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RobotType_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.repository.RobotType_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.repository.RobotType_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/security/HiddenAccess_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/security/HiddenAccess_.java new file mode 100644 index 0000000..24bf34b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/security/HiddenAccess_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.security; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class HiddenAccess_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.security.HiddenAccess_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.security.HiddenAccess_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/serialization/ISerializableHelper_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/serialization/ISerializableHelper_.java new file mode 100644 index 0000000..3dbeb3d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/serialization/ISerializableHelper_.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.serialization; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class ISerializableHelper_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.serialization.ISerializableHelper_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.serialization.ISerializableHelper_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __ISerializableHelper extends system.Object implements net.sf.robocode.serialization.ISerializableHelper { + + protected __ISerializableHelper(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;Ljava/lang/Object;)V") + public native void serialize(net.sf.robocode.serialization.RbSerializer par0, java.nio.ByteBuffer par1, java.lang.Object par2); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;)Ljava/lang/Object;") + public native java.lang.Object deserialize(net.sf.robocode.serialization.RbSerializer par0, java.nio.ByteBuffer par1); + + @net.sf.jni4net.attributes.ClrMethod("(Lnet/sf/robocode/serialization/RbSerializer;Ljava/lang/Object;)I") + public native int sizeOf(net.sf.robocode.serialization.RbSerializer par0, java.lang.Object par1); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/serialization/RbSerializer_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/serialization/RbSerializer_.java new file mode 100644 index 0000000..3244d98 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/net/sf/robocode/serialization/RbSerializer_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package net.sf.robocode.serialization; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RbSerializer_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return net.sf.robocode.serialization.RbSerializer_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + net.sf.robocode.serialization.RbSerializer_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/BattleRules_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/BattleRules_.java new file mode 100644 index 0000000..8825c15 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/BattleRules_.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode; + + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattleRules_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.BattleRules_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.BattleRules_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/BattleSpecification_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/BattleSpecification_.java new file mode 100644 index 0000000..1ef3b27 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/BattleSpecification_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattleSpecification_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.BattleSpecification_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.BattleSpecification_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/BattlefieldSpecification_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/BattlefieldSpecification_.java new file mode 100644 index 0000000..5bb04f6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/BattlefieldSpecification_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattlefieldSpecification_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.BattlefieldSpecification_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.BattlefieldSpecification_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RandomFactory_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RandomFactory_.java new file mode 100644 index 0000000..11488c8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RandomFactory_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RandomFactory_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.RandomFactory_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.RandomFactory_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobocodeEngine_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobocodeEngine_.java new file mode 100644 index 0000000..474d910 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobocodeEngine_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RobocodeEngine_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.RobocodeEngine_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.RobocodeEngine_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotResults_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotResults_.java new file mode 100644 index 0000000..8662aed --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotResults_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RobotResults_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.RobotResults_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.RobotResults_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotSetup_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotSetup_.java new file mode 100644 index 0000000..b96a88d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotSetup_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RobotSetup_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.RobotSetup_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.RobotSetup_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotSpecification_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotSpecification_.java new file mode 100644 index 0000000..af1254f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/RobotSpecification_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RobotSpecification_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.RobotSpecification_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.RobotSpecification_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleCompletedEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleCompletedEvent_.java new file mode 100644 index 0000000..c8e28be --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleCompletedEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattleCompletedEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.BattleCompletedEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.BattleCompletedEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleErrorEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleErrorEvent_.java new file mode 100644 index 0000000..64b99ea --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleErrorEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattleErrorEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.BattleErrorEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.BattleErrorEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleEvent_.java new file mode 100644 index 0000000..cc80540 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattleEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.BattleEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.BattleEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleFinishedEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleFinishedEvent_.java new file mode 100644 index 0000000..6c664aa --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleFinishedEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattleFinishedEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.BattleFinishedEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.BattleFinishedEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleMessageEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleMessageEvent_.java new file mode 100644 index 0000000..219e593 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleMessageEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattleMessageEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.BattleMessageEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.BattleMessageEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattlePausedEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattlePausedEvent_.java new file mode 100644 index 0000000..ec6f7f6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattlePausedEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattlePausedEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.BattlePausedEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.BattlePausedEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleResumedEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleResumedEvent_.java new file mode 100644 index 0000000..7be0da3 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleResumedEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattleResumedEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.BattleResumedEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.BattleResumedEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleStartedEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleStartedEvent_.java new file mode 100644 index 0000000..ded5769 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/BattleStartedEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BattleStartedEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.BattleStartedEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.BattleStartedEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/IBattleListener_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/IBattleListener_.java new file mode 100644 index 0000000..3be3fb9 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/IBattleListener_.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IBattleListener_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.IBattleListener_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.IBattleListener_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IBattleListener extends system.Object implements robocode.control.events.IBattleListener { + + protected __IBattleListener(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/BattleStartedEvent;)V") + public native void onBattleStarted(robocode.control.events.BattleStartedEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/BattleFinishedEvent;)V") + public native void onBattleFinished(robocode.control.events.BattleFinishedEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/BattleCompletedEvent;)V") + public native void onBattleCompleted(robocode.control.events.BattleCompletedEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/BattlePausedEvent;)V") + public native void onBattlePaused(robocode.control.events.BattlePausedEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/BattleResumedEvent;)V") + public native void onBattleResumed(robocode.control.events.BattleResumedEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/RoundStartedEvent;)V") + public native void onRoundStarted(robocode.control.events.RoundStartedEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/RoundEndedEvent;)V") + public native void onRoundEnded(robocode.control.events.RoundEndedEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/TurnStartedEvent;)V") + public native void onTurnStarted(robocode.control.events.TurnStartedEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/TurnEndedEvent;)V") + public native void onTurnEnded(robocode.control.events.TurnEndedEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/BattleMessageEvent;)V") + public native void onBattleMessage(robocode.control.events.BattleMessageEvent par0); + + @net.sf.jni4net.attributes.ClrMethod("(Lrobocode/control/events/BattleErrorEvent;)V") + public native void onBattleError(robocode.control.events.BattleErrorEvent par0); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/RoundEndedEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/RoundEndedEvent_.java new file mode 100644 index 0000000..093cd60 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/RoundEndedEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RoundEndedEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.RoundEndedEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.RoundEndedEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/RoundStartedEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/RoundStartedEvent_.java new file mode 100644 index 0000000..43df805 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/RoundStartedEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RoundStartedEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.RoundStartedEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.RoundStartedEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/TurnEndedEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/TurnEndedEvent_.java new file mode 100644 index 0000000..efbc4cb --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/TurnEndedEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class TurnEndedEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.TurnEndedEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.TurnEndedEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/TurnStartedEvent_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/TurnStartedEvent_.java new file mode 100644 index 0000000..0fb4c2b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/events/TurnStartedEvent_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.events; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class TurnStartedEvent_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.events.TurnStartedEvent_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.events.TurnStartedEvent_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/BulletState_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/BulletState_.java new file mode 100644 index 0000000..c27d210 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/BulletState_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.snapshot; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class BulletState_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.snapshot.BulletState_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.snapshot.BulletState_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IBulletSnapshot_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IBulletSnapshot_.java new file mode 100644 index 0000000..390c165 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IBulletSnapshot_.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.snapshot; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IBulletSnapshot_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.snapshot.IBulletSnapshot_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.snapshot.IBulletSnapshot_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IBulletSnapshot extends system.Object implements robocode.control.snapshot.IBulletSnapshot { + + protected __IBulletSnapshot(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("()Lrobocode/control/snapshot/BulletState;") + public native robocode.control.snapshot.BulletState getState(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getX(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getY(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getHeading(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getPower(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getPaintX(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getPaintY(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getColor(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getFrame(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isExplosion(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getExplosionImageIndex(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getBulletId(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getVictimIndex(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getOwnerIndex(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IDebugProperty_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IDebugProperty_.java new file mode 100644 index 0000000..66f78f4 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IDebugProperty_.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.snapshot; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IDebugProperty_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.snapshot.IDebugProperty_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.snapshot.IDebugProperty_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IDebugProperty extends system.Object implements robocode.control.snapshot.IDebugProperty { + + protected __IDebugProperty(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getValue(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getKey(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IRobotSnapshot_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IRobotSnapshot_.java new file mode 100644 index 0000000..8d11a00 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IRobotSnapshot_.java @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.snapshot; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IRobotSnapshot_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.snapshot.IRobotSnapshot_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.snapshot.IRobotSnapshot_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IRobotSnapshot extends system.Object implements robocode.control.snapshot.IRobotSnapshot { + + protected __IRobotSnapshot(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getName(); + + @net.sf.jni4net.attributes.ClrMethod("()Lrobocode/control/snapshot/RobotState;") + public native robocode.control.snapshot.RobotState getState(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getTeamName(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getX(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getY(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getShortName(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getVeryShortName(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getRobotIndex(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getTeamIndex(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getContestantIndex(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getEnergy(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getVelocity(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getBodyHeading(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getGunHeading(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getRadarHeading(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getGunHeat(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getBodyColor(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getGunColor(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getRadarColor(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getScanColor(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isDroid(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isSentryRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isPaintRobot(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isPaintEnabled(); + + @net.sf.jni4net.attributes.ClrMethod("()Z") + public native boolean isSGPaintEnabled(); + + @net.sf.jni4net.attributes.ClrMethod("()[Lrobocode/control/snapshot/IDebugProperty;") + public native robocode.control.snapshot.IDebugProperty[] getDebugProperties(); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getOutputStreamSnapshot(); + + @net.sf.jni4net.attributes.ClrMethod("()Lrobocode/control/snapshot/IScoreSnapshot;") + public native robocode.control.snapshot.IScoreSnapshot getScoreSnapshot(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IScoreSnapshot_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IScoreSnapshot_.java new file mode 100644 index 0000000..bac14e4 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/IScoreSnapshot_.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.snapshot; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class IScoreSnapshot_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.snapshot.IScoreSnapshot_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.snapshot.IScoreSnapshot_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __IScoreSnapshot extends system.Object implements robocode.control.snapshot.IScoreSnapshot { + + protected __IScoreSnapshot(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("(Ljava/lang/Object;)I") + public native int compareTo(java.lang.Object par0); + + @net.sf.jni4net.attributes.ClrMethod("()Ljava/lang/String;") + public native java.lang.String getName(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getTotalScore(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getTotalSurvivalScore(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getTotalLastSurvivorBonus(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getTotalBulletDamageScore(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getTotalBulletKillBonus(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getTotalRammingDamageScore(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getTotalRammingKillBonus(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getTotalFirsts(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getTotalSeconds(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getTotalThirds(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getCurrentScore(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getCurrentSurvivalScore(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getCurrentSurvivalBonus(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getCurrentBulletDamageScore(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getCurrentBulletKillBonus(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getCurrentRammingDamageScore(); + + @net.sf.jni4net.attributes.ClrMethod("()D") + public native double getCurrentRammingKillBonus(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/ITurnSnapshot_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/ITurnSnapshot_.java new file mode 100644 index 0000000..7513dd2 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/ITurnSnapshot_.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.snapshot; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class ITurnSnapshot_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.snapshot.ITurnSnapshot_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.snapshot.ITurnSnapshot_.staticType = staticType; + } + // +} + +// +@net.sf.jni4net.attributes.ClrProxy +class __ITurnSnapshot extends system.Object implements robocode.control.snapshot.ITurnSnapshot { + + protected __ITurnSnapshot(net.sf.jni4net.inj.INJEnv __env, long __handle) { + super(__env, __handle); + } + + @net.sf.jni4net.attributes.ClrMethod("()[Lrobocode/control/snapshot/IRobotSnapshot;") + public native robocode.control.snapshot.IRobotSnapshot[] getRobots(); + + @net.sf.jni4net.attributes.ClrMethod("()[Lrobocode/control/snapshot/IBulletSnapshot;") + public native robocode.control.snapshot.IBulletSnapshot[] getBullets(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getTPS(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getRound(); + + @net.sf.jni4net.attributes.ClrMethod("()I") + public native int getTurn(); + + @net.sf.jni4net.attributes.ClrMethod("()[Lrobocode/control/snapshot/IScoreSnapshot;") + public native robocode.control.snapshot.IScoreSnapshot[] getSortedTeamScores(); + + @net.sf.jni4net.attributes.ClrMethod("()[Lrobocode/control/snapshot/IScoreSnapshot;") + public native robocode.control.snapshot.IScoreSnapshot[] getIndexedTeamScores(); +} +// diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/RobotState_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/RobotState_.java new file mode 100644 index 0000000..91f7cdc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/control/snapshot/RobotState_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.control.snapshot; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class RobotState_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.control.snapshot.RobotState_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.control.snapshot.RobotState_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/AbortedException_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/AbortedException_.java new file mode 100644 index 0000000..b36c4c8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/AbortedException_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.exception; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class AbortedException_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.exception.AbortedException_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.exception.AbortedException_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/DeathException_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/DeathException_.java new file mode 100644 index 0000000..dfef221 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/DeathException_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.exception; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class DeathException_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.exception.DeathException_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.exception.DeathException_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/DisabledException_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/DisabledException_.java new file mode 100644 index 0000000..9c69e46 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/DisabledException_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.exception; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class DisabledException_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.exception.DisabledException_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.exception.DisabledException_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/WinException_.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/WinException_.java new file mode 100644 index 0000000..75df821 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/main/java/robocode/exception/WinException_.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// ------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +// ------------------------------------------------------------------------------ + +package robocode.exception; + +@net.sf.jni4net.attributes.ClrTypeInfo +public final class WinException_ { + + // + private static system.Type staticType; + + public static system.Type typeof() { + return robocode.exception.WinException_.staticType; + } + + private static void InitJNI(net.sf.jni4net.inj.INJEnv env, system.Type staticType) { + robocode.exception.WinException_.staticType = staticType; + } + // +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/test/java/net/sf/robocode/dotnet/host/TestCLR.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/test/java/net/sf/robocode/dotnet/host/TestCLR.java new file mode 100644 index 0000000..858fd26 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.host/src/test/java/net/sf/robocode/dotnet/host/TestCLR.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.dotnet.host; + + +import org.junit.Test; + + +/** + * @author Pavel Savara (original) + */ +public class TestCLR { + + @Test + public void test1() {} + + @Test + public void test2() {} +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.iml new file mode 100644 index 0000000..c163c5f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.iml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.classpath b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.classpath new file mode 100644 index 0000000..5114d59 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.classpath @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.project new file mode 100644 index 0000000..26afbc5 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.project @@ -0,0 +1,14 @@ + + + robocode.dotnet.installer + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..764c3ab --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:34:11 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/test/java=8859_1 +encoding/src/main/resources=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/pom.xml new file mode 100644 index 0000000..66dc7b8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + robocode.dotnet.installer + Robocode .NET Installer + + robocode.dotnet + net.sf.robocode + ${robocode.dotnet.version} + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + net.sf.robocode.installer.AutoExtract + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/robocode.dotnet.installer.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/robocode.dotnet.installer.iml new file mode 100644 index 0000000..93c108a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.installer/robocode.dotnet.installer.iml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ipr b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ipr new file mode 100644 index 0000000..d223cbc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ipr @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.iws b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.iws new file mode 100644 index 0000000..03c854e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.iws @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/.project new file mode 100644 index 0000000..8426045 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/.project @@ -0,0 +1,11 @@ + + + robocode.dotnet.nhost + .NET nhost for Robocode. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.dotnet.api + robocode.dotnet.control.api + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..070758f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +#Tue Nov 27 22:34:10 CET 2012 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 +encoding/src/main/resources=8859_1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/test/resources=8859_1 +encoding/src=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/pom.xml new file mode 100644 index 0000000..5b166f5 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/pom.xml @@ -0,0 +1,93 @@ + + + 4.0.0 + robocode.dotnet.nhost + Robocode .NET nHost + .NET nhost for Robocode + dotnet:library + + robocode.dotnet + net.sf.robocode + ${robocode.dotnet.version} + + + + net.sf.jni4net + jni4net.n + 0.8.7.0 + dotnet:library + + + net.sf.robocode + robocode.dotnet.api + ${project.version} + dotnet:library + + + net.sf.robocode + robocode.dotnet.control.api + ${project.version} + dotnet:library + + + + src + + + org.sonatype.nmaven.plugins + maven-dotnet-compiler-plugin + + /unsafe /warn:0 /nowarn:1591 /keyfile:"${basedir}/../tools/keys/robocode.snk" + + + + org.jvnet.maven-antrun-extended-plugin + maven-antrun-extended-plugin + + + process-classes + + + + + + + + + + + + + + run + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/robocode.dotnet.nhost.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/robocode.dotnet.nhost.iml new file mode 100644 index 0000000..f4981fc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/robocode.dotnet.nhost.iml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/.gitignore b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/.gitignore new file mode 100644 index 0000000..7c7991e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/.gitignore @@ -0,0 +1,3 @@ +/robocode.dotnet.nhost.sln +/robocode.dotnet.nhost.suo +/obj diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/core/ContainerBase.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/core/ContainerBase.generated.cs new file mode 100644 index 0000000..321b090 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/core/ContainerBase.generated.cs @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.core { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class ContainerBase : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getComponent0; + + internal static global::net.sf.jni4net.jni.FieldId j4n_instance1; + + protected ContainerBase(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.core.ContainerBase.staticClass; + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lnet/sf/robocode/core/ContainerBase;")] + public static global::net.sf.robocode.core.ContainerBase instance { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::net.sf.robocode.core.ContainerBase.staticClass, global::net.sf.robocode.core.ContainerBase.j4n_instance1)); + } + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.core.ContainerBase.staticClass = @__class; + global::net.sf.robocode.core.ContainerBase.j4n_getComponent0 = @__env.GetStaticMethodID(global::net.sf.robocode.core.ContainerBase.staticClass, "getComponent", "(Ljava/lang/Class;)Ljava/lang/Object;"); + global::net.sf.robocode.core.ContainerBase.j4n_instance1 = @__env.GetStaticFieldID(global::net.sf.robocode.core.ContainerBase.staticClass, "instance", "Lnet/sf/robocode/core/ContainerBase;"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/Class;)Ljava/lang/Object;")] + public static global::java.lang.Object getComponent(global::java.lang.Class par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.core.ContainerBase.staticClass, global::net.sf.robocode.core.ContainerBase.j4n_getComponent0, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.core.ContainerBase(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/host/DotNetHost.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/host/DotNetHost.generated.cs new file mode 100644 index 0000000..b981589 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/host/DotNetHost.generated.cs @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.dotnet.host { + + + #region Component Designer generated code + public partial class DotNetHost_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.dotnet.host.@__DotNetHost.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.dotnet.host.DotNetHost), typeof(global::net.sf.robocode.dotnet.host.DotNetHost_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.dotnet.host.DotNetHost), typeof(global::net.sf.robocode.dotnet.host.DotNetHost_))] + internal sealed partial class @__DotNetHost : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + private @__DotNetHost(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.dotnet.host.@__DotNetHost.staticClass = @__class; + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__DotNetHost); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "createRobotProxy", "createRobotProxy0", "(Lnet/sf/robocode/host/IHostManager;Lrobocode/control/RobotSpecification;Lnet/sf/" + + "robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/h" + + "ost/proxies/IHostingRobotProxy;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getReferencedClasses", "getReferencedClasses1", "(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRobotType", "getRobotType2", "(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;" + + "")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "createRobotProxy", "createRobotProxy3", "(Lnet/sf/robocode/host/IHostManager;Ljava/lang/Object;Lnet/sf/robocode/peer/IRobo" + + "tStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostin" + + "gRobotProxy;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "__ctorDotNetHost0", "__ctorDotNetHost0", "(Lnet/sf/jni4net/inj/IClrProxy;)V")); + return methods; + } + + private static global::net.sf.jni4net.utils.JniHandle createRobotProxy0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, global::net.sf.jni4net.utils.JniLocalHandle par1, global::net.sf.jni4net.utils.JniLocalHandle par2, global::net.sf.jni4net.utils.JniLocalHandle par3) { + // (Lnet/sf/robocode/host/IHostManager;Lrobocode/control/RobotSpecification;Lnet/sf/robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostingRobotProxy; + // (Lnet/sf/robocode/host/IHostManager;Lrobocode/control/RobotSpecification;Lnet/sf/robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostingRobotProxy; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.dotnet.host.DotNetHost @__real = global::net.sf.jni4net.utils.Convertor.StrongJp2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.FullC2J(@__env, ((global::net.sf.robocode.host.IHost)(@__real)).createRobotProxy(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0), global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par1), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par2), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par3))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getReferencedClasses1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String; + // (Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.dotnet.host.DotNetHost @__real = global::net.sf.jni4net.utils.Convertor.StrongJp2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.ArrayStrongCp2J(@__env, ((global::net.sf.robocode.host.IHost)(@__real)).getReferencedClasses(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRobotType2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, bool par1, bool par2) { + // (Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType; + // (Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.dotnet.host.DotNetHost @__real = global::net.sf.jni4net.utils.Convertor.StrongJp2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.host.IHost)(@__real)).getRobotType(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0), par1, par2)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle createRobotProxy3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle hostManager, global::net.sf.jni4net.utils.JniLocalHandle robotSpecification, global::net.sf.jni4net.utils.JniLocalHandle statics, global::net.sf.jni4net.utils.JniLocalHandle peer) { + // (Lnet/sf/robocode/host/IHostManager;Ljava/lang/Object;Lnet/sf/robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostingRobotProxy; + // (Lnet/sf/robocode/host/IHostManager;Ljava/lang/Object;Lnet/sf/robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostingRobotProxy; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.dotnet.host.DotNetHost @__real = global::net.sf.jni4net.utils.Convertor.StrongJp2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.FullC2J(@__env, @__real.createRobotProxy(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, hostManager), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, robotSpecification), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, statics), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, peer))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static void @__ctorDotNetHost0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.dotnet.host.DotNetHost @__real = new global::net.sf.robocode.dotnet.host.DotNetHost(); + global::net.sf.jni4net.utils.Convertor.InitProxy(@__env, @__obj, @__real); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.dotnet.host.@__DotNetHost(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/nhost/ModuleN.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/nhost/ModuleN.generated.cs new file mode 100644 index 0000000..27b66cc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/nhost/ModuleN.generated.cs @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.dotnet.nhost { + + + #region Component Designer generated code + public partial class ModuleN_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.dotnet.nhost.@__ModuleN.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.dotnet.nhost.ModuleN), typeof(global::net.sf.robocode.dotnet.nhost.ModuleN_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.dotnet.nhost.ModuleN), typeof(global::net.sf.robocode.dotnet.nhost.ModuleN_))] + internal sealed partial class @__ModuleN : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + private @__ModuleN(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.dotnet.nhost.@__ModuleN.staticClass = @__class; + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__ModuleN); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "InitN", "InitN0", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "__ctorModuleN0", "__ctorModuleN0", "(Lnet/sf/jni4net/inj/IClrProxy;)V")); + return methods; + } + + private static void InitN0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.dotnet.nhost.ModuleN.InitN(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void @__ctorModuleN0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.dotnet.nhost.ModuleN @__real = new global::net.sf.robocode.dotnet.nhost.ModuleN(); + global::net.sf.jni4net.utils.Convertor.InitProxy(@__env, @__obj, @__real); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.dotnet.nhost.@__ModuleN(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/repository/root/DllRootHelper.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/repository/root/DllRootHelper.generated.cs new file mode 100644 index 0000000..c0c5016 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/dotnet/repository/root/DllRootHelper.generated.cs @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.dotnet.repository.root { + + + #region Component Designer generated code + public partial class DllRootHelper_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.dotnet.repository.root.@__DllRootHelper.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.dotnet.repository.root.DllRootHelper), typeof(global::net.sf.robocode.dotnet.repository.root.DllRootHelper_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.dotnet.repository.root.DllRootHelper), typeof(global::net.sf.robocode.dotnet.repository.root.DllRootHelper_))] + internal sealed partial class @__DllRootHelper : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + private @__DllRootHelper(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.dotnet.repository.root.@__DllRootHelper.staticClass = @__class; + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__DllRootHelper); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "Open", "Open0", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "Close", "Close1", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "findItems", "findItems2", "(Ljava/lang/String;)[Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "GetRobotType", "GetRobotType3", "(Lnet/sf/robocode/repository/IRobotItem;)Lnet/sf/robocode/repository/RobotType;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "GetDllFileName", "GetDllFileName4", "(Lnet/sf/robocode/repository/IRobotItem;)Ljava/lang/String;")); + return methods; + } + + private static void Open0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.dotnet.repository.root.DllRootHelper.Open(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void Close1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.dotnet.repository.root.DllRootHelper.Close(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static global::net.sf.jni4net.utils.JniHandle findItems2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class, global::net.sf.jni4net.utils.JniLocalHandle dllPath) { + // (Ljava/lang/String;)[Ljava/lang/String; + // (LSystem/String;)[LSystem/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + @__return = global::net.sf.jni4net.utils.Convertor.ArrayStrongC2JString(@__env, global::net.sf.robocode.dotnet.repository.root.DllRootHelper.findItems(global::net.sf.jni4net.utils.Convertor.StrongJ2CString(@__env, dllPath))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle GetRobotType3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class, global::net.sf.jni4net.utils.JniLocalHandle robotItem) { + // (Lnet/sf/robocode/repository/IRobotItem;)Lnet/sf/robocode/repository/RobotType; + // (Lnet/sf/robocode/repository/IRobotItem;)Lnet/sf/robocode/repository/RobotType; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(global::net.sf.robocode.dotnet.repository.root.DllRootHelper.GetRobotType(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, robotItem))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle GetDllFileName4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__class, global::net.sf.jni4net.utils.JniLocalHandle robotItem) { + // (Lnet/sf/robocode/repository/IRobotItem;)Ljava/lang/String; + // (Lnet/sf/robocode/repository/IRobotItem;)LSystem/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + @__return = global::net.sf.jni4net.utils.Convertor.StrongC2JString(@__env, global::net.sf.robocode.dotnet.repository.root.DllRootHelper.GetDllFileName(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, robotItem))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.dotnet.repository.root.@__DllRootHelper(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/IHost.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/IHost.generated.cs new file mode 100644 index 0000000..d2ea4ea --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/IHost.generated.cs @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.host { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IHost { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/host/IHostManager;Lrobocode/control/RobotSpecification;Lnet/sf/" + + "robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/h" + + "ost/proxies/IHostingRobotProxy;")] + global::net.sf.robocode.host.proxies.IHostingRobotProxy createRobotProxy(global::net.sf.robocode.host.IHostManager par0, global::java.lang.Object par1, global::net.sf.robocode.peer.IRobotStatics par2, global::net.sf.robocode.peer.IRobotPeer par3); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;")] + java.lang.String[] getReferencedClasses(global::net.sf.robocode.repository.IRobotItem par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;" + + "")] + global::net.sf.robocode.repository.RobotType getRobotType(global::net.sf.robocode.repository.IRobotItem par0, bool par1, bool par2); + } + #endregion + + #region Component Designer generated code + public partial class IHost_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.host.@__IHost.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.host.IHost), typeof(global::net.sf.robocode.host.IHost_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.host.IHost), typeof(global::net.sf.robocode.host.IHost_))] + internal sealed partial class @__IHost : global::java.lang.Object, global::net.sf.robocode.host.IHost { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_createRobotProxy0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getReferencedClasses1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobotType2; + + private @__IHost(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.host.@__IHost.staticClass = @__class; + global::net.sf.robocode.host.@__IHost.j4n_createRobotProxy0 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHost.staticClass, "createRobotProxy", "(Lnet/sf/robocode/host/IHostManager;Lrobocode/control/RobotSpecification;Lnet/sf/" + + "robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/h" + + "ost/proxies/IHostingRobotProxy;"); + global::net.sf.robocode.host.@__IHost.j4n_getReferencedClasses1 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHost.staticClass, "getReferencedClasses", "(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;"); + global::net.sf.robocode.host.@__IHost.j4n_getRobotType2 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHost.staticClass, "getRobotType", "(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;" + + ""); + } + + public global::net.sf.robocode.host.proxies.IHostingRobotProxy createRobotProxy(global::net.sf.robocode.host.IHostManager par0, global::java.lang.Object par1, global::net.sf.robocode.peer.IRobotStatics par2, global::net.sf.robocode.peer.IRobotPeer par3) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 18)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.host.@__IHost.j4n_createRobotProxy0, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par2), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par3))); + } + } + + public java.lang.String[] getReferencedClasses(global::net.sf.robocode.repository.IRobotItem par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.host.@__IHost.j4n_getReferencedClasses1, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0))); + } + } + + public global::net.sf.robocode.repository.RobotType getRobotType(global::net.sf.robocode.repository.IRobotItem par0, bool par1, bool par2) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.host.@__IHost.j4n_getRobotType2, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2))); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IHost); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "createRobotProxy", "createRobotProxy0", "(Lnet/sf/robocode/host/IHostManager;Lrobocode/control/RobotSpecification;Lnet/sf/" + + "robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/h" + + "ost/proxies/IHostingRobotProxy;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getReferencedClasses", "getReferencedClasses1", "(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRobotType", "getRobotType2", "(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;" + + "")); + return methods; + } + + private static global::net.sf.jni4net.utils.JniHandle createRobotProxy0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, global::net.sf.jni4net.utils.JniLocalHandle par1, global::net.sf.jni4net.utils.JniLocalHandle par2, global::net.sf.jni4net.utils.JniLocalHandle par3) { + // (Lnet/sf/robocode/host/IHostManager;Lrobocode/control/RobotSpecification;Lnet/sf/robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostingRobotProxy; + // (Lnet/sf/robocode/host/IHostManager;Ljava/lang/Object;Lnet/sf/robocode/peer/IRobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Lnet/sf/robocode/host/proxies/IHostingRobotProxy; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.host.IHost @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.FullC2J(@__env, @__real.createRobotProxy(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0), global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par1), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par2), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par3))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getReferencedClasses1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String; + // (Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.host.IHost @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.ArrayStrongCp2J(@__env, @__real.getReferencedClasses(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRobotType2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, bool par1, bool par2) { + // (Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType; + // (Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.host.IHost @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getRobotType(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0), par1, par2)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.host.@__IHost(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/IHostManager.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/IHostManager.generated.cs new file mode 100644 index 0000000..f8aa9fd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/IHostManager.generated.cs @@ -0,0 +1,323 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.host { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IHostManager { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void cleanup(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/RobotSpecification;Lnet/sf/robocode/host/RobotStatics;Lnet/sf/" + + "robocode/peer/IRobotPeer;)Ljava/lang/Object;")] + global::java.lang.Object createRobotProxy(global::java.lang.Object par0, global::java.lang.Object par1, global::net.sf.robocode.peer.IRobotPeer par2); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;")] + java.lang.String[] getReferencedClasses(global::net.sf.robocode.repository.IRobotItem par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;" + + "")] + global::net.sf.robocode.repository.RobotType getRobotType(global::net.sf.robocode.repository.IRobotItem par0, bool par1, bool par2); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void initSecurity(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()J")] + long getRobotFilesystemQuota(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void resetThreadManager(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/Thread;)V")] + void addSafeThread(global::java.lang.Object par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/Thread;)V")] + void removeSafeThread(global::java.lang.Object par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/io/PrintStream;")] + global::java.io.PrintStream getRobotOutputStream(); + } + #endregion + + #region Component Designer generated code + public partial class IHostManager_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.host.@__IHostManager.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.host.IHostManager), typeof(global::net.sf.robocode.host.IHostManager_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.host.IHostManager), typeof(global::net.sf.robocode.host.IHostManager_))] + internal sealed partial class @__IHostManager : global::java.lang.Object, global::net.sf.robocode.host.IHostManager { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_cleanup0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_createRobotProxy1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getReferencedClasses2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobotType3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_initSecurity4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobotFilesystemQuota5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_resetThreadManager6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_addSafeThread7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_removeSafeThread8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobotOutputStream9; + + private @__IHostManager(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.host.@__IHostManager.staticClass = @__class; + global::net.sf.robocode.host.@__IHostManager.j4n_cleanup0 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "cleanup", "()V"); + global::net.sf.robocode.host.@__IHostManager.j4n_createRobotProxy1 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "createRobotProxy", "(Lrobocode/control/RobotSpecification;Lnet/sf/robocode/host/RobotStatics;Lnet/sf/" + + "robocode/peer/IRobotPeer;)Ljava/lang/Object;"); + global::net.sf.robocode.host.@__IHostManager.j4n_getReferencedClasses2 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "getReferencedClasses", "(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;"); + global::net.sf.robocode.host.@__IHostManager.j4n_getRobotType3 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "getRobotType", "(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;" + + ""); + global::net.sf.robocode.host.@__IHostManager.j4n_initSecurity4 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "initSecurity", "()V"); + global::net.sf.robocode.host.@__IHostManager.j4n_getRobotFilesystemQuota5 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "getRobotFilesystemQuota", "()J"); + global::net.sf.robocode.host.@__IHostManager.j4n_resetThreadManager6 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "resetThreadManager", "()V"); + global::net.sf.robocode.host.@__IHostManager.j4n_addSafeThread7 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "addSafeThread", "(Ljava/lang/Thread;)V"); + global::net.sf.robocode.host.@__IHostManager.j4n_removeSafeThread8 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "removeSafeThread", "(Ljava/lang/Thread;)V"); + global::net.sf.robocode.host.@__IHostManager.j4n_getRobotOutputStream9 = @__env.GetMethodID(global::net.sf.robocode.host.@__IHostManager.staticClass, "getRobotOutputStream", "()Ljava/io/PrintStream;"); + } + + public void cleanup() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.host.@__IHostManager.j4n_cleanup0); + } + } + + public global::java.lang.Object createRobotProxy(global::java.lang.Object par0, global::java.lang.Object par1, global::net.sf.robocode.peer.IRobotPeer par2) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.host.@__IHostManager.j4n_createRobotProxy1, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par2))); + } + } + + public java.lang.String[] getReferencedClasses(global::net.sf.robocode.repository.IRobotItem par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.host.@__IHostManager.j4n_getReferencedClasses2, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0))); + } + } + + public global::net.sf.robocode.repository.RobotType getRobotType(global::net.sf.robocode.repository.IRobotItem par0, bool par1, bool par2) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.host.@__IHostManager.j4n_getRobotType3, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2))); + } + } + + public void initSecurity() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.host.@__IHostManager.j4n_initSecurity4); + } + } + + public long getRobotFilesystemQuota() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((long)(@__env.CallLongMethod(this, global::net.sf.robocode.host.@__IHostManager.j4n_getRobotFilesystemQuota5))); + } + } + + public void resetThreadManager() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.host.@__IHostManager.j4n_resetThreadManager6); + } + } + + public void addSafeThread(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.host.@__IHostManager.j4n_addSafeThread7, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void removeSafeThread(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.host.@__IHostManager.j4n_removeSafeThread8, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public global::java.io.PrintStream getRobotOutputStream() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.host.@__IHostManager.j4n_getRobotOutputStream9)); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IHostManager); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "cleanup", "cleanup0", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "createRobotProxy", "createRobotProxy1", "(Lrobocode/control/RobotSpecification;Lnet/sf/robocode/host/RobotStatics;Lnet/sf/" + + "robocode/peer/IRobotPeer;)Ljava/lang/Object;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getReferencedClasses", "getReferencedClasses2", "(Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRobotType", "getRobotType3", "(Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType;" + + "")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "initSecurity", "initSecurity4", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRobotFilesystemQuota", "getRobotFilesystemQuota5", "()J")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "resetThreadManager", "resetThreadManager6", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "addSafeThread", "addSafeThread7", "(Ljava/lang/Thread;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "removeSafeThread", "removeSafeThread8", "(Ljava/lang/Thread;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRobotOutputStream", "getRobotOutputStream9", "()Ljava/io/PrintStream;")); + return methods; + } + + private static void cleanup0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.cleanup(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static global::net.sf.jni4net.utils.JniHandle createRobotProxy1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, global::net.sf.jni4net.utils.JniLocalHandle par1, global::net.sf.jni4net.utils.JniLocalHandle par2) { + // (Lrobocode/control/RobotSpecification;Lnet/sf/robocode/host/RobotStatics;Lnet/sf/robocode/peer/IRobotPeer;)Ljava/lang/Object; + // (Ljava/lang/Object;Ljava/lang/Object;Lnet/sf/robocode/peer/IRobotPeer;)Ljava/lang/Object; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.FullC2J(@__env, @__real.createRobotProxy(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0), global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par1), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par2))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getReferencedClasses2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String; + // (Lnet/sf/robocode/repository/IRobotItem;)[Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.ArrayStrongCp2J(@__env, @__real.getReferencedClasses(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRobotType3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, bool par1, bool par2) { + // (Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType; + // (Lnet/sf/robocode/repository/IRobotItem;ZZ)Lnet/sf/robocode/repository/RobotType; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getRobotType(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0), par1, par2)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static void initSecurity4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.initSecurity(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static long getRobotFilesystemQuota5(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()J + // ()J + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + long @__return = default(long); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((long)(@__real.getRobotFilesystemQuota())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static void resetThreadManager6(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.resetThreadManager(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void addSafeThread7(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Ljava/lang/Thread;)V + // (Ljava/lang/Object;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.addSafeThread(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void removeSafeThread8(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Ljava/lang/Thread;)V + // (Ljava/lang/Object;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.removeSafeThread(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static global::net.sf.jni4net.utils.JniHandle getRobotOutputStream9(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/io/PrintStream; + // ()Ljava/io/PrintStream; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.host.IHostManager @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getRobotOutputStream()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.host.@__IHostManager(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/proxies/IHostingRobotProxy.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/proxies/IHostingRobotProxy.generated.cs new file mode 100644 index 0000000..9ee4cf0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/host/proxies/IHostingRobotProxy.generated.cs @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.host.proxies { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IHostingRobotProxy { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void cleanup(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/peer/ExecCommands;Lrobocode/RobotStatus;)V")] + void startRound(global::java.lang.Object par0, global::java.lang.Object par1); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void forceStopThread(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void waitForStopThread(); + } + #endregion + + #region Component Designer generated code + public partial class IHostingRobotProxy_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.host.proxies.IHostingRobotProxy), typeof(global::net.sf.robocode.host.proxies.IHostingRobotProxy_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.host.proxies.IHostingRobotProxy), typeof(global::net.sf.robocode.host.proxies.IHostingRobotProxy_))] + internal sealed partial class @__IHostingRobotProxy : global::java.lang.Object, global::net.sf.robocode.host.proxies.IHostingRobotProxy { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_cleanup0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_startRound1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_forceStopThread2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_waitForStopThread3; + + private @__IHostingRobotProxy(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.staticClass = @__class; + global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.j4n_cleanup0 = @__env.GetMethodID(global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.staticClass, "cleanup", "()V"); + global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.j4n_startRound1 = @__env.GetMethodID(global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.staticClass, "startRound", "(Lnet/sf/robocode/peer/ExecCommands;Lrobocode/RobotStatus;)V"); + global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.j4n_forceStopThread2 = @__env.GetMethodID(global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.staticClass, "forceStopThread", "()V"); + global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.j4n_waitForStopThread3 = @__env.GetMethodID(global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.staticClass, "waitForStopThread", "()V"); + } + + public void cleanup() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.j4n_cleanup0); + } + } + + public void startRound(global::java.lang.Object par0, global::java.lang.Object par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.j4n_startRound1, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1)); + } + } + + public void forceStopThread() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.j4n_forceStopThread2); + } + } + + public void waitForStopThread() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.host.proxies.@__IHostingRobotProxy.j4n_waitForStopThread3); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IHostingRobotProxy); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "cleanup", "cleanup0", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "startRound", "startRound1", "(Lnet/sf/robocode/peer/ExecCommands;Lrobocode/RobotStatus;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "forceStopThread", "forceStopThread2", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "waitForStopThread", "waitForStopThread3", "()V")); + return methods; + } + + private static void cleanup0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.host.proxies.IHostingRobotProxy @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.cleanup(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void startRound1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, global::net.sf.jni4net.utils.JniLocalHandle par1) { + // (Lnet/sf/robocode/peer/ExecCommands;Lrobocode/RobotStatus;)V + // (Ljava/lang/Object;Ljava/lang/Object;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.host.proxies.IHostingRobotProxy @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.startRound(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0), global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par1)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void forceStopThread2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.host.proxies.IHostingRobotProxy @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.forceStopThread(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void waitForStopThread3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.host.proxies.IHostingRobotProxy @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.waitForStopThread(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.host.proxies.@__IHostingRobotProxy(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/io/Logger.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/io/Logger.generated.cs new file mode 100644 index 0000000..ed6fce7 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/io/Logger.generated.cs @@ -0,0 +1,175 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.io { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class Logger : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_logError0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_logError1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_logError2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setLogListener3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_logMessage4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_logMessage5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_logWarning6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_printlnToRobotsConsole7; + + internal static global::net.sf.jni4net.jni.FieldId j4n_realOut8; + + internal static global::net.sf.jni4net.jni.FieldId j4n_realErr9; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorLogger10; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public Logger() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n__ctorLogger10, this); + } + } + + protected Logger(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.io.Logger.staticClass; + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Ljava/io/PrintStream;")] + public static global::java.io.PrintStream realOut { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_realOut8)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Ljava/io/PrintStream;")] + public static global::java.io.PrintStream realErr { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_realErr9)); + } + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.io.Logger.staticClass = @__class; + global::net.sf.robocode.io.Logger.j4n_logError0 = @__env.GetStaticMethodID(global::net.sf.robocode.io.Logger.staticClass, "logError", "(Ljava/lang/Throwable;)V"); + global::net.sf.robocode.io.Logger.j4n_logError1 = @__env.GetStaticMethodID(global::net.sf.robocode.io.Logger.staticClass, "logError", "(Ljava/lang/String;)V"); + global::net.sf.robocode.io.Logger.j4n_logError2 = @__env.GetStaticMethodID(global::net.sf.robocode.io.Logger.staticClass, "logError", "(Ljava/lang/String;Ljava/lang/Throwable;)V"); + global::net.sf.robocode.io.Logger.j4n_setLogListener3 = @__env.GetStaticMethodID(global::net.sf.robocode.io.Logger.staticClass, "setLogListener", "(Lrobocode/control/events/IBattleListener;)V"); + global::net.sf.robocode.io.Logger.j4n_logMessage4 = @__env.GetStaticMethodID(global::net.sf.robocode.io.Logger.staticClass, "logMessage", "(Ljava/lang/String;Z)V"); + global::net.sf.robocode.io.Logger.j4n_logMessage5 = @__env.GetStaticMethodID(global::net.sf.robocode.io.Logger.staticClass, "logMessage", "(Ljava/lang/String;)V"); + global::net.sf.robocode.io.Logger.j4n_logWarning6 = @__env.GetStaticMethodID(global::net.sf.robocode.io.Logger.staticClass, "logWarning", "(Ljava/lang/String;)V"); + global::net.sf.robocode.io.Logger.j4n_printlnToRobotsConsole7 = @__env.GetStaticMethodID(global::net.sf.robocode.io.Logger.staticClass, "printlnToRobotsConsole", "(Ljava/lang/String;)V"); + global::net.sf.robocode.io.Logger.j4n_realOut8 = @__env.GetStaticFieldID(global::net.sf.robocode.io.Logger.staticClass, "realOut", "Ljava/io/PrintStream;"); + global::net.sf.robocode.io.Logger.j4n_realErr9 = @__env.GetStaticFieldID(global::net.sf.robocode.io.Logger.staticClass, "realErr", "Ljava/io/PrintStream;"); + global::net.sf.robocode.io.Logger.j4n__ctorLogger10 = @__env.GetMethodID(global::net.sf.robocode.io.Logger.staticClass, "", "()V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/Throwable;)V")] + public static void logError(global::java.lang.Throwable par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_logError0, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public static void logError(global::java.lang.String par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_logError1, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;Ljava/lang/Throwable;)V")] + public static void logError(global::java.lang.String par0, global::java.lang.Throwable par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_logError2, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/events/IBattleListener;)V")] + public static void setLogListener(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_setLogListener3, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;Z)V")] + public static void logMessage(global::java.lang.String par0, bool par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_logMessage4, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public static void logMessage(global::java.lang.String par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_logMessage5, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public static void logWarning(global::java.lang.String par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_logWarning6, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public static void printlnToRobotsConsole(global::java.lang.String par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.io.Logger.staticClass, global::net.sf.robocode.io.Logger.j4n_printlnToRobotsConsole7, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.io.Logger(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/manager/IVersionManagerBase.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/manager/IVersionManagerBase.generated.cs new file mode 100644 index 0000000..70279dc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/manager/IVersionManagerBase.generated.cs @@ -0,0 +1,171 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.manager { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IVersionManagerBase { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getVersion(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + int getVersionAsInt(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getVersionN(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isLastRunVersionChanged(); + } + #endregion + + #region Component Designer generated code + public partial class IVersionManagerBase_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.manager.@__IVersionManagerBase.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.manager.IVersionManagerBase), typeof(global::net.sf.robocode.manager.IVersionManagerBase_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.manager.IVersionManagerBase), typeof(global::net.sf.robocode.manager.IVersionManagerBase_))] + internal sealed partial class @__IVersionManagerBase : global::java.lang.Object, global::net.sf.robocode.manager.IVersionManagerBase { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVersion0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVersionAsInt1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVersionN2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isLastRunVersionChanged3; + + private @__IVersionManagerBase(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.manager.@__IVersionManagerBase.staticClass = @__class; + global::net.sf.robocode.manager.@__IVersionManagerBase.j4n_getVersion0 = @__env.GetMethodID(global::net.sf.robocode.manager.@__IVersionManagerBase.staticClass, "getVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.manager.@__IVersionManagerBase.j4n_getVersionAsInt1 = @__env.GetMethodID(global::net.sf.robocode.manager.@__IVersionManagerBase.staticClass, "getVersionAsInt", "()I"); + global::net.sf.robocode.manager.@__IVersionManagerBase.j4n_getVersionN2 = @__env.GetMethodID(global::net.sf.robocode.manager.@__IVersionManagerBase.staticClass, "getVersionN", "()Ljava/lang/String;"); + global::net.sf.robocode.manager.@__IVersionManagerBase.j4n_isLastRunVersionChanged3 = @__env.GetMethodID(global::net.sf.robocode.manager.@__IVersionManagerBase.staticClass, "isLastRunVersionChanged", "()Z"); + } + + public global::java.lang.String getVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.manager.@__IVersionManagerBase.j4n_getVersion0)); + } + } + + public int getVersionAsInt() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.manager.@__IVersionManagerBase.j4n_getVersionAsInt1))); + } + } + + public global::java.lang.String getVersionN() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.manager.@__IVersionManagerBase.j4n_getVersionN2)); + } + } + + public bool isLastRunVersionChanged() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.manager.@__IVersionManagerBase.j4n_isLastRunVersionChanged3))); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IVersionManagerBase); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getVersion", "getVersion0", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getVersionAsInt", "getVersionAsInt1", "()I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getVersionN", "getVersionN2", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isLastRunVersionChanged", "isLastRunVersionChanged3", "()Z")); + return methods; + } + + private static global::net.sf.jni4net.utils.JniHandle getVersion0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.manager.IVersionManagerBase @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int getVersionAsInt1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()I + // ()I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::net.sf.robocode.manager.IVersionManagerBase @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.getVersionAsInt())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getVersionN2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.manager.IVersionManagerBase @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getVersionN()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isLastRunVersionChanged3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.manager.IVersionManagerBase @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isLastRunVersionChanged())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.manager.@__IVersionManagerBase(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/BadBehavior.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/BadBehavior.generated.cs new file mode 100644 index 0000000..a794055 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/BadBehavior.generated.cs @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.peer { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class BadBehavior : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_valueOf0; + + internal static global::net.sf.jni4net.jni.FieldId j4n_CANNOT_START1; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SKIPPED_TOO_MANY_TURNS2; + + internal static global::net.sf.jni4net.jni.FieldId j4n_UNSTOPPABLE3; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SECURITY_VIOLATION4; + + protected BadBehavior(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.peer.BadBehavior.staticClass; + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lnet/sf/robocode/peer/BadBehavior;")] + public static global::net.sf.robocode.peer.BadBehavior CANNOT_START { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::net.sf.robocode.peer.BadBehavior.staticClass, global::net.sf.robocode.peer.BadBehavior.j4n_CANNOT_START1)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lnet/sf/robocode/peer/BadBehavior;")] + public static global::net.sf.robocode.peer.BadBehavior SKIPPED_TOO_MANY_TURNS { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::net.sf.robocode.peer.BadBehavior.staticClass, global::net.sf.robocode.peer.BadBehavior.j4n_SKIPPED_TOO_MANY_TURNS2)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lnet/sf/robocode/peer/BadBehavior;")] + public static global::net.sf.robocode.peer.BadBehavior UNSTOPPABLE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::net.sf.robocode.peer.BadBehavior.staticClass, global::net.sf.robocode.peer.BadBehavior.j4n_UNSTOPPABLE3)); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lnet/sf/robocode/peer/BadBehavior;")] + public static global::net.sf.robocode.peer.BadBehavior SECURITY_VIOLATION { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::net.sf.robocode.peer.BadBehavior.staticClass, global::net.sf.robocode.peer.BadBehavior.j4n_SECURITY_VIOLATION4)); + } + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.peer.BadBehavior.staticClass = @__class; + global::net.sf.robocode.peer.BadBehavior.j4n_valueOf0 = @__env.GetStaticMethodID(global::net.sf.robocode.peer.BadBehavior.staticClass, "valueOf", "(Ljava/lang/String;)Lnet/sf/robocode/peer/BadBehavior;"); + global::net.sf.robocode.peer.BadBehavior.j4n_CANNOT_START1 = @__env.GetStaticFieldID(global::net.sf.robocode.peer.BadBehavior.staticClass, "CANNOT_START", "Lnet/sf/robocode/peer/BadBehavior;"); + global::net.sf.robocode.peer.BadBehavior.j4n_SKIPPED_TOO_MANY_TURNS2 = @__env.GetStaticFieldID(global::net.sf.robocode.peer.BadBehavior.staticClass, "SKIPPED_TOO_MANY_TURNS", "Lnet/sf/robocode/peer/BadBehavior;"); + global::net.sf.robocode.peer.BadBehavior.j4n_UNSTOPPABLE3 = @__env.GetStaticFieldID(global::net.sf.robocode.peer.BadBehavior.staticClass, "UNSTOPPABLE", "Lnet/sf/robocode/peer/BadBehavior;"); + global::net.sf.robocode.peer.BadBehavior.j4n_SECURITY_VIOLATION4 = @__env.GetStaticFieldID(global::net.sf.robocode.peer.BadBehavior.staticClass, "SECURITY_VIOLATION", "Lnet/sf/robocode/peer/BadBehavior;"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)Lnet/sf/robocode/peer/BadBehavior;")] + public static global::net.sf.robocode.peer.BadBehavior valueOf(global::java.lang.String par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.peer.BadBehavior.staticClass, global::net.sf.robocode.peer.BadBehavior.j4n_valueOf0, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.peer.BadBehavior(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/IRobotPeer.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/IRobotPeer.generated.cs new file mode 100644 index 0000000..e3e1c34 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/IRobotPeer.generated.cs @@ -0,0 +1,313 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.peer { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IRobotPeer { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void drainEnergy(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/peer/BadBehavior;)V")] + void punishBadBehavior(global::net.sf.robocode.peer.BadBehavior par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Z)V")] + void setRunning(bool par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isRunning(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/peer/ExecCommands;)Lnet/sf/robocode/peer/ExecResults;")] + global::java.lang.Object waitForBattleEndImpl(global::java.lang.Object par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/peer/ExecCommands;)Lnet/sf/robocode/peer/ExecResults;")] + global::java.lang.Object executeImpl(global::java.lang.Object par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)V")] + void setupBuffer(global::java.nio.ByteBuffer par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void executeImplSerial(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void waitForBattleEndImplSerial(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + void setupThread(); + } + #endregion + + #region Component Designer generated code + public partial class IRobotPeer_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.peer.@__IRobotPeer.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.peer.IRobotPeer), typeof(global::net.sf.robocode.peer.IRobotPeer_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.peer.IRobotPeer), typeof(global::net.sf.robocode.peer.IRobotPeer_))] + internal sealed partial class @__IRobotPeer : global::java.lang.Object, global::net.sf.robocode.peer.IRobotPeer { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_drainEnergy0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_punishBadBehavior1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setRunning2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isRunning3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_waitForBattleEndImpl4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_executeImpl5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setupBuffer6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_executeImplSerial7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_waitForBattleEndImplSerial8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setupThread9; + + private @__IRobotPeer(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.peer.@__IRobotPeer.staticClass = @__class; + global::net.sf.robocode.peer.@__IRobotPeer.j4n_drainEnergy0 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "drainEnergy", "()V"); + global::net.sf.robocode.peer.@__IRobotPeer.j4n_punishBadBehavior1 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "punishBadBehavior", "(Lnet/sf/robocode/peer/BadBehavior;)V"); + global::net.sf.robocode.peer.@__IRobotPeer.j4n_setRunning2 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "setRunning", "(Z)V"); + global::net.sf.robocode.peer.@__IRobotPeer.j4n_isRunning3 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "isRunning", "()Z"); + global::net.sf.robocode.peer.@__IRobotPeer.j4n_waitForBattleEndImpl4 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "waitForBattleEndImpl", "(Lnet/sf/robocode/peer/ExecCommands;)Lnet/sf/robocode/peer/ExecResults;"); + global::net.sf.robocode.peer.@__IRobotPeer.j4n_executeImpl5 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "executeImpl", "(Lnet/sf/robocode/peer/ExecCommands;)Lnet/sf/robocode/peer/ExecResults;"); + global::net.sf.robocode.peer.@__IRobotPeer.j4n_setupBuffer6 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "setupBuffer", "(Ljava/nio/ByteBuffer;)V"); + global::net.sf.robocode.peer.@__IRobotPeer.j4n_executeImplSerial7 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "executeImplSerial", "()V"); + global::net.sf.robocode.peer.@__IRobotPeer.j4n_waitForBattleEndImplSerial8 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "waitForBattleEndImplSerial", "()V"); + global::net.sf.robocode.peer.@__IRobotPeer.j4n_setupThread9 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotPeer.staticClass, "setupThread", "()V"); + } + + public void drainEnergy() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_drainEnergy0); + } + } + + public void punishBadBehavior(global::net.sf.robocode.peer.BadBehavior par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_punishBadBehavior1, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void setRunning(bool par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_setRunning2, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + public bool isRunning() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_isRunning3))); + } + } + + public global::java.lang.Object waitForBattleEndImpl(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_waitForBattleEndImpl4, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + public global::java.lang.Object executeImpl(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_executeImpl5, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + public void setupBuffer(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_setupBuffer6, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + public void executeImplSerial() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_executeImplSerial7); + } + } + + public void waitForBattleEndImplSerial() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_waitForBattleEndImplSerial8); + } + } + + public void setupThread() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.peer.@__IRobotPeer.j4n_setupThread9); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IRobotPeer); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "drainEnergy", "drainEnergy0", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "punishBadBehavior", "punishBadBehavior1", "(Lnet/sf/robocode/peer/BadBehavior;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "setRunning", "setRunning2", "(Z)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isRunning", "isRunning3", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "waitForBattleEndImpl", "waitForBattleEndImpl4", "(Lnet/sf/robocode/peer/ExecCommands;)Lnet/sf/robocode/peer/ExecResults;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "executeImpl", "executeImpl5", "(Lnet/sf/robocode/peer/ExecCommands;)Lnet/sf/robocode/peer/ExecResults;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "setupBuffer", "setupBuffer6", "(Ljava/nio/ByteBuffer;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "executeImplSerial", "executeImplSerial7", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "waitForBattleEndImplSerial", "waitForBattleEndImplSerial8", "()V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "setupThread", "setupThread9", "()V")); + return methods; + } + + private static void drainEnergy0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.drainEnergy(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void punishBadBehavior1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lnet/sf/robocode/peer/BadBehavior;)V + // (Lnet/sf/robocode/peer/BadBehavior;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.punishBadBehavior(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void setRunning2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, bool par0) { + // (Z)V + // (Z)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.setRunning(par0); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static bool isRunning3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isRunning())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle waitForBattleEndImpl4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lnet/sf/robocode/peer/ExecCommands;)Lnet/sf/robocode/peer/ExecResults; + // (Ljava/lang/Object;)Ljava/lang/Object; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.waitForBattleEndImpl(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle executeImpl5(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Lnet/sf/robocode/peer/ExecCommands;)Lnet/sf/robocode/peer/ExecResults; + // (Ljava/lang/Object;)Ljava/lang/Object; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.executeImpl(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static void setupBuffer6(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Ljava/nio/ByteBuffer;)V + // (Ljava/nio/ByteBuffer;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.setupBuffer(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void executeImplSerial7(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.executeImplSerial(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void waitForBattleEndImplSerial8(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.waitForBattleEndImplSerial(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static void setupThread9(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()V + // ()V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.peer.IRobotPeer @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.setupThread(); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.peer.@__IRobotPeer(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/IRobotStatics.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/IRobotStatics.generated.cs new file mode 100644 index 0000000..50f44bd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/peer/IRobotStatics.generated.cs @@ -0,0 +1,171 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.peer { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IRobotStatics { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isAdvancedRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isTeamRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isInteractiveRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isPaintRobot(); + } + #endregion + + #region Component Designer generated code + public partial class IRobotStatics_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.peer.@__IRobotStatics.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.peer.IRobotStatics), typeof(global::net.sf.robocode.peer.IRobotStatics_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.peer.IRobotStatics), typeof(global::net.sf.robocode.peer.IRobotStatics_))] + internal sealed partial class @__IRobotStatics : global::java.lang.Object, global::net.sf.robocode.peer.IRobotStatics { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isAdvancedRobot0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isTeamRobot1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isInteractiveRobot2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isPaintRobot3; + + private @__IRobotStatics(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.peer.@__IRobotStatics.staticClass = @__class; + global::net.sf.robocode.peer.@__IRobotStatics.j4n_isAdvancedRobot0 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotStatics.staticClass, "isAdvancedRobot", "()Z"); + global::net.sf.robocode.peer.@__IRobotStatics.j4n_isTeamRobot1 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotStatics.staticClass, "isTeamRobot", "()Z"); + global::net.sf.robocode.peer.@__IRobotStatics.j4n_isInteractiveRobot2 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotStatics.staticClass, "isInteractiveRobot", "()Z"); + global::net.sf.robocode.peer.@__IRobotStatics.j4n_isPaintRobot3 = @__env.GetMethodID(global::net.sf.robocode.peer.@__IRobotStatics.staticClass, "isPaintRobot", "()Z"); + } + + public bool isAdvancedRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.peer.@__IRobotStatics.j4n_isAdvancedRobot0))); + } + } + + public bool isTeamRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.peer.@__IRobotStatics.j4n_isTeamRobot1))); + } + } + + public bool isInteractiveRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.peer.@__IRobotStatics.j4n_isInteractiveRobot2))); + } + } + + public bool isPaintRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.peer.@__IRobotStatics.j4n_isPaintRobot3))); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IRobotStatics); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isAdvancedRobot", "isAdvancedRobot0", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isTeamRobot", "isTeamRobot1", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isInteractiveRobot", "isInteractiveRobot2", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isPaintRobot", "isPaintRobot3", "()Z")); + return methods; + } + + private static bool isAdvancedRobot0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.peer.IRobotStatics @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isAdvancedRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isTeamRobot1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.peer.IRobotStatics @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isTeamRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isInteractiveRobot2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.peer.IRobotStatics @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isInteractiveRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isPaintRobot3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.peer.IRobotStatics @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isPaintRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.peer.@__IRobotStatics(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/IRobotItem.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/IRobotItem.generated.cs new file mode 100644 index 0000000..4c46208 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/IRobotItem.generated.cs @@ -0,0 +1,1045 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.repository { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IRobotItem : global::net.sf.robocode.repository.IRobotSpecItem { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getPlatform(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isJuniorRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isStandardRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isAdvancedRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isTeamRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isDroid(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isSentryRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isInteractiveRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isPaintRobot(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/net/URL;")] + global::java.net.URL getClassPathURL(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()[Ljava/net/URL;")] + java.net.URL[] getSourcePathURLs(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getWritableDirectory(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getReadableDirectory(); + } + #endregion + + #region Component Designer generated code + public partial class IRobotItem_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.repository.@__IRobotItem.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.repository.IRobotItem), typeof(global::net.sf.robocode.repository.IRobotItem_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.repository.IRobotItem), typeof(global::net.sf.robocode.repository.IRobotItem_))] + internal sealed partial class @__IRobotItem : global::java.lang.Object, global::net.sf.robocode.repository.IRobotItem { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_compareTo0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isValid1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVersion2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isTeam3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isInJAR4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setValid5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getDescription6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getAuthorName7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getWebpage8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getIncludeSource9; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getIncludeData10; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isSourceIncluded11; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRootPath12; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getItemURL13; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isDevelopmentVersion14; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobocodeVersion15; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getFullPackage16; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRelativePath17; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRootPackage18; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getFullClassNameWithVersion19; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getUniqueFullClassName20; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getUniqueFullClassNameWithVersion21; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getUniqueShortClassNameWithVersion22; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getUniqueVeryShortClassNameWithVersion23; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getFullClassName24; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getShortClassName25; + + internal static global::net.sf.jni4net.jni.MethodId j4n_createRobotSpecification26; + + internal static global::net.sf.jni4net.jni.MethodId j4n_storeProperties27; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getPlatform28; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isJuniorRobot29; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isStandardRobot30; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isAdvancedRobot31; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isTeamRobot32; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isDroid33; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isSentryRobot34; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isInteractiveRobot35; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isPaintRobot36; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getClassPathURL37; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getSourcePathURLs38; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getWritableDirectory39; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getReadableDirectory40; + + private @__IRobotItem(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.repository.@__IRobotItem.staticClass = @__class; + global::net.sf.robocode.repository.@__IRobotItem.j4n_compareTo0 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "compareTo", "(Ljava/lang/Object;)I"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isValid1 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isValid", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getVersion2 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isTeam3 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isTeam", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isInJAR4 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isInJAR", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_setValid5 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "setValid", "(Z)V"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getDescription6 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getDescription", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getAuthorName7 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getAuthorName", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getWebpage8 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getWebpage", "()Ljava/net/URL;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getIncludeSource9 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getIncludeSource", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getIncludeData10 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getIncludeData", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isSourceIncluded11 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isSourceIncluded", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getRootPath12 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getRootPath", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getItemURL13 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getItemURL", "()Ljava/net/URL;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isDevelopmentVersion14 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isDevelopmentVersion", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getRobocodeVersion15 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getRobocodeVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getFullPackage16 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getFullPackage", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getRelativePath17 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getRelativePath", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getRootPackage18 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getRootPackage", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getFullClassNameWithVersion19 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getFullClassNameWithVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getUniqueFullClassName20 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getUniqueFullClassName", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getUniqueFullClassNameWithVersion21 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getUniqueFullClassNameWithVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getUniqueShortClassNameWithVersion22 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getUniqueShortClassNameWithVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getUniqueVeryShortClassNameWithVersion23 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getUniqueVeryShortClassNameWithVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getFullClassName24 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getFullClassName", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getShortClassName25 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getShortClassName", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_createRobotSpecification26 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "createRobotSpecification", "()Lrobocode/control/RobotSpecification;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_storeProperties27 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "storeProperties", "(Ljava/io/OutputStream;Lnet/sf/robocode/repository/RobotProperties;)V"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getPlatform28 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getPlatform", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isJuniorRobot29 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isJuniorRobot", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isStandardRobot30 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isStandardRobot", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isAdvancedRobot31 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isAdvancedRobot", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isTeamRobot32 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isTeamRobot", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isDroid33 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isDroid", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isSentryRobot34 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isSentryRobot", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isInteractiveRobot35 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isInteractiveRobot", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_isPaintRobot36 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "isPaintRobot", "()Z"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getClassPathURL37 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getClassPathURL", "()Ljava/net/URL;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getSourcePathURLs38 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getSourcePathURLs", "()[Ljava/net/URL;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getWritableDirectory39 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getWritableDirectory", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotItem.j4n_getReadableDirectory40 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotItem.staticClass, "getReadableDirectory", "()Ljava/lang/String;"); + } + + public int compareTo(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_compareTo0, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)))); + } + } + + public bool isValid() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isValid1))); + } + } + + public global::java.lang.String getVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getVersion2)); + } + } + + public bool isTeam() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isTeam3))); + } + } + + public bool isInJAR() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isInJAR4))); + } + } + + public void setValid(bool par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_setValid5, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + public global::java.lang.String getDescription() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getDescription6)); + } + } + + public global::java.lang.String getAuthorName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getAuthorName7)); + } + } + + public global::java.net.URL getWebpage() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getWebpage8)); + } + } + + public bool getIncludeSource() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getIncludeSource9))); + } + } + + public bool getIncludeData() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getIncludeData10))); + } + } + + public bool isSourceIncluded() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isSourceIncluded11))); + } + } + + public global::java.lang.String getRootPath() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getRootPath12)); + } + } + + public global::java.net.URL getItemURL() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getItemURL13)); + } + } + + public bool isDevelopmentVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isDevelopmentVersion14))); + } + } + + public global::java.lang.String getRobocodeVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getRobocodeVersion15)); + } + } + + public global::java.lang.String getFullPackage() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getFullPackage16)); + } + } + + public global::java.lang.String getRelativePath() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getRelativePath17)); + } + } + + public global::java.lang.String getRootPackage() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getRootPackage18)); + } + } + + public global::java.lang.String getFullClassNameWithVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getFullClassNameWithVersion19)); + } + } + + public global::java.lang.String getUniqueFullClassName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getUniqueFullClassName20)); + } + } + + public global::java.lang.String getUniqueFullClassNameWithVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getUniqueFullClassNameWithVersion21)); + } + } + + public global::java.lang.String getUniqueShortClassNameWithVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getUniqueShortClassNameWithVersion22)); + } + } + + public global::java.lang.String getUniqueVeryShortClassNameWithVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getUniqueVeryShortClassNameWithVersion23)); + } + } + + public global::java.lang.String getFullClassName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getFullClassName24)); + } + } + + public global::java.lang.String getShortClassName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getShortClassName25)); + } + } + + public global::java.lang.Object createRobotSpecification() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_createRobotSpecification26)); + } + } + + public void storeProperties(global::java.io.OutputStream par0, global::java.lang.Object par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_storeProperties27, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1)); + } + } + + public global::java.lang.String getPlatform() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getPlatform28)); + } + } + + public bool isJuniorRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isJuniorRobot29))); + } + } + + public bool isStandardRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isStandardRobot30))); + } + } + + public bool isAdvancedRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isAdvancedRobot31))); + } + } + + public bool isTeamRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isTeamRobot32))); + } + } + + public bool isDroid() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isDroid33))); + } + } + + public bool isSentryRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isSentryRobot34))); + } + } + + public bool isInteractiveRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isInteractiveRobot35))); + } + } + + public bool isPaintRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_isPaintRobot36))); + } + } + + public global::java.net.URL getClassPathURL() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getClassPathURL37)); + } + } + + public java.net.URL[] getSourcePathURLs() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.ArrayStrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getSourcePathURLs38)); + } + } + + public global::java.lang.String getWritableDirectory() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getWritableDirectory39)); + } + } + + public global::java.lang.String getReadableDirectory() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotItem.j4n_getReadableDirectory40)); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IRobotItem); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "compareTo", "compareTo0", "(Ljava/lang/Object;)I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isValid", "isValid1", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getVersion", "getVersion2", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isTeam", "isTeam3", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isInJAR", "isInJAR4", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "setValid", "setValid5", "(Z)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getDescription", "getDescription6", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getAuthorName", "getAuthorName7", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getWebpage", "getWebpage8", "()Ljava/net/URL;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getIncludeSource", "getIncludeSource9", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getIncludeData", "getIncludeData10", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isSourceIncluded", "isSourceIncluded11", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRootPath", "getRootPath12", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getItemURL", "getItemURL13", "()Ljava/net/URL;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isDevelopmentVersion", "isDevelopmentVersion14", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRobocodeVersion", "getRobocodeVersion15", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getFullPackage", "getFullPackage16", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRelativePath", "getRelativePath17", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRootPackage", "getRootPackage18", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getFullClassNameWithVersion", "getFullClassNameWithVersion19", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getUniqueFullClassName", "getUniqueFullClassName20", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getUniqueFullClassNameWithVersion", "getUniqueFullClassNameWithVersion21", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getUniqueShortClassNameWithVersion", "getUniqueShortClassNameWithVersion22", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getUniqueVeryShortClassNameWithVersion", "getUniqueVeryShortClassNameWithVersion23", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getFullClassName", "getFullClassName24", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getShortClassName", "getShortClassName25", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "createRobotSpecification", "createRobotSpecification26", "()Lrobocode/control/RobotSpecification;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "storeProperties", "storeProperties27", "(Ljava/io/OutputStream;Lnet/sf/robocode/repository/RobotProperties;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getPlatform", "getPlatform28", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isJuniorRobot", "isJuniorRobot29", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isStandardRobot", "isStandardRobot30", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isAdvancedRobot", "isAdvancedRobot31", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isTeamRobot", "isTeamRobot32", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isDroid", "isDroid33", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isSentryRobot", "isSentryRobot34", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isInteractiveRobot", "isInteractiveRobot35", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isPaintRobot", "isPaintRobot36", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getClassPathURL", "getClassPathURL37", "()Ljava/net/URL;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getSourcePathURLs", "getSourcePathURLs38", "()[Ljava/net/URL;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getWritableDirectory", "getWritableDirectory39", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getReadableDirectory", "getReadableDirectory40", "()Ljava/lang/String;")); + return methods; + } + + private static int compareTo0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Ljava/lang/Object;)I + // (Ljava/lang/Object;)I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(((global::java.lang.Comparable)(@__real)).compareTo(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0)))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isValid1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).isValid())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getVersion2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isTeam3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).isTeam())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isInJAR4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).isInJAR())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static void setValid5(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, bool par0) { + // (Z)V + // (Z)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + ((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).setValid(par0); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static global::net.sf.jni4net.utils.JniHandle getDescription6(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getDescription()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getAuthorName7(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getAuthorName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getWebpage8(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/net/URL; + // ()Ljava/net/URL; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getWebpage()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool getIncludeSource9(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getIncludeSource())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool getIncludeData10(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getIncludeData())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isSourceIncluded11(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).isSourceIncluded())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRootPath12(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getRootPath()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getItemURL13(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/net/URL; + // ()Ljava/net/URL; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getItemURL()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isDevelopmentVersion14(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).isDevelopmentVersion())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRobocodeVersion15(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getRobocodeVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getFullPackage16(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getFullPackage()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRelativePath17(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getRelativePath()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRootPackage18(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getRootPackage()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getFullClassNameWithVersion19(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getFullClassNameWithVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getUniqueFullClassName20(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getUniqueFullClassName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getUniqueFullClassNameWithVersion21(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getUniqueFullClassNameWithVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getUniqueShortClassNameWithVersion22(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getUniqueShortClassNameWithVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getUniqueVeryShortClassNameWithVersion23(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getUniqueVeryShortClassNameWithVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getFullClassName24(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getFullClassName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getShortClassName25(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).getShortClassName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle createRobotSpecification26(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Lrobocode/control/RobotSpecification; + // ()Ljava/lang/Object; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).createRobotSpecification()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static void storeProperties27(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, global::net.sf.jni4net.utils.JniLocalHandle par1) { + // (Ljava/io/OutputStream;Lnet/sf/robocode/repository/RobotProperties;)V + // (Ljava/io/OutputStream;Ljava/lang/Object;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + ((global::net.sf.robocode.repository.IRobotSpecItem)(@__real)).storeProperties(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0), global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par1)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static global::net.sf.jni4net.utils.JniHandle getPlatform28(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getPlatform()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isJuniorRobot29(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isJuniorRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isStandardRobot30(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isStandardRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isAdvancedRobot31(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isAdvancedRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isTeamRobot32(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isTeamRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isDroid33(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isDroid())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isSentryRobot34(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isSentryRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isInteractiveRobot35(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isInteractiveRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isPaintRobot36(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isPaintRobot())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getClassPathURL37(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/net/URL; + // ()Ljava/net/URL; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getClassPathURL()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getSourcePathURLs38(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()[Ljava/net/URL; + // ()[Ljava/net/URL; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.ArrayStrongCp2J(@__env, @__real.getSourcePathURLs()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getWritableDirectory39(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getWritableDirectory()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getReadableDirectory40(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getReadableDirectory()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.repository.@__IRobotItem(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/IRobotSpecItem.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/IRobotSpecItem.generated.cs new file mode 100644 index 0000000..5200f27 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/IRobotSpecItem.generated.cs @@ -0,0 +1,788 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.repository { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface IRobotSpecItem : global::java.lang.Comparable { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isValid(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getVersion(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isTeam(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isInJAR(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Z)V")] + void setValid(bool par0); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getDescription(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getAuthorName(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/net/URL;")] + global::java.net.URL getWebpage(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool getIncludeSource(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool getIncludeData(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isSourceIncluded(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getRootPath(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/net/URL;")] + global::java.net.URL getItemURL(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + bool isDevelopmentVersion(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getRobocodeVersion(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getFullPackage(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getRelativePath(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getRootPackage(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getFullClassNameWithVersion(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getUniqueFullClassName(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getUniqueFullClassNameWithVersion(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getUniqueShortClassNameWithVersion(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getUniqueVeryShortClassNameWithVersion(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getFullClassName(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Ljava/lang/String;")] + global::java.lang.String getShortClassName(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Lrobocode/control/RobotSpecification;")] + global::java.lang.Object createRobotSpecification(); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/io/OutputStream;Lnet/sf/robocode/repository/RobotProperties;)V")] + void storeProperties(global::java.io.OutputStream par0, global::java.lang.Object par1); + } + #endregion + + #region Component Designer generated code + public partial class IRobotSpecItem_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.repository.IRobotSpecItem), typeof(global::net.sf.robocode.repository.IRobotSpecItem_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.repository.IRobotSpecItem), typeof(global::net.sf.robocode.repository.IRobotSpecItem_))] + internal sealed partial class @__IRobotSpecItem : global::java.lang.Object, global::net.sf.robocode.repository.IRobotSpecItem { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_compareTo0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isValid1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getVersion2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isTeam3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isInJAR4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setValid5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getDescription6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getAuthorName7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getWebpage8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getIncludeSource9; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getIncludeData10; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isSourceIncluded11; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRootPath12; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getItemURL13; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isDevelopmentVersion14; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobocodeVersion15; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getFullPackage16; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRelativePath17; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRootPackage18; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getFullClassNameWithVersion19; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getUniqueFullClassName20; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getUniqueFullClassNameWithVersion21; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getUniqueShortClassNameWithVersion22; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getUniqueVeryShortClassNameWithVersion23; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getFullClassName24; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getShortClassName25; + + internal static global::net.sf.jni4net.jni.MethodId j4n_createRobotSpecification26; + + internal static global::net.sf.jni4net.jni.MethodId j4n_storeProperties27; + + private @__IRobotSpecItem(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass = @__class; + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_compareTo0 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "compareTo", "(Ljava/lang/Object;)I"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isValid1 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "isValid", "()Z"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getVersion2 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isTeam3 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "isTeam", "()Z"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isInJAR4 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "isInJAR", "()Z"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_setValid5 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "setValid", "(Z)V"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getDescription6 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getDescription", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getAuthorName7 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getAuthorName", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getWebpage8 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getWebpage", "()Ljava/net/URL;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getIncludeSource9 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getIncludeSource", "()Z"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getIncludeData10 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getIncludeData", "()Z"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isSourceIncluded11 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "isSourceIncluded", "()Z"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getRootPath12 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getRootPath", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getItemURL13 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getItemURL", "()Ljava/net/URL;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isDevelopmentVersion14 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "isDevelopmentVersion", "()Z"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getRobocodeVersion15 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getRobocodeVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getFullPackage16 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getFullPackage", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getRelativePath17 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getRelativePath", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getRootPackage18 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getRootPackage", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getFullClassNameWithVersion19 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getFullClassNameWithVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getUniqueFullClassName20 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getUniqueFullClassName", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getUniqueFullClassNameWithVersion21 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getUniqueFullClassNameWithVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getUniqueShortClassNameWithVersion22 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getUniqueShortClassNameWithVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getUniqueVeryShortClassNameWithVersion23 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getUniqueVeryShortClassNameWithVersion", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getFullClassName24 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getFullClassName", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getShortClassName25 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "getShortClassName", "()Ljava/lang/String;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_createRobotSpecification26 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "createRobotSpecification", "()Lrobocode/control/RobotSpecification;"); + global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_storeProperties27 = @__env.GetMethodID(global::net.sf.robocode.repository.@__IRobotSpecItem.staticClass, "storeProperties", "(Ljava/io/OutputStream;Lnet/sf/robocode/repository/RobotProperties;)V"); + } + + public int compareTo(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_compareTo0, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0)))); + } + } + + public bool isValid() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isValid1))); + } + } + + public global::java.lang.String getVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getVersion2)); + } + } + + public bool isTeam() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isTeam3))); + } + } + + public bool isInJAR() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isInJAR4))); + } + } + + public void setValid(bool par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_setValid5, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + public global::java.lang.String getDescription() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getDescription6)); + } + } + + public global::java.lang.String getAuthorName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getAuthorName7)); + } + } + + public global::java.net.URL getWebpage() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getWebpage8)); + } + } + + public bool getIncludeSource() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getIncludeSource9))); + } + } + + public bool getIncludeData() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getIncludeData10))); + } + } + + public bool isSourceIncluded() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isSourceIncluded11))); + } + } + + public global::java.lang.String getRootPath() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getRootPath12)); + } + } + + public global::java.net.URL getItemURL() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getItemURL13)); + } + } + + public bool isDevelopmentVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_isDevelopmentVersion14))); + } + } + + public global::java.lang.String getRobocodeVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getRobocodeVersion15)); + } + } + + public global::java.lang.String getFullPackage() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getFullPackage16)); + } + } + + public global::java.lang.String getRelativePath() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getRelativePath17)); + } + } + + public global::java.lang.String getRootPackage() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getRootPackage18)); + } + } + + public global::java.lang.String getFullClassNameWithVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getFullClassNameWithVersion19)); + } + } + + public global::java.lang.String getUniqueFullClassName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getUniqueFullClassName20)); + } + } + + public global::java.lang.String getUniqueFullClassNameWithVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getUniqueFullClassNameWithVersion21)); + } + } + + public global::java.lang.String getUniqueShortClassNameWithVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getUniqueShortClassNameWithVersion22)); + } + } + + public global::java.lang.String getUniqueVeryShortClassNameWithVersion() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getUniqueVeryShortClassNameWithVersion23)); + } + } + + public global::java.lang.String getFullClassName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getFullClassName24)); + } + } + + public global::java.lang.String getShortClassName() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_getShortClassName25)); + } + } + + public global::java.lang.Object createRobotSpecification() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_createRobotSpecification26)); + } + } + + public void storeProperties(global::java.io.OutputStream par0, global::java.lang.Object par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.repository.@__IRobotSpecItem.j4n_storeProperties27, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1)); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__IRobotSpecItem); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "compareTo", "compareTo0", "(Ljava/lang/Object;)I")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isValid", "isValid1", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getVersion", "getVersion2", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isTeam", "isTeam3", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isInJAR", "isInJAR4", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "setValid", "setValid5", "(Z)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getDescription", "getDescription6", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getAuthorName", "getAuthorName7", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getWebpage", "getWebpage8", "()Ljava/net/URL;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getIncludeSource", "getIncludeSource9", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getIncludeData", "getIncludeData10", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isSourceIncluded", "isSourceIncluded11", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRootPath", "getRootPath12", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getItemURL", "getItemURL13", "()Ljava/net/URL;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "isDevelopmentVersion", "isDevelopmentVersion14", "()Z")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRobocodeVersion", "getRobocodeVersion15", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getFullPackage", "getFullPackage16", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRelativePath", "getRelativePath17", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getRootPackage", "getRootPackage18", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getFullClassNameWithVersion", "getFullClassNameWithVersion19", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getUniqueFullClassName", "getUniqueFullClassName20", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getUniqueFullClassNameWithVersion", "getUniqueFullClassNameWithVersion21", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getUniqueShortClassNameWithVersion", "getUniqueShortClassNameWithVersion22", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getUniqueVeryShortClassNameWithVersion", "getUniqueVeryShortClassNameWithVersion23", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getFullClassName", "getFullClassName24", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "getShortClassName", "getShortClassName25", "()Ljava/lang/String;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "createRobotSpecification", "createRobotSpecification26", "()Lrobocode/control/RobotSpecification;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "storeProperties", "storeProperties27", "(Ljava/io/OutputStream;Lnet/sf/robocode/repository/RobotProperties;)V")); + return methods; + } + + private static int compareTo0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0) { + // (Ljava/lang/Object;)I + // (Ljava/lang/Object;)I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(((global::java.lang.Comparable)(@__real)).compareTo(global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par0)))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isValid1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isValid())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getVersion2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isTeam3(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isTeam())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isInJAR4(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isInJAR())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static void setValid5(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, bool par0) { + // (Z)V + // (Z)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.setValid(par0); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static global::net.sf.jni4net.utils.JniHandle getDescription6(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getDescription()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getAuthorName7(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getAuthorName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getWebpage8(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/net/URL; + // ()Ljava/net/URL; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getWebpage()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool getIncludeSource9(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.getIncludeSource())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool getIncludeData10(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.getIncludeData())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isSourceIncluded11(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isSourceIncluded())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRootPath12(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getRootPath()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getItemURL13(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/net/URL; + // ()Ljava/net/URL; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getItemURL()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static bool isDevelopmentVersion14(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Z + // ()Z + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + bool @__return = default(bool); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((bool)(@__real.isDevelopmentVersion())); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRobocodeVersion15(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getRobocodeVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getFullPackage16(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getFullPackage()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRelativePath17(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getRelativePath()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getRootPackage18(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getRootPackage()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getFullClassNameWithVersion19(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getFullClassNameWithVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getUniqueFullClassName20(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getUniqueFullClassName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getUniqueFullClassNameWithVersion21(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getUniqueFullClassNameWithVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getUniqueShortClassNameWithVersion22(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getUniqueShortClassNameWithVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getUniqueVeryShortClassNameWithVersion23(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getUniqueVeryShortClassNameWithVersion()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getFullClassName24(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getFullClassName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle getShortClassName25(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Ljava/lang/String; + // ()Ljava/lang/String; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.getShortClassName()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static global::net.sf.jni4net.utils.JniHandle createRobotSpecification26(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj) { + // ()Lrobocode/control/RobotSpecification; + // ()Ljava/lang/Object; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.StrongCp2J(@__real.createRobotSpecification()); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static void storeProperties27(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, global::net.sf.jni4net.utils.JniLocalHandle par1) { + // (Ljava/io/OutputStream;Lnet/sf/robocode/repository/RobotProperties;)V + // (Ljava/io/OutputStream;Ljava/lang/Object;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.repository.IRobotSpecItem @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.storeProperties(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0), global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par1)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.repository.@__IRobotSpecItem(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/RobotType.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/RobotType.generated.cs new file mode 100644 index 0000000..83b0eb4 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/repository/RobotType.generated.cs @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.repository { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RobotType : global::java.lang.Object, global::java.io.Serializable { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isValid0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isJuniorRobot1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isStandardRobot2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isAdvancedRobot3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isTeamRobot4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isDroid5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isSentryRobot6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isInteractiveRobot7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isPaintRobot8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getTypeFlags9; + + internal static global::net.sf.jni4net.jni.FieldId j4n_INVALID10; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobotType11; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRobotType12; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(ZZZZZZZZ)V")] + public RobotType(bool par0, bool par1, bool par2, bool par3, bool par4, bool par5, bool par6, bool par7) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 26)){ + @__env.NewObject(global::net.sf.robocode.repository.RobotType.staticClass, global::net.sf.robocode.repository.RobotType.j4n__ctorRobotType11, this, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par3), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par4), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par5), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par6), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par7)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(I)V")] + public RobotType(int par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::net.sf.robocode.repository.RobotType.staticClass, global::net.sf.robocode.repository.RobotType.j4n__ctorRobotType12, this, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0)); + } + } + + protected RobotType(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.repository.RobotType.staticClass; + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("Lnet/sf/robocode/repository/RobotType;")] + public static global::net.sf.robocode.repository.RobotType INVALID { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.GetStaticObjectFieldPtr(global::net.sf.robocode.repository.RobotType.staticClass, global::net.sf.robocode.repository.RobotType.j4n_INVALID10)); + } + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.repository.RobotType.staticClass = @__class; + global::net.sf.robocode.repository.RobotType.j4n_isValid0 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "isValid", "()Z"); + global::net.sf.robocode.repository.RobotType.j4n_isJuniorRobot1 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "isJuniorRobot", "()Z"); + global::net.sf.robocode.repository.RobotType.j4n_isStandardRobot2 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "isStandardRobot", "()Z"); + global::net.sf.robocode.repository.RobotType.j4n_isAdvancedRobot3 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "isAdvancedRobot", "()Z"); + global::net.sf.robocode.repository.RobotType.j4n_isTeamRobot4 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "isTeamRobot", "()Z"); + global::net.sf.robocode.repository.RobotType.j4n_isDroid5 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "isDroid", "()Z"); + global::net.sf.robocode.repository.RobotType.j4n_isSentryRobot6 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "isSentryRobot", "()Z"); + global::net.sf.robocode.repository.RobotType.j4n_isInteractiveRobot7 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "isInteractiveRobot", "()Z"); + global::net.sf.robocode.repository.RobotType.j4n_isPaintRobot8 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "isPaintRobot", "()Z"); + global::net.sf.robocode.repository.RobotType.j4n_getTypeFlags9 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "getTypeFlags", "()I"); + global::net.sf.robocode.repository.RobotType.j4n_INVALID10 = @__env.GetStaticFieldID(global::net.sf.robocode.repository.RobotType.staticClass, "INVALID", "Lnet/sf/robocode/repository/RobotType;"); + global::net.sf.robocode.repository.RobotType.j4n__ctorRobotType11 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "", "(ZZZZZZZZ)V"); + global::net.sf.robocode.repository.RobotType.j4n__ctorRobotType12 = @__env.GetMethodID(global::net.sf.robocode.repository.RobotType.staticClass, "", "(I)V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isValid() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.RobotType.j4n_isValid0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isJuniorRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.RobotType.j4n_isJuniorRobot1))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isStandardRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.RobotType.j4n_isStandardRobot2))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isAdvancedRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.RobotType.j4n_isAdvancedRobot3))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isTeamRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.RobotType.j4n_isTeamRobot4))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isDroid() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.RobotType.j4n_isDroid5))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isSentryRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.RobotType.j4n_isSentryRobot6))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isInteractiveRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.RobotType.j4n_isInteractiveRobot7))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public virtual bool isPaintRobot() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.repository.RobotType.j4n_isPaintRobot8))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()I")] + public virtual int getTypeFlags() { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.repository.RobotType.j4n_getTypeFlags9))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.repository.RobotType(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/security/HiddenAccess.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/security/HiddenAccess.generated.cs new file mode 100644 index 0000000..074fe17 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/security/HiddenAccess.generated.cs @@ -0,0 +1,293 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.security { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class HiddenAccess : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_dispatch0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_init1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_cleanup2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_update3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_initContainer4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_robocodeMain5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isCriticalEvent6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setEventTime7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setEventPriority8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setDefaultPriority9; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getSerializationType10; + + internal static global::net.sf.jni4net.jni.MethodId j4n_createSpecification11; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getFileSpecification12; + + internal static global::net.sf.jni4net.jni.MethodId j4n_getRobotTeamName13; + + internal static global::net.sf.jni4net.jni.MethodId j4n_setTeamId14; + + internal static global::net.sf.jni4net.jni.MethodId j4n_createStatus15; + + internal static global::net.sf.jni4net.jni.MethodId j4n_createRules16; + + internal static global::net.sf.jni4net.jni.MethodId j4n_isSafeThread17; + + internal static global::net.sf.jni4net.jni.MethodId j4n_initContainerForRobotEngine18; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorHiddenAccess19; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public HiddenAccess() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n__ctorHiddenAccess19, this); + } + } + + protected HiddenAccess(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.security.HiddenAccess.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.security.HiddenAccess.staticClass = @__class; + global::net.sf.robocode.security.HiddenAccess.j4n_dispatch0 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "dispatch", "(Lrobocode/Event;Lrobocode/robotinterfaces/IBasicRobot;Lnet/sf/robocode/peer/IRob" + + "otStatics;Ljava/awt/Graphics2D;)V"); + global::net.sf.robocode.security.HiddenAccess.j4n_init1 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "init", "()V"); + global::net.sf.robocode.security.HiddenAccess.j4n_cleanup2 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "cleanup", "()V"); + global::net.sf.robocode.security.HiddenAccess.j4n_update3 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "update", "(Lrobocode/Bullet;DDLjava/lang/String;Z)V"); + global::net.sf.robocode.security.HiddenAccess.j4n_initContainer4 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "initContainer", "()V"); + global::net.sf.robocode.security.HiddenAccess.j4n_robocodeMain5 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "robocodeMain", "([Ljava/lang/String;)V"); + global::net.sf.robocode.security.HiddenAccess.j4n_isCriticalEvent6 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "isCriticalEvent", "(Lrobocode/Event;)Z"); + global::net.sf.robocode.security.HiddenAccess.j4n_setEventTime7 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "setEventTime", "(Lrobocode/Event;J)V"); + global::net.sf.robocode.security.HiddenAccess.j4n_setEventPriority8 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "setEventPriority", "(Lrobocode/Event;I)V"); + global::net.sf.robocode.security.HiddenAccess.j4n_setDefaultPriority9 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "setDefaultPriority", "(Lrobocode/Event;)V"); + global::net.sf.robocode.security.HiddenAccess.j4n_getSerializationType10 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "getSerializationType", "(Lrobocode/Event;)B"); + global::net.sf.robocode.security.HiddenAccess.j4n_createSpecification11 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "createSpecification", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/la" + + "ng/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Strin" + + "g;)Lrobocode/control/RobotSpecification;"); + global::net.sf.robocode.security.HiddenAccess.j4n_getFileSpecification12 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "getFileSpecification", "(Lrobocode/control/RobotSpecification;)Ljava/lang/Object;"); + global::net.sf.robocode.security.HiddenAccess.j4n_getRobotTeamName13 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "getRobotTeamName", "(Lrobocode/control/RobotSpecification;)Ljava/lang/String;"); + global::net.sf.robocode.security.HiddenAccess.j4n_setTeamId14 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "setTeamId", "(Lrobocode/control/RobotSpecification;Ljava/lang/String;)V"); + global::net.sf.robocode.security.HiddenAccess.j4n_createStatus15 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "createStatus", "(DDDDDDDDDDDDIIIIJ)Lrobocode/RobotStatus;"); + global::net.sf.robocode.security.HiddenAccess.j4n_createRules16 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "createRules", "(IIIDJZI)Lrobocode/BattleRules;"); + global::net.sf.robocode.security.HiddenAccess.j4n_isSafeThread17 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "isSafeThread", "()Z"); + global::net.sf.robocode.security.HiddenAccess.j4n_initContainerForRobotEngine18 = @__env.GetStaticMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "initContainerForRobotEngine", "(Ljava/io/File;Lrobocode/control/events/IBattleListener;)V"); + global::net.sf.robocode.security.HiddenAccess.j4n__ctorHiddenAccess19 = @__env.GetMethodID(global::net.sf.robocode.security.HiddenAccess.staticClass, "", "()V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/Event;Lrobocode/robotinterfaces/IBasicRobot;Lnet/sf/robocode/peer/IRob" + + "otStatics;Ljava/awt/Graphics2D;)V")] + public static void dispatch(global::java.lang.Object par0, global::java.lang.Object par1, global::net.sf.robocode.peer.IRobotStatics par2, global::java.lang.Object par3) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 18)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_dispatch0, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par1), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par2), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par3)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public static void init() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_init1); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public static void cleanup() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_cleanup2); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/Bullet;DDLjava/lang/String;Z)V")] + public static void update(global::java.lang.Object par0, double par1, double par2, global::java.lang.String par3, bool par4) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 20)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_update3, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par3), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par4)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public static void initContainer() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_initContainer4); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("([Ljava/lang/String;)V")] + public static void robocodeMain(java.lang.String[] par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_robocodeMain5, global::net.sf.jni4net.utils.Convertor.ParArrayStrongCp2J(@__env, par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/Event;)Z")] + public static bool isCriticalEvent(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((bool)(@__env.CallStaticBooleanMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_isCriticalEvent6, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/Event;J)V")] + public static void setEventTime(global::java.lang.Object par0, long par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_setEventTime7, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/Event;I)V")] + public static void setEventPriority(global::java.lang.Object par0, int par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_setEventPriority8, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/Event;)V")] + public static void setDefaultPriority(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_setDefaultPriority9, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/Event;)B")] + public static byte getSerializationType(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((byte)(@__env.CallStaticByteMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_getSerializationType10, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/la" + + "ng/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Strin" + + "g;)Lrobocode/control/RobotSpecification;")] + public static global::java.lang.Object createSpecification(global::java.lang.Object par0, global::java.lang.String par1, global::java.lang.String par2, global::java.lang.String par3, global::java.lang.String par4, global::java.lang.String par5, global::java.lang.String par6, global::java.lang.String par7, global::java.lang.String par8) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 28)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_createSpecification11, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par2), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par3), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par4), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par5), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par6), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par7), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par8))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/RobotSpecification;)Ljava/lang/Object;")] + public static global::java.lang.Object getFileSpecification(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_getFileSpecification12, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/RobotSpecification;)Ljava/lang/String;")] + public static global::java.lang.String getRobotTeamName(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_getRobotTeamName13, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/control/RobotSpecification;Ljava/lang/String;)V")] + public static void setTeamId(global::java.lang.Object par0, global::java.lang.String par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_setTeamId14, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(DDDDDDDDDDDDIIIIJ)Lrobocode/RobotStatus;")] + public static global::java.lang.Object createStatus( + double par0, + double par1, + double par2, + double par3, + double par4, + double par5, + double par6, + double par7, + double par8, + double par9, + double par10, + double par11, + int par12, + int par13, + int par14, + int par15, + long par16) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 44)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_createStatus15, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par3), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par4), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par5), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par6), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par7), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par8), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par9), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par10), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par11), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par12), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par13), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par14), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par15), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par16))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(IIIDJZI)Lrobocode/BattleRules;")] + public static global::java.lang.Object createRules(int par0, int par1, int par2, double par3, long par4, bool par5, int par6) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 24)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_createRules16, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par2), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par3), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par4), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par5), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par6))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()Z")] + public static bool isSafeThread() { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((bool)(@__env.CallStaticBooleanMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_isSafeThread17))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/io/File;Lrobocode/control/events/IBattleListener;)V")] + public static void initContainerForRobotEngine(global::java.io.File par0, global::java.lang.Object par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.security.HiddenAccess.staticClass, global::net.sf.robocode.security.HiddenAccess.j4n_initContainerForRobotEngine18, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par1)); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.security.HiddenAccess(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/serialization/ISerializableHelper.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/serialization/ISerializableHelper.generated.cs new file mode 100644 index 0000000..7c4c9d8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/serialization/ISerializableHelper.generated.cs @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.serialization { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaInterfaceAttribute()] + public partial interface ISerializableHelper { + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;Ljava/lang/Obje" + + "ct;)V")] + void serialize(global::net.sf.robocode.serialization.RbSerializer par0, global::java.nio.ByteBuffer par1, global::java.lang.Object par2); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;)Ljava/lang/Obj" + + "ect;")] + global::java.lang.Object deserialize(global::net.sf.robocode.serialization.RbSerializer par0, global::java.nio.ByteBuffer par1); + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lnet/sf/robocode/serialization/RbSerializer;Ljava/lang/Object;)I")] + int sizeOf(global::net.sf.robocode.serialization.RbSerializer par0, global::java.lang.Object par1); + } + #endregion + + #region Component Designer generated code + public partial class ISerializableHelper_ { + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.serialization.@__ISerializableHelper.staticClass; + } + } + } + #endregion + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaProxyAttribute(typeof(global::net.sf.robocode.serialization.ISerializableHelper), typeof(global::net.sf.robocode.serialization.ISerializableHelper_))] + [global::net.sf.jni4net.attributes.ClrWrapperAttribute(typeof(global::net.sf.robocode.serialization.ISerializableHelper), typeof(global::net.sf.robocode.serialization.ISerializableHelper_))] + internal sealed partial class @__ISerializableHelper : global::java.lang.Object, global::net.sf.robocode.serialization.ISerializableHelper { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserialize1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_sizeOf2; + + private @__ISerializableHelper(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.serialization.@__ISerializableHelper.staticClass = @__class; + global::net.sf.robocode.serialization.@__ISerializableHelper.j4n_serialize0 = @__env.GetMethodID(global::net.sf.robocode.serialization.@__ISerializableHelper.staticClass, "serialize", "(Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;Ljava/lang/Obje" + + "ct;)V"); + global::net.sf.robocode.serialization.@__ISerializableHelper.j4n_deserialize1 = @__env.GetMethodID(global::net.sf.robocode.serialization.@__ISerializableHelper.staticClass, "deserialize", "(Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;)Ljava/lang/Obj" + + "ect;"); + global::net.sf.robocode.serialization.@__ISerializableHelper.j4n_sizeOf2 = @__env.GetMethodID(global::net.sf.robocode.serialization.@__ISerializableHelper.staticClass, "sizeOf", "(Lnet/sf/robocode/serialization/RbSerializer;Ljava/lang/Object;)I"); + } + + public void serialize(global::net.sf.robocode.serialization.RbSerializer par0, global::java.nio.ByteBuffer par1, global::java.lang.Object par2) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.@__ISerializableHelper.j4n_serialize0, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par2)); + } + } + + public global::java.lang.Object deserialize(global::net.sf.robocode.serialization.RbSerializer par0, global::java.nio.ByteBuffer par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.@__ISerializableHelper.j4n_deserialize1, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1))); + } + } + + public int sizeOf(global::net.sf.robocode.serialization.RbSerializer par0, global::java.lang.Object par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.serialization.@__ISerializableHelper.j4n_sizeOf2, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par1)))); + } + } + + private static global::System.Collections.Generic.List @__Init(global::net.sf.jni4net.jni.JNIEnv @__env, global::java.lang.Class @__class) { + global::System.Type @__type = typeof(__ISerializableHelper); + global::System.Collections.Generic.List methods = new global::System.Collections.Generic.List(); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "serialize", "serialize0", "(Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;Ljava/lang/Obje" + + "ct;)V")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "deserialize", "deserialize1", "(Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;)Ljava/lang/Obj" + + "ect;")); + methods.Add(global::net.sf.jni4net.jni.JNINativeMethod.Create(@__type, "sizeOf", "sizeOf2", "(Lnet/sf/robocode/serialization/RbSerializer;Ljava/lang/Object;)I")); + return methods; + } + + private static void serialize0(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, global::net.sf.jni4net.utils.JniLocalHandle par1, global::net.sf.jni4net.utils.JniLocalHandle par2) { + // (Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;Ljava/lang/Object;)V + // (Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;Ljava/lang/Object;)V + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + try { + global::net.sf.robocode.serialization.ISerializableHelper @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__real.serialize(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0), global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par1), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par2)); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + } + + private static global::net.sf.jni4net.utils.JniHandle deserialize1(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, global::net.sf.jni4net.utils.JniLocalHandle par1) { + // (Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;)Ljava/lang/Object; + // (Lnet/sf/robocode/serialization/RbSerializer;Ljava/nio/ByteBuffer;)Ljava/lang/Object; + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + global::net.sf.jni4net.utils.JniHandle @__return = default(global::net.sf.jni4net.utils.JniHandle); + try { + global::net.sf.robocode.serialization.ISerializableHelper @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = global::net.sf.jni4net.utils.Convertor.FullC2J(@__env, @__real.deserialize(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0), global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par1))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + private static int sizeOf2(global::System.IntPtr @__envp, global::net.sf.jni4net.utils.JniLocalHandle @__obj, global::net.sf.jni4net.utils.JniLocalHandle par0, global::net.sf.jni4net.utils.JniLocalHandle par1) { + // (Lnet/sf/robocode/serialization/RbSerializer;Ljava/lang/Object;)I + // (Lnet/sf/robocode/serialization/RbSerializer;Ljava/lang/Object;)I + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.Wrap(@__envp); + int @__return = default(int); + try { + global::net.sf.robocode.serialization.ISerializableHelper @__real = global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__obj); + @__return = ((int)(@__real.sizeOf(global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, par0), global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, par1)))); + }catch (global::System.Exception __ex){@__env.ThrowExisting(__ex);} + return @__return; + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.serialization.@__ISerializableHelper(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/serialization/RbSerializer.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/serialization/RbSerializer.generated.cs new file mode 100644 index 0000000..aa01b31 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/net/sf/robocode/serialization/RbSerializer.generated.cs @@ -0,0 +1,1036 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace net.sf.robocode.serialization { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + public partial class RbSerializer : global::java.lang.Object { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n_register0; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize1; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize2; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize3; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize4; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize5; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize6; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize7; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize8; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize9; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize10; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize11; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize12; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize13; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize14; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serialize15; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serializeToBuffer16; + + internal static global::net.sf.jni4net.jni.MethodId j4n_serializeToBuffer17; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserialize18; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserialize19; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeAny20; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeString21; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeBytes22; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeIntegers23; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeFloats24; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeChars25; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeDoubles26; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeBoolean27; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeChar28; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeInt29; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeFloat30; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeDouble31; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeLong32; + + internal static global::net.sf.jni4net.jni.MethodId j4n_sizeOf33; + + internal static global::net.sf.jni4net.jni.MethodId j4n_sizeOf34; + + internal static global::net.sf.jni4net.jni.MethodId j4n_sizeOf35; + + internal static global::net.sf.jni4net.jni.MethodId j4n_sizeOf36; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deserializeFromBuffer37; + + internal static global::net.sf.jni4net.jni.MethodId j4n_deepCopy38; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SIZEOF_TYPEINFO39; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SIZEOF_BYTE40; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SIZEOF_BOOL41; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SIZEOF_CHAR42; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SIZEOF_INT43; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SIZEOF_LONG44; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SIZEOF_DOUBLE45; + + internal static global::net.sf.jni4net.jni.FieldId j4n_TERMINATOR_TYPE46; + + internal static global::net.sf.jni4net.jni.FieldId j4n_ExecCommands_TYPE47; + + internal static global::net.sf.jni4net.jni.FieldId j4n_BulletCommand_TYPE48; + + internal static global::net.sf.jni4net.jni.FieldId j4n_TeamMessage_TYPE49; + + internal static global::net.sf.jni4net.jni.FieldId j4n_DebugProperty_TYPE50; + + internal static global::net.sf.jni4net.jni.FieldId j4n_ExecResults_TYPE51; + + internal static global::net.sf.jni4net.jni.FieldId j4n_RobotStatus_TYPE52; + + internal static global::net.sf.jni4net.jni.FieldId j4n_BulletStatus_TYPE53; + + internal static global::net.sf.jni4net.jni.FieldId j4n_BattleResults_TYPE54; + + internal static global::net.sf.jni4net.jni.FieldId j4n_Bullet_TYPE55; + + internal static global::net.sf.jni4net.jni.FieldId j4n_RobotStatics_TYPE56; + + internal static global::net.sf.jni4net.jni.FieldId j4n_BattleEndedEvent_TYPE57; + + internal static global::net.sf.jni4net.jni.FieldId j4n_BulletHitBulletEvent_TYPE58; + + internal static global::net.sf.jni4net.jni.FieldId j4n_BulletHitEvent_TYPE59; + + internal static global::net.sf.jni4net.jni.FieldId j4n_BulletMissedEvent_TYPE60; + + internal static global::net.sf.jni4net.jni.FieldId j4n_DeathEvent_TYPE61; + + internal static global::net.sf.jni4net.jni.FieldId j4n_WinEvent_TYPE62; + + internal static global::net.sf.jni4net.jni.FieldId j4n_HitWallEvent_TYPE63; + + internal static global::net.sf.jni4net.jni.FieldId j4n_RobotDeathEvent_TYPE64; + + internal static global::net.sf.jni4net.jni.FieldId j4n_SkippedTurnEvent_TYPE65; + + internal static global::net.sf.jni4net.jni.FieldId j4n_ScannedRobotEvent_TYPE66; + + internal static global::net.sf.jni4net.jni.FieldId j4n_HitByBulletEvent_TYPE67; + + internal static global::net.sf.jni4net.jni.FieldId j4n_HitRobotEvent_TYPE68; + + internal static global::net.sf.jni4net.jni.FieldId j4n_KeyPressedEvent_TYPE69; + + internal static global::net.sf.jni4net.jni.FieldId j4n_KeyReleasedEvent_TYPE70; + + internal static global::net.sf.jni4net.jni.FieldId j4n_KeyTypedEvent_TYPE71; + + internal static global::net.sf.jni4net.jni.FieldId j4n_MouseClickedEvent_TYPE72; + + internal static global::net.sf.jni4net.jni.FieldId j4n_MouseDraggedEvent_TYPE73; + + internal static global::net.sf.jni4net.jni.FieldId j4n_MouseEnteredEvent_TYPE74; + + internal static global::net.sf.jni4net.jni.FieldId j4n_MouseExitedEvent_TYPE75; + + internal static global::net.sf.jni4net.jni.FieldId j4n_MouseMovedEvent_TYPE76; + + internal static global::net.sf.jni4net.jni.FieldId j4n_MousePressedEvent_TYPE77; + + internal static global::net.sf.jni4net.jni.FieldId j4n_MouseReleasedEvent_TYPE78; + + internal static global::net.sf.jni4net.jni.FieldId j4n_MouseWheelMovedEvent_TYPE79; + + internal static global::net.sf.jni4net.jni.FieldId j4n_RoundEndedEvent_TYPE80; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorRbSerializer81; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public RbSerializer() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n__ctorRbSerializer81, this); + } + } + + protected RbSerializer(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + public static global::java.lang.Class _class { + get { + return global::net.sf.robocode.serialization.RbSerializer.staticClass; + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("I")] + public static int SIZEOF_TYPEINFO { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.GetStaticIntField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_TYPEINFO39))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("I")] + public static int SIZEOF_BYTE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.GetStaticIntField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_BYTE40))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("I")] + public static int SIZEOF_BOOL { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.GetStaticIntField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_BOOL41))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("I")] + public static int SIZEOF_CHAR { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.GetStaticIntField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_CHAR42))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("I")] + public static int SIZEOF_INT { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.GetStaticIntField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_INT43))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("I")] + public static int SIZEOF_LONG { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.GetStaticIntField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_LONG44))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("I")] + public static int SIZEOF_DOUBLE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((int)(@__env.GetStaticIntField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_DOUBLE45))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte TERMINATOR_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_TERMINATOR_TYPE46))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte ExecCommands_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_ExecCommands_TYPE47))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte BulletCommand_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_BulletCommand_TYPE48))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte TeamMessage_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_TeamMessage_TYPE49))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte DebugProperty_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_DebugProperty_TYPE50))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte ExecResults_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_ExecResults_TYPE51))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte RobotStatus_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_RobotStatus_TYPE52))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte BulletStatus_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_BulletStatus_TYPE53))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte BattleResults_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_BattleResults_TYPE54))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte Bullet_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_Bullet_TYPE55))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte RobotStatics_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_RobotStatics_TYPE56))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte BattleEndedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_BattleEndedEvent_TYPE57))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte BulletHitBulletEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_BulletHitBulletEvent_TYPE58))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte BulletHitEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_BulletHitEvent_TYPE59))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte BulletMissedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_BulletMissedEvent_TYPE60))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte DeathEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_DeathEvent_TYPE61))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte WinEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_WinEvent_TYPE62))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte HitWallEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_HitWallEvent_TYPE63))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte RobotDeathEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_RobotDeathEvent_TYPE64))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte SkippedTurnEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_SkippedTurnEvent_TYPE65))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte ScannedRobotEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_ScannedRobotEvent_TYPE66))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte HitByBulletEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_HitByBulletEvent_TYPE67))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte HitRobotEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_HitRobotEvent_TYPE68))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte KeyPressedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_KeyPressedEvent_TYPE69))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte KeyReleasedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_KeyReleasedEvent_TYPE70))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte KeyTypedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_KeyTypedEvent_TYPE71))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte MouseClickedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_MouseClickedEvent_TYPE72))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte MouseDraggedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_MouseDraggedEvent_TYPE73))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte MouseEnteredEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_MouseEnteredEvent_TYPE74))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte MouseExitedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_MouseExitedEvent_TYPE75))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte MouseMovedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_MouseMovedEvent_TYPE76))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte MousePressedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_MousePressedEvent_TYPE77))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte MouseReleasedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_MouseReleasedEvent_TYPE78))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte MouseWheelMovedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_MouseWheelMovedEvent_TYPE79))); + } + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("B")] + public static byte RoundEndedEvent_TYPE { + get { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + return ((byte)(@__env.GetStaticByteField(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_RoundEndedEvent_TYPE80))); + } + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::net.sf.robocode.serialization.RbSerializer.staticClass = @__class; + global::net.sf.robocode.serialization.RbSerializer.j4n_register0 = @__env.GetStaticMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "register", "(Ljava/lang/Class;B)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize1 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/io/OutputStream;BLjava/lang/Object;)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize2 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;Lrobocode/Event;)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize3 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;BLjava/lang/Object;)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize4 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;Ljava/lang/String;)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize5 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;[B)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize6 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;[I)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize7 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;[C)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize8 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;[D)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize9 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;[F)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize10 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;Z)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize11 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;D)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize12 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;C)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize13 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;J)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize14 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(Ljava/nio/ByteBuffer;I)V"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serialize15 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serialize", "(BLjava/lang/Object;)Ljava/nio/ByteBuffer;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serializeToBuffer16 = @__env.GetStaticMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serializeToBuffer", "(Ljava/lang/Object;)Ljava/nio/ByteBuffer;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_serializeToBuffer17 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "serializeToBuffer", "(Ljava/nio/ByteBuffer;BLjava/lang/Object;)Ljava/nio/ByteBuffer;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserialize18 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserialize", "(Ljava/io/InputStream;)Ljava/lang/Object;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserialize19 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserialize", "(Ljava/nio/ByteBuffer;)Ljava/lang/Object;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeAny20 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeAny", "(Ljava/nio/ByteBuffer;)Ljava/lang/Object;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeString21 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeString", "(Ljava/nio/ByteBuffer;)Ljava/lang/String;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeBytes22 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeBytes", "(Ljava/nio/ByteBuffer;)[B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeIntegers23 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeIntegers", "(Ljava/nio/ByteBuffer;)[I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeFloats24 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeFloats", "(Ljava/nio/ByteBuffer;)[F"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeChars25 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeChars", "(Ljava/nio/ByteBuffer;)[C"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeDoubles26 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeDoubles", "(Ljava/nio/ByteBuffer;)[D"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeBoolean27 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeBoolean", "(Ljava/nio/ByteBuffer;)Z"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeChar28 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeChar", "(Ljava/nio/ByteBuffer;)C"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeInt29 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeInt", "(Ljava/nio/ByteBuffer;)I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeFloat30 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeFloat", "(Ljava/nio/ByteBuffer;)Ljava/lang/Float;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeDouble31 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeDouble", "(Ljava/nio/ByteBuffer;)D"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeLong32 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeLong", "(Ljava/nio/ByteBuffer;)J"); + global::net.sf.robocode.serialization.RbSerializer.j4n_sizeOf33 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "sizeOf", "(BLjava/lang/Object;)I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_sizeOf34 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "sizeOf", "(Lrobocode/Event;)I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_sizeOf35 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "sizeOf", "([B)I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_sizeOf36 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "sizeOf", "(Ljava/lang/String;)I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeFromBuffer37 = @__env.GetStaticMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deserializeFromBuffer", "(Ljava/nio/ByteBuffer;)Ljava/lang/Object;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_deepCopy38 = @__env.GetStaticMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "deepCopy", "(BLjava/lang/Object;)Ljava/lang/Object;"); + global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_TYPEINFO39 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "SIZEOF_TYPEINFO", "I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_BYTE40 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "SIZEOF_BYTE", "I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_BOOL41 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "SIZEOF_BOOL", "I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_CHAR42 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "SIZEOF_CHAR", "I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_INT43 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "SIZEOF_INT", "I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_LONG44 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "SIZEOF_LONG", "I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_SIZEOF_DOUBLE45 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "SIZEOF_DOUBLE", "I"); + global::net.sf.robocode.serialization.RbSerializer.j4n_TERMINATOR_TYPE46 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "TERMINATOR_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_ExecCommands_TYPE47 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "ExecCommands_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_BulletCommand_TYPE48 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "BulletCommand_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_TeamMessage_TYPE49 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "TeamMessage_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_DebugProperty_TYPE50 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "DebugProperty_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_ExecResults_TYPE51 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "ExecResults_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_RobotStatus_TYPE52 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "RobotStatus_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_BulletStatus_TYPE53 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "BulletStatus_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_BattleResults_TYPE54 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "BattleResults_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_Bullet_TYPE55 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "Bullet_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_RobotStatics_TYPE56 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "RobotStatics_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_BattleEndedEvent_TYPE57 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "BattleEndedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_BulletHitBulletEvent_TYPE58 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "BulletHitBulletEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_BulletHitEvent_TYPE59 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "BulletHitEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_BulletMissedEvent_TYPE60 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "BulletMissedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_DeathEvent_TYPE61 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "DeathEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_WinEvent_TYPE62 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "WinEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_HitWallEvent_TYPE63 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "HitWallEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_RobotDeathEvent_TYPE64 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "RobotDeathEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_SkippedTurnEvent_TYPE65 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "SkippedTurnEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_ScannedRobotEvent_TYPE66 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "ScannedRobotEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_HitByBulletEvent_TYPE67 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "HitByBulletEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_HitRobotEvent_TYPE68 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "HitRobotEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_KeyPressedEvent_TYPE69 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "KeyPressedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_KeyReleasedEvent_TYPE70 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "KeyReleasedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_KeyTypedEvent_TYPE71 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "KeyTypedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_MouseClickedEvent_TYPE72 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "MouseClickedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_MouseDraggedEvent_TYPE73 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "MouseDraggedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_MouseEnteredEvent_TYPE74 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "MouseEnteredEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_MouseExitedEvent_TYPE75 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "MouseExitedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_MouseMovedEvent_TYPE76 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "MouseMovedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_MousePressedEvent_TYPE77 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "MousePressedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_MouseReleasedEvent_TYPE78 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "MouseReleasedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_MouseWheelMovedEvent_TYPE79 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "MouseWheelMovedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n_RoundEndedEvent_TYPE80 = @__env.GetStaticFieldID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "RoundEndedEvent_TYPE", "B"); + global::net.sf.robocode.serialization.RbSerializer.j4n__ctorRbSerializer81 = @__env.GetMethodID(global::net.sf.robocode.serialization.RbSerializer.staticClass, "", "()V"); + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/Class;B)V")] + public static void register(global::java.lang.Class par0, byte par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallStaticVoidMethod(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_register0, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/io/OutputStream;BLjava/lang/Object;)V")] + public virtual void serialize(global::java.io.OutputStream par0, byte par1, global::java.lang.Object par2) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize1, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par2)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;Lrobocode/Event;)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, global::java.lang.Object par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize2, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;BLjava/lang/Object;)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, byte par1, global::java.lang.Object par2) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize3, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par2)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;Ljava/lang/String;)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, global::java.lang.String par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize4, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;[B)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, byte[] par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize5, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParArrayPrimC2J(@__env, par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;[I)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, int[] par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize6, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParArrayPrimC2J(@__env, par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;[C)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, char[] par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize7, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParArrayPrimC2J(@__env, par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;[D)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, double[] par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize8, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParArrayPrimC2J(@__env, par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;[F)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, float[] par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize9, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParArrayPrimC2J(@__env, par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;Z)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, bool par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize10, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;D)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, double par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize11, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;C)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, char par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize12, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;J)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, long par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize13, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;I)V")] + public virtual void serialize(global::java.nio.ByteBuffer par0, int par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + @__env.CallVoidMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize14, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1)); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(BLjava/lang/Object;)Ljava/nio/ByteBuffer;")] + public virtual global::java.nio.ByteBuffer serialize(byte par0, global::java.lang.Object par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serialize15, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par1))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/Object;)Ljava/nio/ByteBuffer;")] + public static global::java.nio.ByteBuffer serializeToBuffer(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_serializeToBuffer16, global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;BLjava/lang/Object;)Ljava/nio/ByteBuffer;")] + public virtual global::java.nio.ByteBuffer serializeToBuffer(global::java.nio.ByteBuffer par0, byte par1, global::java.lang.Object par2) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 16)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_serializeToBuffer17, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0), global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par1), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par2))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/io/InputStream;)Ljava/lang/Object;")] + public virtual global::java.lang.Object deserialize(global::java.io.InputStream par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserialize18, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)Ljava/lang/Object;")] + public virtual global::java.lang.Object deserialize(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserialize19, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)Ljava/lang/Object;")] + public virtual global::java.lang.Object deserializeAny(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeAny20, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)Ljava/lang/String;")] + public virtual global::java.lang.String deserializeString(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2CpString(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeString21, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)[B")] + public virtual byte[] deserializeBytes(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.ArrayPrimJ2Cbyte(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeBytes22, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)[I")] + public virtual int[] deserializeIntegers(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.ArrayPrimJ2Cint(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeIntegers23, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)[F")] + public virtual float[] deserializeFloats(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.ArrayPrimJ2Cfloat(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeFloats24, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)[C")] + public virtual char[] deserializeChars(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.ArrayPrimJ2Cchar(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeChars25, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)[D")] + public virtual double[] deserializeDoubles(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.ArrayPrimJ2Cdouble(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeDoubles26, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)Z")] + public virtual bool deserializeBoolean(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((bool)(@__env.CallBooleanMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeBoolean27, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)C")] + public virtual char deserializeChar(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((char)(@__env.CallCharMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeChar28, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)I")] + public virtual int deserializeInt(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeInt29, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)Ljava/lang/Float;")] + public virtual global::java.lang.Float deserializeFloat(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.StrongJ2Cp(@__env, @__env.CallObjectMethodPtr(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeFloat30, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)D")] + public virtual double deserializeDouble(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((double)(@__env.CallDoubleMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeDouble31, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)J")] + public virtual long deserializeLong(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((long)(@__env.CallLongMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeLong32, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(BLjava/lang/Object;)I")] + public virtual int sizeOf(byte par0, global::java.lang.Object par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_sizeOf33, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par1)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Lrobocode/Event;)I")] + public virtual int sizeOf(global::java.lang.Object par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_sizeOf34, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("([B)I")] + public virtual int sizeOf(byte[] par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_sizeOf35, global::net.sf.jni4net.utils.Convertor.ParArrayPrimC2J(@__env, par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)I")] + public virtual int sizeOf(global::java.lang.String par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = this.Env; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return ((int)(@__env.CallIntMethod(this, global::net.sf.robocode.serialization.RbSerializer.j4n_sizeOf36, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/nio/ByteBuffer;)Ljava/lang/Object;")] + public static global::java.lang.Object deserializeFromBuffer(global::java.nio.ByteBuffer par0) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_deserializeFromBuffer37, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0))); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(BLjava/lang/Object;)Ljava/lang/Object;")] + public static global::java.lang.Object deepCopy(byte par0, global::java.lang.Object par1) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 14)){ + return global::net.sf.jni4net.utils.Convertor.FullJ2C(@__env, @__env.CallStaticObjectMethodPtr(global::net.sf.robocode.serialization.RbSerializer.staticClass, global::net.sf.robocode.serialization.RbSerializer.j4n_deepCopy38, global::net.sf.jni4net.utils.Convertor.ParPrimC2J(par0), global::net.sf.jni4net.utils.Convertor.ParFullC2J(@__env, par1))); + } + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::net.sf.robocode.serialization.RbSerializer(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/AbortedException.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/AbortedException.generated.cs new file mode 100644 index 0000000..7143de0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/AbortedException.generated.cs @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.exception { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + [global::System.SerializableAttribute()] + public partial class AbortedException : global::java.lang.Error { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorAbortedException0; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorAbortedException1; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public AbortedException() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.exception.AbortedException.staticClass, global::robocode.exception.AbortedException.j4n__ctorAbortedException0, this); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public AbortedException(global::java.lang.String par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.exception.AbortedException.staticClass, global::robocode.exception.AbortedException.j4n__ctorAbortedException1, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + protected AbortedException(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + protected AbortedException(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : + base(info, context) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.exception.AbortedException.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.exception.AbortedException.staticClass = @__class; + global::robocode.exception.AbortedException.j4n__ctorAbortedException0 = @__env.GetMethodID(global::robocode.exception.AbortedException.staticClass, "", "()V"); + global::robocode.exception.AbortedException.j4n__ctorAbortedException1 = @__env.GetMethodID(global::robocode.exception.AbortedException.staticClass, "", "(Ljava/lang/String;)V"); + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.exception.AbortedException(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/DeathException.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/DeathException.generated.cs new file mode 100644 index 0000000..7b57751 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/DeathException.generated.cs @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.exception { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + [global::System.SerializableAttribute()] + public partial class DeathException : global::java.lang.Error { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorDeathException0; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorDeathException1; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public DeathException() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.exception.DeathException.staticClass, global::robocode.exception.DeathException.j4n__ctorDeathException0, this); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public DeathException(global::java.lang.String par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.exception.DeathException.staticClass, global::robocode.exception.DeathException.j4n__ctorDeathException1, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + protected DeathException(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + protected DeathException(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : + base(info, context) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.exception.DeathException.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.exception.DeathException.staticClass = @__class; + global::robocode.exception.DeathException.j4n__ctorDeathException0 = @__env.GetMethodID(global::robocode.exception.DeathException.staticClass, "", "()V"); + global::robocode.exception.DeathException.j4n__ctorDeathException1 = @__env.GetMethodID(global::robocode.exception.DeathException.staticClass, "", "(Ljava/lang/String;)V"); + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.exception.DeathException(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/DisabledException.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/DisabledException.generated.cs new file mode 100644 index 0000000..4672eed --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/DisabledException.generated.cs @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.exception { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + [global::System.SerializableAttribute()] + public partial class DisabledException : global::java.lang.Error { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorDisabledException0; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorDisabledException1; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public DisabledException() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.exception.DisabledException.staticClass, global::robocode.exception.DisabledException.j4n__ctorDisabledException0, this); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public DisabledException(global::java.lang.String par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.exception.DisabledException.staticClass, global::robocode.exception.DisabledException.j4n__ctorDisabledException1, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + protected DisabledException(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + protected DisabledException(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : + base(info, context) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.exception.DisabledException.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.exception.DisabledException.staticClass = @__class; + global::robocode.exception.DisabledException.j4n__ctorDisabledException0 = @__env.GetMethodID(global::robocode.exception.DisabledException.staticClass, "", "()V"); + global::robocode.exception.DisabledException.j4n__ctorDisabledException1 = @__env.GetMethodID(global::robocode.exception.DisabledException.staticClass, "", "(Ljava/lang/String;)V"); + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.exception.DisabledException(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/WinException.generated.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/WinException.generated.cs new file mode 100644 index 0000000..2787601 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/generated/robocode/exception/WinException.generated.cs @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +//------------------------------------------------------------------------------ +// +// This code was generated by jni4net. See http://jni4net.sourceforge.net/ +// Runtime Version:2.0.50727.8669 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace robocode.exception { + + + #region Component Designer generated code + [global::net.sf.jni4net.attributes.JavaClassAttribute()] + [global::System.SerializableAttribute()] + public partial class WinException : global::java.lang.Error { + + internal new static global::java.lang.Class staticClass; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorWinException0; + + internal static global::net.sf.jni4net.jni.MethodId j4n__ctorWinException1; + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("()V")] + public WinException() : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 10)){ + @__env.NewObject(global::robocode.exception.WinException.staticClass, global::robocode.exception.WinException.j4n__ctorWinException0, this); + } + } + + [global::net.sf.jni4net.attributes.JavaMethodAttribute("(Ljava/lang/String;)V")] + public WinException(global::java.lang.String par0) : + base(((global::net.sf.jni4net.jni.JNIEnv)(null))) { + global::net.sf.jni4net.jni.JNIEnv @__env = global::net.sf.jni4net.jni.JNIEnv.ThreadEnv; + using(new global::net.sf.jni4net.jni.LocalFrame(@__env, 12)){ + @__env.NewObject(global::robocode.exception.WinException.staticClass, global::robocode.exception.WinException.j4n__ctorWinException1, this, global::net.sf.jni4net.utils.Convertor.ParStrongCp2J(par0)); + } + } + + protected WinException(global::net.sf.jni4net.jni.JNIEnv @__env) : + base(@__env) { + } + + protected WinException(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : + base(info, context) { + } + + public static global::java.lang.Class _class { + get { + return global::robocode.exception.WinException.staticClass; + } + } + + private static void InitJNI(global::net.sf.jni4net.jni.JNIEnv @__env, java.lang.Class @__class) { + global::robocode.exception.WinException.staticClass = @__class; + global::robocode.exception.WinException.j4n__ctorWinException0 = @__env.GetMethodID(global::robocode.exception.WinException.staticClass, "", "()V"); + global::robocode.exception.WinException.j4n__ctorWinException1 = @__env.GetMethodID(global::robocode.exception.WinException.staticClass, "", "(Ljava/lang/String;)V"); + } + + new internal sealed class ContructionHelper : global::net.sf.jni4net.utils.IConstructionHelper { + + public global::net.sf.jni4net.jni.IJvmProxy CreateProxy(global::net.sf.jni4net.jni.JNIEnv @__env) { + return new global::robocode.exception.WinException(@__env); + } + } + } + #endregion +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/DotNetHost.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/DotNetHost.cs new file mode 100644 index 0000000..befcc51 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/DotNetHost.cs @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.IO; +using net.sf.jni4net; +using net.sf.robocode.dotnet.host.seed; +using net.sf.robocode.dotnet.repository.root; +using net.sf.robocode.host; +using net.sf.robocode.host.proxies; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using net.sf.robocode.security; +using robocode.control; +using Object = java.lang.Object; +using String = java.lang.String; + +namespace net.sf.robocode.dotnet.host +{ + public class DotNetHost : IHost + { + #region IHost Members + + public IHostingRobotProxy createRobotProxy(IHostManager hostManager, Object robotSpecification, IRobotStatics statics, IRobotPeer peer) + { + Object s = HiddenAccess.getFileSpecification(robotSpecification); + var itemSpecification = Bridge.Cast(s); + string file = DllRootHelper.GetDllFileName(itemSpecification); + HostingShell hostingShell = new HostingShell(itemSpecification, hostManager, peer, statics, file); + return hostingShell; + } + + public String[] getReferencedClasses(IRobotItem robotItem) + { + return new String[] {}; + } + + public RobotType getRobotType(IRobotItem robotItem, bool resolve, bool message) + { + return DllRootHelper.GetRobotType(robotItem); + } + + #endregion + + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/ModuleN.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/ModuleN.cs new file mode 100644 index 0000000..af2dc39 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/ModuleN.cs @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Globalization; +using System.Windows.Forms; +using net.sf.jni4net; +using net.sf.robocode.core; +using net.sf.robocode.dotnet.peer; +using net.sf.robocode.host; +using net.sf.robocode.io; +using net.sf.robocode.manager; +using net.sf.robocode.security; +using net.sf.robocode.serialization; +using Robocode; +using robocode.control; + +namespace net.sf.robocode.dotnet.nhost +{ + public class ModuleN + { + public static void InitN() + { + System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; + System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; + HiddenAccessN.init(); + LoggerN.IsSafeThread = true; + LoggerN.setLogListener(new Logger(true)); + HiddenAccessN.randomHelper = new RandomFactory(true); + + var versionManager = + Bridge.Cast(ContainerBase.getComponent(IVersionManagerBase_._class)); + int currentVersion = versionManager.getVersionAsInt(); + RbSerializer.Init(currentVersion); + RbSerializerN.Init(currentVersion); + + RbSerializerN.register(typeof (RobotStatus), RbSerializerN.RobotStatus_TYPE); + RbSerializerN.register(typeof (BattleResults), RbSerializerN.BattleResults_TYPE); + RbSerializerN.register(typeof (Bullet), RbSerializerN.Bullet_TYPE); + RbSerializerN.register(typeof (RobotStatics), RbSerializerN.RobotStatics_TYPE); + + // events + RbSerializerN.register(typeof (RoundEndedEvent), RbSerializerN.RoundEndedEvent_TYPE); + RbSerializerN.register(typeof (BattleEndedEvent), RbSerializerN.BattleEndedEvent_TYPE); + RbSerializerN.register(typeof (BulletHitBulletEvent), RbSerializerN.BulletHitBulletEvent_TYPE); + RbSerializerN.register(typeof (BulletHitEvent), RbSerializerN.BulletHitEvent_TYPE); + RbSerializerN.register(typeof (BulletMissedEvent), RbSerializerN.BulletMissedEvent_TYPE); + RbSerializerN.register(typeof (DeathEvent), RbSerializerN.DeathEvent_TYPE); + RbSerializerN.register(typeof (WinEvent), RbSerializerN.WinEvent_TYPE); + RbSerializerN.register(typeof (HitWallEvent), RbSerializerN.HitWallEvent_TYPE); + RbSerializerN.register(typeof (RobotDeathEvent), RbSerializerN.RobotDeathEvent_TYPE); + RbSerializerN.register(typeof (SkippedTurnEvent), RbSerializerN.SkippedTurnEvent_TYPE); + RbSerializerN.register(typeof (ScannedRobotEvent), RbSerializerN.ScannedRobotEvent_TYPE); + RbSerializerN.register(typeof (HitByBulletEvent), RbSerializerN.HitByBulletEvent_TYPE); + RbSerializerN.register(typeof (HitRobotEvent), RbSerializerN.HitRobotEvent_TYPE); + RbSerializerN.register(typeof (KeyPressedEvent), RbSerializerN.KeyPressedEvent_TYPE); + RbSerializerN.register(typeof (KeyReleasedEvent), RbSerializerN.KeyReleasedEvent_TYPE); + RbSerializerN.register(typeof (KeyTypedEvent), RbSerializerN.KeyTypedEvent_TYPE); + RbSerializerN.register(typeof (MouseClickedEvent), RbSerializerN.MouseClickedEvent_TYPE); + RbSerializerN.register(typeof (MouseDraggedEvent), RbSerializerN.MouseDraggedEvent_TYPE); + RbSerializerN.register(typeof (MouseEnteredEvent), RbSerializerN.MouseEnteredEvent_TYPE); + RbSerializerN.register(typeof (MouseExitedEvent), RbSerializerN.MouseExitedEvent_TYPE); + RbSerializerN.register(typeof (MouseMovedEvent), RbSerializerN.MouseMovedEvent_TYPE); + RbSerializerN.register(typeof (MousePressedEvent), RbSerializerN.MousePressedEvent_TYPE); + RbSerializerN.register(typeof (MouseReleasedEvent), RbSerializerN.MouseReleasedEvent_TYPE); + RbSerializerN.register(typeof (MouseWheelMovedEvent), RbSerializerN.MouseWheelMovedEvent_TYPE); + + RbSerializerN.register(typeof (ExecCommands), RbSerializerN.ExecCommands_TYPE); + RbSerializerN.register(typeof (BulletCommand), RbSerializerN.BulletCommand_TYPE); + RbSerializerN.register(typeof (TeamMessage), RbSerializerN.TeamMessage_TYPE); + RbSerializerN.register(typeof (DebugProperty), RbSerializerN.DebugProperty_TYPE); + RbSerializerN.register(typeof (ExecResults), RbSerializerN.ExecResults_TYPE); + RbSerializerN.register(typeof (BulletStatus), RbSerializerN.BulletStatus_TYPE); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/RobotStatics.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/RobotStatics.cs new file mode 100644 index 0000000..9267e4f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/RobotStatics.cs @@ -0,0 +1,312 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using net.sf.robocode.nio; +using net.sf.robocode.peer; +using net.sf.robocode.security; +using net.sf.robocode.serialization; +using Robocode; + +namespace net.sf.robocode.host +{ + [Serializable] + public class RobotStatics : IRobotStaticsN + { + private readonly string robocodeVersion; + private readonly BattleRules battleRules; + private readonly int contestantIndex; + private readonly string fullClassName; + private readonly int index; + private readonly bool isJuniorRobot; + private readonly bool isAdvancedRobot; + private readonly bool isTeamRobot; + private readonly bool isDroid; + private readonly bool isSentryRobot; + private readonly bool isInteractiveRobot; + private readonly bool isPaintRobot; + private readonly bool isTeamLeader; + private readonly string name; + private readonly string shortClassName; + private readonly string shortName; + private readonly string teamName; + private readonly string[] teammates; + private readonly string veryShortName; + + public RobotStatics(string robocodeVersion, bool isJuniorRobot, bool isInteractiveRobot, bool isPaintRobot, bool isAdvancedRobot, + bool isTeamRobot, bool isTeamLeader, bool isDroid, bool isSentryRobot, string name, string shortName, + string veryShortName, string fullClassName, string shortClassName, BattleRules battleRules, + string[] teammates, string teamName, int index, int contestantIndex) + { + this.robocodeVersion = robocodeVersion; + this.isJuniorRobot = isJuniorRobot; + this.isAdvancedRobot = isAdvancedRobot; + this.isTeamRobot = isTeamRobot; + this.isDroid = isDroid; + this.isSentryRobot = isSentryRobot; + this.isInteractiveRobot = isInteractiveRobot; + this.isPaintRobot = isPaintRobot; + this.isTeamLeader = isTeamLeader; + this.name = name; + this.shortName = shortName; + this.veryShortName = veryShortName; + this.fullClassName = fullClassName; + this.shortClassName = shortClassName; + this.battleRules = battleRules; + this.teammates = teammates; + this.teamName = teamName; + this.index = index; + this.contestantIndex = contestantIndex; + } + + #region IRobotStaticsN Members + + public bool IsInteractiveRobot() + { + return isInteractiveRobot; + } + + public bool IsPaintRobot() + { + return isPaintRobot; + } + + public bool IsAdvancedRobot() + { + return isAdvancedRobot; + } + + public bool IsTeamRobot() + { + return isTeamRobot; + } + + #endregion + + public string getRobocodeVersion() + { + return robocodeVersion; + } + + public bool IsJuniorRobot() + { + return isJuniorRobot; + } + + public bool IsDroid() + { + return isDroid; + } + + public bool IsTeamLeader() + { + return isTeamLeader; + } + + public string getName() + { + return name; + } + + public string getShortName() + { + return shortName; + } + + public string getVeryShortName() + { + return veryShortName; + } + + public string getFullClassName() + { + return fullClassName; + } + + public string getShortClassName() + { + return shortClassName; + } + + public BattleRules getBattleRules() + { + return battleRules; + } + + public string[] getTeammates() + { + if (teammates == null) + { + return null; + } + var copy = new string[teammates.Length]; + Array.Copy(teammates, copy, teammates.Length); + return copy; + } + + public string getTeamName() + { + return teamName; + } + + public int getIndex() + { + return index; + } + + public int getContestIndex() + { + return contestantIndex; + } + + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + #region Nested type: SerializableHelper + + private class SerializableHelper : ISerializableHelperN + { + #region ISerializableHelperN Members + + public int sizeOf(RbSerializerN serializer, object obje) + { + var obj = (RobotStatics) obje; + int size = RbSerializerN.SIZEOF_TYPEINFO + + serializer.sizeOf(obj.robocodeVersion) + + RbSerializerN.SIZEOF_BOOL * 9 + + serializer.sizeOf(obj.name) + + serializer.sizeOf(obj.shortName) + + serializer.sizeOf(obj.veryShortName) + + serializer.sizeOf(obj.fullClassName) + + serializer.sizeOf(obj.shortClassName) + + RbSerializerN.SIZEOF_INT*6 + + RbSerializerN.SIZEOF_DOUBLE + + RbSerializerN.SIZEOF_LONG; + if (obj.teammates != null) + { + foreach (String mate in obj.teammates) + { + size += serializer.sizeOf(mate); + } + } + size += RbSerializerN.SIZEOF_INT; + size += serializer.sizeOf(obj.teamName); + + return size; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, object obje) + { + var obj = (RobotStatics) obje; + + serializer.serialize(buffer, obj.robocodeVersion); + serializer.serialize(buffer, obj.isJuniorRobot); + serializer.serialize(buffer, obj.isInteractiveRobot); + serializer.serialize(buffer, obj.isPaintRobot); + serializer.serialize(buffer, obj.isAdvancedRobot); + serializer.serialize(buffer, obj.isTeamRobot); + serializer.serialize(buffer, obj.isTeamLeader); + serializer.serialize(buffer, obj.isDroid); + serializer.serialize(buffer, obj.isSentryRobot); + serializer.serialize(buffer, obj.name); + serializer.serialize(buffer, obj.shortName); + serializer.serialize(buffer, obj.veryShortName); + serializer.serialize(buffer, obj.fullClassName); + serializer.serialize(buffer, obj.shortClassName); + serializer.serialize(buffer, obj.battleRules.BattlefieldWidth); + serializer.serialize(buffer, obj.battleRules.BattlefieldHeight); + serializer.serialize(buffer, obj.battleRules.NumRounds); + serializer.serialize(buffer, obj.battleRules.GunCoolingRate); + serializer.serialize(buffer, obj.battleRules.InactivityTime); + serializer.serialize(buffer, obj.battleRules.HideEnemyNames); + serializer.serialize(buffer, obj.battleRules.SentryBorderSize); + if (obj.teammates != null) + { + foreach (string mate in obj.teammates) + { + serializer.serialize(buffer, mate); + } + } + buffer.putInt(-1); + serializer.serialize(buffer, obj.teamName); + serializer.serialize(buffer, obj.index); + serializer.serialize(buffer, obj.contestantIndex); + } + + public object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + string robocodeVersion = serializer.deserializeString(buffer); + bool isJuniorRobot = serializer.deserializeBoolean(buffer); + bool isInteractiveRobot = serializer.deserializeBoolean(buffer); + bool isPaintRobot = serializer.deserializeBoolean(buffer); + bool isAdvancedRobot = serializer.deserializeBoolean(buffer); + bool isTeamRobot = serializer.deserializeBoolean(buffer); + bool isTeamLeader = serializer.deserializeBoolean(buffer); + bool isDroid = serializer.deserializeBoolean(buffer); + bool isSentryRobot = serializer.deserializeBoolean(buffer); + string name = serializer.deserializeString(buffer); + string shortName = serializer.deserializeString(buffer); + string veryShortName = serializer.deserializeString(buffer); + string fullClassName = serializer.deserializeString(buffer); + string shortClassName = serializer.deserializeString(buffer); + BattleRules battleRules = HiddenAccessN.createRules( + serializer.deserializeInt(buffer), // BattlefieldWidth + serializer.deserializeInt(buffer), // BattlefieldHeight + serializer.deserializeInt(buffer), // NumRounds + serializer.deserializeDouble(buffer), // GunCoolingRate + serializer.deserializeLong(buffer), // InactivityTime + serializer.deserializeBoolean(buffer), // HideEnemyNames + serializer.deserializeInt(buffer) // SentryBorderSize + ); + + var teammates = new List(); + object item = serializer.deserializeString(buffer); + while (item != null) + { + if (item is string) + { + teammates.Add((string) item); + } + item = serializer.deserializeString(buffer); + } + + string teamName = serializer.deserializeString(buffer); + int index = serializer.deserializeInt(buffer); + int contestantIndex = serializer.deserializeInt(buffer); + + return new RobotStatics( + robocodeVersion, + isJuniorRobot, + isInteractiveRobot, + isPaintRobot, + isAdvancedRobot, + isTeamRobot, + isTeamLeader, + isDroid, + isSentryRobot, + name, + shortName, + veryShortName, + fullClassName, + shortClassName, + battleRules, + teammates.ToArray(), + teamName, + index, + contestantIndex + ); + } + + #endregion + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/events/EventManager.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/events/EventManager.cs new file mode 100644 index 0000000..85a9daa --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/events/EventManager.cs @@ -0,0 +1,702 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using System.Security; +using System.Security.Permissions; +using net.sf.robocode.dotnet.host.proxies; +using net.sf.robocode.security; +using Robocode; +using robocode.exception; +using Robocode.Exception; +using Robocode.RobotInterfaces; + +namespace net.sf.robocode.dotnet.host.events +{ + /// + /// This class is used for managing the event queue for a robot. + /// + public sealed class EventManager + { + private const int MAX_PRIORITY = 100; + public const int MAX_EVENT_STACK = 2; + public const int MAX_QUEUE_SIZE = 256; + + private readonly List customEvents = new List(); + private readonly EventQueue eventQueue; + + private readonly bool[] interruptible = new bool[MAX_PRIORITY + 1]; + private Event currentTopEvent; + private int currentTopEventPriority; + private ScannedRobotEvent dummyScannedRobotEvent; + private Dictionary eventNames; + + private IBasicRobot robot; + private BasicRobotProxy robotProxy; + + /// + /// Constructs a new EventManager. + /// + /// the robot proxy that this event manager applies to. + public EventManager(BasicRobotProxy robotProxy) + { + this.robotProxy = robotProxy; + eventQueue = new EventQueue(); + + RegisterEventNames(); + Reset(); + } + + /// + /// Adds an event to the event queue. + /// + /// is the event to add to the event queue. + public void Add(Event evnt) + { + if (!HiddenAccessN.IsCriticalEvent(evnt)) + { + int priority = GetEventPriority(evnt.GetType().Name); + HiddenAccessN.SetEventPriority(evnt, priority); + } + AddImpl(evnt); + } + + /// + /// Internal method for adding an event to the event queue. + /// + /// is the event to add to the event queue. + private void AddImpl(Event evnt) + { + if (eventQueue != null) + { + if (eventQueue.Count > MAX_QUEUE_SIZE) + { + robotProxy.println( + "Not adding to " + robotProxy.getStatics().getName() + "'s queue, exceeded " + MAX_QUEUE_SIZE + + " events in queue."); + } + else + { + HiddenAccessN.SetEventTime(evnt, Time); + eventQueue.Add(evnt); + } + } + } + + /// + /// Adds an custom event to the event queue based on a condition. + /// + /// is the condition that must be met in order to trigger the custom event. + public void AddCustomEvent(Condition condition) + { + customEvents.Add(condition); + } + + /// + /// Removes all events from the event queue. + /// + /// + /// true if system events must be removed as well; + /// false if system events should stay on the event queue. + /// + public void ClearAllEvents(bool includingSystemEvents) + { + eventQueue.clear(includingSystemEvents); + // customEvents.clear(); // Custom event should not be cleared here + } + + /// + /// Cleans up the event queue. + /// + /// + /// This method should be called when the event queue is no longer needed, + /// i.e. before it must be garbage collected. + /// + public void Cleanup() + { + // Remove all events + Reset(); + + // Remove all references to robots + robot = null; + robotProxy = null; + } + + + /// + /// Returns a list containing all events currently in the robot's queue. + /// + public List GetAllEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + events.Add(e); + } + } + return events; + } + + /// + /// Returns a list containing all BulletHitBulletEvents currently in the robot's queue. + /// + public List GetBulletHitBulletEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as BulletHitBulletEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Returns a list containing all BulletHitEvents currently in the robot's queue. + /// + public List GetBulletHitEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as BulletHitEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Returns a list containing all BulletMissedEvents currently in the robot's queue. + /// + public List GetBulletMissedEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as BulletMissedEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Returns a list containing all HitByBulletEvent currently in the robot's queue. + /// + public List GetHitByBulletEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as HitByBulletEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Returns a list containing all HitRobotEvent currently in the robot's queue. + /// + public List GetHitRobotEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as HitRobotEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Returns a list containing all HitWallEvent currently in the robot's queue. + /// + public List GetHitWallEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as HitWallEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Returns a list containing all RobotDeathEvent currently in the robot's queue. + /// + public List GetRobotDeathEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as RobotDeathEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Returns a list containing all ScannedRobotEvent currently in the robot's queue. + /// + public List GetScannedRobotEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as ScannedRobotEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Returns a list containing all MessageEvent currently in the robot's queue. + /// + public List GetMessageEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as MessageEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Returns a list containing all StatusEvent currently in the robot's queue. + /// + public List GetStatusEvents() + { + var events = new List(); + lock (eventQueue) + { + foreach (Event e in eventQueue) + { + var c = e as StatusEvent; + if (c != null) + { + events.Add(c); + } + } + } + return events; + } + + /// + /// Priority of the current top event. + /// + public int CurrentTopEventPriority + { + get { return currentTopEventPriority; } + } + + /// + /// Current top event. + /// + public Event CurrentTopEvent + { + get { return currentTopEvent; } + } + + /// + /// Checks if events with a specific event priority are interruptible. + /// + /// is the event priority that must be checked. + /// + public bool IsInterruptible(int priority) + { + return interruptible[priority]; + } + + /// + /// Sets the robot that will receive events dispatched from the event queue. + /// + /// is the robot that will receive event dispatched from the event queue. + public void SetRobot(IBasicRobot robot) + { + this.robot = robot; + } + + /// + /// The priority of a ScannedRobotEvent. + /// + public int ScannedRobotEventPriority + { + get { return dummyScannedRobotEvent.Priority; } + } + + /// + /// The current time/turn of the battle round. + /// + public long Time + { + get { return robotProxy.getTimeImpl(); } + } + + /// + /// This is the heart of the event manager, which processes the events for a robot. + /// + public void ProcessEvents() + { + // Remove old events + eventQueue.clear(Time - MAX_EVENT_STACK); + + // Copy list of custom events prior iteration, because user could call RemoveCustomEvent + List eventsCopy = new List(customEvents); + + // Process custom events + foreach (Condition customEvent in eventsCopy) + { + bool conditionSatisfied = CallUserCode(customEvent); + if (conditionSatisfied) + { + AddImpl(new CustomEvent(customEvent)); + } + } + + // Process event queue here + eventQueue.sort(); + + Event currentEvent; + while ((currentEvent = (eventQueue.Count > 0) ? eventQueue[0] : null) != null + && currentEvent.Priority >= currentTopEventPriority) + { + if (currentEvent.Priority == currentTopEventPriority) + { + if (currentTopEventPriority > int.MinValue && IsInterruptible(currentTopEventPriority)) + { + SetInterruptible(currentTopEventPriority, false); // we're going to restart it, so reset. + + // We are already in an event handler, took action, and a new event was generated. + // So we want to break out of the old handler to process it here. + throw new EventInterruptedException(currentEvent.Priority); + } + break; + } + + int oldTopEventPriority = currentTopEventPriority; + + currentTopEventPriority = currentEvent.Priority; + currentTopEvent = currentEvent; + + eventQueue.Remove(currentEvent); + try + { + Dispatch(currentEvent); + + SetInterruptible(currentTopEventPriority, false); + } + catch (EventInterruptedException) + { + currentTopEvent = null; + } + catch (Exception) + { + currentTopEvent = null; + throw; + } + finally + { + currentTopEventPriority = oldTopEventPriority; + } + } + } + + /// + /// Checks if the user's condition for a custom event is satisfied. + /// + /// is the condition to check. + /// + /// true if the condition is satisfied; false otherwise. + /// + [SecurityPermission(SecurityAction.Deny)] + [ReflectionPermission(SecurityAction.Deny)] + [FileIOPermission(SecurityAction.Deny)] + [UIPermission(SecurityAction.Deny)] + private bool CallUserCode(Condition condition) + { + bool conditionSatisfied; + robotProxy.setTestingCondition(true); + try + { + conditionSatisfied = condition.Test(); + } + finally + { + robotProxy.setTestingCondition(false); + } + return conditionSatisfied; + } + + /// + /// Dispatches an event for a robot. + /// + /// + /// Too old events will not be dispatched and a critical event is always dispatched. + /// + /// is the event to dispatch to the robot. + private void Dispatch(Event evnt) + { + if (robot != null && evnt != null) + { + try + { + // skip too old events + if ((evnt.Time > Time - MAX_EVENT_STACK) || HiddenAccessN.IsCriticalEvent(evnt)) + { + HiddenAccessN.Dispatch(evnt, robot, robotProxy.getStatics(), robotProxy.getGraphicsImpl()); + } + } + catch (Exception ex) + { + if (ex is SecurityException) + { + robotProxy.punishSecurityViolation(robotProxy.getStatics().getName() + " " + ex.Message); + } + else if (ex.InnerException is SecurityException) + { + robotProxy.punishSecurityViolation(robotProxy.getStatics().getName() + " " + ex.InnerException + ": " + ex.Message); + } + else if (!(ex is EventInterruptedException || ex is AbortedException || ex is DeathException || ex is DisabledException || ex is WinException)) + { + robotProxy.println("SYSTEM: " + ex.GetType().Name + " occurred on " + evnt.GetType().Name); + robotProxy.GetOut().WriteLine(ex.StackTrace); + } + throw; + } + } + } + + /// + /// Removes the custom event with the specified condition from the event queue. + /// + /// is the condition of the custom event to remove. + public void RemoveCustomEvent(Condition condition) + { + customEvents.Remove(condition); + } + + /// + /// Removes all custom events from the event queue. + /// + public void ResetCustomEvents() + { + customEvents.Clear(); + } + + /// + /// Resets this event manager by removing all events from the event queue. + /// + public void Reset() + { + lock (this) + { + currentTopEventPriority = int.MinValue; + ClearAllEvents(true); + customEvents.Clear(); + } + } + + /// + /// Changes the interruptible flag for events with a specific priority. + /// + /// + /// When an event is interrupted, events with the same priority are allowed to restart the event handler. + /// + /// is the priority of the event to set the interruptible flag for. + /// + /// true if events with the specified priority must be interruptible + /// allowing events with the same priority to restart the event handler. + /// false if events with the specified priority must not be interruptible + /// disallowing events with the same priority to restart the event handler. + /// + public void SetInterruptible(int priority, bool interruptable) + { + if (priority < 0 || priority > 99) + { + return; + } + interruptible[priority] = interruptable; + } + + /// + /// Returns the priority of events belonging to a specific class. + /// + /// + /// is a string with the full class name of the event type to get the priority from. + /// the event priority of the specified event class. + /// + public int GetEventPriority(string eventClass) + { + if (eventClass == null) + { + return -1; + } + Event evnt; + if (!eventNames.TryGetValue(eventClass, out evnt)) + { + return -1; + } + return evnt.Priority; + } + + /// + /// Sets the event priority of events belonging to a specific class. + /// + /// + /// is a string with the full class name of the event type to set the priority for. + /// is the new priority + public void SetEventPriority(string eventClass, int priority) + { + if (eventClass == null) + { + return; + } + Event evnt; + if (!eventNames.TryGetValue(eventClass, out evnt)) + { + robotProxy.println("SYSTEM: Unknown event class: " + eventClass); + return; + } + if (HiddenAccessN.IsCriticalEvent(evnt)) + { + robotProxy.println("SYSTEM: You may not change the priority of a system event."); + } + HiddenAccessN.SetEventPriority(evnt, priority); + } + + /// + /// Registers the full and simple class names of all events used by and + /// and sets the default priority of each event class. + /// + private void RegisterEventNames() + { + eventNames = new Dictionary(); + dummyScannedRobotEvent = new ScannedRobotEvent(null, 0, 0, 0, 0, 0); + registerEventNames(new BattleEndedEvent(false, null)); + registerEventNames(new BulletHitBulletEvent(null, null)); + registerEventNames(new BulletHitEvent(null, 0, null)); + registerEventNames(new BulletMissedEvent(null)); + registerEventNames(new DeathEvent()); + registerEventNames(new HitByBulletEvent(0, null)); + registerEventNames(new HitRobotEvent(null, 0, 0, false)); + registerEventNames(new HitWallEvent(0)); + registerEventNames(new KeyPressedEvent('a', 0, 0, 0, 0, 0)); + registerEventNames(new KeyReleasedEvent('a', 0, 0, 0, 0, 0)); + registerEventNames(new KeyTypedEvent('a', 0, 0, 0, 0, 0)); + registerEventNames(new MessageEvent(null, null)); + registerEventNames(new MouseClickedEvent(0, 0, 0, 0, 0, 0, 0)); + registerEventNames(new MouseDraggedEvent(0, 0, 0, 0, 0, 0, 0)); + registerEventNames(new MouseEnteredEvent(0, 0, 0, 0, 0, 0, 0)); + registerEventNames(new MouseExitedEvent(0, 0, 0, 0, 0, 0, 0)); + registerEventNames(new MouseMovedEvent(0, 0, 0, 0, 0, 0, 0)); + registerEventNames(new MousePressedEvent(0, 0, 0, 0, 0, 0, 0)); + registerEventNames(new MouseReleasedEvent(0, 0, 0, 0, 0, 0, 0)); + registerEventNames(new MouseWheelMovedEvent(0, 0, 0, 0, 0, 0, 0, 0, 0)); + registerEventNames(new PaintEvent()); + registerEventNames(new RobotDeathEvent(null)); + registerEventNames(dummyScannedRobotEvent); + registerEventNames(new SkippedTurnEvent(0)); + registerEventNames(new StatusEvent(null)); + registerEventNames(new WinEvent()); + + // same as any line above but for custom event + var customEvent = new DummyCustomEvent(); + eventNames.Add("robocode.CustomEvent", customEvent); // full name with package name + eventNames.Add("CustomEvent", customEvent); // only the class name + } + + /// + /// Registers the full and simple class name of the specified event and sets the default + /// priority of the event class. + /// + /// an event belonging to the event class to register the class name for etc. + private void registerEventNames(Event evnt) + { + if (!HiddenAccessN.IsCriticalEvent(evnt)) + { + HiddenAccessN.SetDefaultPriority(evnt); + } + Type type = evnt.GetType(); + eventNames.Add(type.FullName, evnt); // full name with package name + eventNames.Add(type.Name, evnt); // only the class name + } + + #region Nested type: DummyCustomEvent + + /// + /// A dummy CustomEvent used only for registering the class name. + /// + private sealed class DummyCustomEvent : CustomEvent + { + public DummyCustomEvent() + : base(null) + { + } + } + + #endregion + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/events/EventQueue.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/events/EventQueue.cs new file mode 100644 index 0000000..69d9089 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/events/EventQueue.cs @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Collections.Generic; +using net.sf.robocode.security; +using Robocode; + +namespace net.sf.robocode.dotnet.host.events +{ + internal class EventQueue : List + { + public void clear(bool includingSystemEvents) + { + if (includingSystemEvents) + { + Clear(); + return; + } + + for (int i = 0; i < Count; i++) + { + Event e = this[i]; + + if (!HiddenAccessN.IsCriticalEvent(e)) + { + RemoveAt(i--); + } + } + } + + public void clear(long clearTime) + { + for (int i = 0; i < Count; i++) + { + Event e = this[i]; + + if ((e.Time <= clearTime) && !HiddenAccessN.IsCriticalEvent(e)) + { + RemoveAt(i--); + } + } + } + + public void sort() + { + Sort(); + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/AdvancedRobotProxy.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/AdvancedRobotProxy.cs new file mode 100644 index 0000000..8220b51 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/AdvancedRobotProxy.cs @@ -0,0 +1,227 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using System.IO; +using net.sf.robocode.host; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using Robocode; +using Robocode.RobotInterfaces.Peer; + +namespace net.sf.robocode.dotnet.host.proxies +{ + internal class AdvancedRobotProxy : StandardRobotProxy, IAdvancedRobotPeer + { + public AdvancedRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, + RobotStatics statics) + : base(specification, hostManager, peer, statics) + { + } + + // asynchronous actions + + #region IAdvancedRobotPeer Members + + public void SetResume() + { + SetCall(); + setResumeImpl(); + } + + public void SetStop(bool overwrite) + { + SetCall(); + setStopImpl(overwrite); + } + + public void SetMove(double distance) + { + SetCall(); + setMoveImpl(distance); + } + + public void SetTurnBody(double radians) + { + SetCall(); + setTurnBodyImpl(radians); + } + + public void SetTurnGun(double radians) + { + SetCall(); + setTurnGunImpl(radians); + } + + public void SetTurnRadar(double radians) + { + SetCall(); + setTurnRadarImpl(radians); + } + + // blocking actions + public void WaitFor(Condition condition) + { + waitCondition = condition; + do + { + Execute(); // Always tick at least once + } while (!condition.Test()); + + waitCondition = null; + } + + // fast setters + public void SetMaxTurnRate(double newTurnRate) + { + SetCall(); + if (Double.IsNaN(newTurnRate)) + { + println("You cannot SetMaxTurnRate to: " + newTurnRate); + return; + } + commands.setMaxTurnRate(newTurnRate); + } + + public void SetMaxVelocity(double newVelocity) + { + SetCall(); + if (Double.IsNaN(newVelocity)) + { + println("You cannot SetMaxVelocity to: " + newVelocity); + return; + } + commands.setMaxVelocity(newVelocity); + } + + // events manipulation + public void SetInterruptible(bool interruptable) + { + SetCall(); + eventManager.SetInterruptible(eventManager.CurrentTopEventPriority, interruptable); + } + + public void SetEventPriority(String eventClass, int priority) + { + SetCall(); + eventManager.SetEventPriority(eventClass, priority); + } + + public int GetEventPriority(String eventClass) + { + GetCall(); + return eventManager.GetEventPriority(eventClass); + } + + public void RemoveCustomEvent(Condition condition) + { + SetCall(); + eventManager.RemoveCustomEvent(condition); + } + + public void AddCustomEvent(Condition condition) + { + SetCall(); + eventManager.AddCustomEvent(condition); + } + + public void clearAllEvents() + { + SetCall(); + eventManager.ClearAllEvents(false); + } + + public IList GetAllEvents() + { + GetCall(); + return eventManager.GetAllEvents(); + } + + public IList GetStatusEvents() + { + GetCall(); + return eventManager.GetStatusEvents(); + } + + public IList GetBulletMissedEvents() + { + GetCall(); + return eventManager.GetBulletMissedEvents(); + } + + public IList GetBulletHitBulletEvents() + { + GetCall(); + return eventManager.GetBulletHitBulletEvents(); + } + + public IList GetBulletHitEvents() + { + GetCall(); + return eventManager.GetBulletHitEvents(); + } + + public IList GetHitByBulletEvents() + { + GetCall(); + return eventManager.GetHitByBulletEvents(); + } + + public IList GetHitRobotEvents() + { + GetCall(); + return eventManager.GetHitRobotEvents(); + } + + public IList GetHitWallEvents() + { + GetCall(); + return eventManager.GetHitWallEvents(); + } + + public IList GetRobotDeathEvents() + { + GetCall(); + return eventManager.GetRobotDeathEvents(); + } + + public IList GetScannedRobotEvents() + { + GetCall(); + return eventManager.GetScannedRobotEvents(); + } + + // data + public string GetDataDirectory() + { + GetCall(); + commands.setIORobot(); + return robotFileSystemManager.getWritableDirectory(); + } + + public Stream GetDataFile(string filename) + { + GetCall(); + commands.setIORobot(); + if (filename.Contains("..")) + { + throw new AccessViolationException("no relative path allowed"); + } + + return robotFileSystemManager.getDataFile(filename); + } + + public long GetDataQuotaAvailable() + { + GetCall(); + return robotFileSystemManager.getDataQuotaAvailable(); + } + + #endregion + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/BasicRobotProxy.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/BasicRobotProxy.cs new file mode 100644 index 0000000..125e00c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/BasicRobotProxy.cs @@ -0,0 +1,716 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Threading; +using net.sf.jni4net.nio; +using net.sf.robocode.dotnet.host.events; +using net.sf.robocode.dotnet.peer; +using net.sf.robocode.host; +using net.sf.robocode.io; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using net.sf.robocode.security; +using net.sf.robocode.serialization; +using Robocode; +using robocode.exception; +using Robocode.Exception; +using Robocode.RobotInterfaces.Peer; +using Robocode.Util; +using ByteBuffer = net.sf.robocode.nio.ByteBuffer; +using Thread = System.Threading.Thread; + +namespace net.sf.robocode.dotnet.host.proxies +{ + public class BasicRobotProxy : HostingRobotProxy, IBasicRobotPeer + { + private const long + MAX_SET_CALL_COUNT = 10000, + MAX_GET_CALL_COUNT = 10000; + + private GraphicsProxy graphicsProxy; + + private RobotStatus status; + private bool isDisabled; + protected ExecCommands commands; + private ExecResults execResults; + + private readonly Dictionary bullets = new Dictionary(); + private int bulletCounter; + + private int setCallCount; + private int getCallCount; + + protected Condition waitCondition; + private bool testingCondition; + private double firedEnergy; + private double firedHeat; + + private readonly DirectByteBuffer execJavaBuffer; + private readonly ByteBuffer execNetBuffer; + private readonly RbSerializerN rbSerializerN; + + public BasicRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) + : base(specification, hostManager, peer, statics) + { + eventManager = new EventManager(this); + + graphicsProxy = new GraphicsProxy(); + + // dummy + execResults = new ExecResults(null, null, null, null, null, false, false, false); + + setSetCallCount(0); + setGetCallCount(0); + + var sharedBuffer = new byte[10*1024*100]; + execJavaBuffer = new DirectByteBuffer(sharedBuffer); + execNetBuffer = ByteBuffer.wrap(sharedBuffer); + rbSerializerN = new RbSerializerN(); + this.peer.setupBuffer(execJavaBuffer); + } + + // asynchronous actions + + #region IBasicRobotPeer Members + + public Bullet SetFire(double power) + { + SetCall(); + return setFireImpl(power); + } + + // blocking actions + public void Execute() + { + executeImpl(); + } + + public void Move(double distance) + { + setMoveImpl(distance); + do + { + Execute(); // Always tick at least once + } while (GetDistanceRemaining() != 0); + } + + public void TurnBody(double radians) + { + setTurnBodyImpl(radians); + do + { + Execute(); // Always tick at least once + } while (GetBodyTurnRemaining() != 0); + } + + public void TurnGun(double radians) + { + setTurnGunImpl(radians); + do + { + Execute(); // Always tick at least once + } while (GetGunTurnRemaining() != 0); + } + + public Bullet Fire(double power) + { + Bullet bullet = SetFire(power); + + Execute(); + return bullet; + } + + // fast setters + public void SetBodyColor(Color color) + { + SetCall(); + commands.setBodyColor(color.ToArgb()); + } + + public Color GetBodyColor() + { + GetCall(); + return Color.FromArgb(commands.getBodyColor()); + } + + public void SetGunColor(Color color) + { + SetCall(); + commands.setGunColor(color.ToArgb()); + } + + public Color GetGunColor() + { + GetCall(); + return Color.FromArgb(commands.getGunColor()); + } + + public void SetRadarColor(Color color) + { + SetCall(); + commands.setRadarColor(color.ToArgb()); + } + + public Color GetRadarColor() + { + GetCall(); + return Color.FromArgb(commands.getRadarColor()); + } + + public void SetBulletColor(Color color) + { + SetCall(); + commands.setBulletColor(color.ToArgb()); + } + + public Color GetBulletColor() + { + GetCall(); + return Color.FromArgb(commands.getBulletColor()); + } + + public void SetScanColor(Color color) + { + SetCall(); + commands.setScanColor(color.ToArgb()); + } + + public Color GetScanColor() + { + GetCall(); + return Color.FromArgb(commands.getScanColor()); + } + + // counters + public void SetCall() + { + if (!isDisabled) + { + int res = Interlocked.Increment(ref setCallCount); + + if (res >= MAX_SET_CALL_COUNT) + { + isDisabled = true; + println("SYSTEM: You have made " + res + " calls to setXX methods without calling Execute()"); + throw new DisabledException("Too many calls to setXX methods"); + } + } + } + + public void GetCall() + { + if (!isDisabled) + { + int res = Interlocked.Increment(ref getCallCount); + + if (res >= MAX_GET_CALL_COUNT) + { + isDisabled = true; + println("SYSTEM: You have made " + res + " calls to getXX methods without calling Execute()"); + throw new DisabledException("Too many calls to getXX methods"); + } + } + } + + public double GetDistanceRemaining() + { + GetCall(); + return commands.getDistanceRemaining(); + } + + public double GetRadarTurnRemaining() + { + GetCall(); + return commands.getRadarTurnRemaining(); + } + + public double GetBodyTurnRemaining() + { + GetCall(); + return commands.getBodyTurnRemaining(); + } + + public double GetGunTurnRemaining() + { + GetCall(); + return commands.getGunTurnRemaining(); + } + + public double GetVelocity() + { + GetCall(); + return status.Velocity; + } + + public double GetGunCoolingRate() + { + GetCall(); + return statics.getBattleRules().GunCoolingRate; + } + + public String GetName() + { + GetCall(); + return statics.getName(); + } + + public long GetTime() + { + GetCall(); + return getTimeImpl(); + } + + public double GetBodyHeading() + { + GetCall(); + return status.HeadingRadians; + } + + public double GetGunHeading() + { + GetCall(); + return status.GunHeadingRadians; + } + + public double GetRadarHeading() + { + GetCall(); + return status.RadarHeadingRadians; + } + + public double GetEnergy() + { + GetCall(); + return getEnergyImpl(); + } + + public double GetGunHeat() + { + GetCall(); + return getGunHeatImpl(); + } + + public double GetX() + { + GetCall(); + return status.X; + } + + public double GetY() + { + GetCall(); + return status.Y; + } + + public int GetOthers() + { + GetCall(); + return status.Others; + } + + public int GetNumSentries() + { + GetCall(); + return status.NumSentries; + } + + public double GetBattleFieldHeight() + { + GetCall(); + return statics.getBattleRules().BattlefieldHeight; + } + + public double GetBattleFieldWidth() + { + GetCall(); + return statics.getBattleRules().BattlefieldWidth; + } + + public int GetNumRounds() + { + GetCall(); + return statics.getBattleRules().NumRounds; + } + + public int GetRoundNum() + { + GetCall(); + return status.RoundNum; + } + + public int GetSentryBorderSize() + { + GetCall(); + return statics.getBattleRules().SentryBorderSize; + } + + public IGraphics GetGraphics() + { + GetCall(); + commands.setTryingToPaint(true); + return getGraphicsImpl(); + } + + public void SetDebugProperty(String key, String value) + { + SetCall(); + commands.setDebugProperty(key, value); + } + + public void Rescan() + { + bool reset = false; + bool origInterruptableValue = false; + + if (eventManager.CurrentTopEventPriority == eventManager.ScannedRobotEventPriority) + { + reset = true; + origInterruptableValue = eventManager.IsInterruptible(eventManager.ScannedRobotEventPriority); + eventManager.SetInterruptible(eventManager.ScannedRobotEventPriority, true); + } + + commands.setScan(true); + executeImpl(); + + if (reset) + { + eventManager.SetInterruptible(eventManager.ScannedRobotEventPriority, origInterruptableValue); + } + } + + #endregion + + internal override void initializeRound(ExecCommands commands, RobotStatus status) + { + updateStatus(commands, status); + eventManager.Reset(); + var start = new StatusEvent(status); + + eventManager.Add(start); + setSetCallCount(0); + setGetCallCount(0); + } + + public override void cleanup() + { + base.cleanup(); + + // Cleanup and remove current wait condition + waitCondition = null; + + // Cleanup and remove the event manager + if (eventManager != null) + { + eventManager.Cleanup(); + eventManager = null; + } + + graphicsProxy = null; + execResults = null; + status = null; + commands = null; + } + + // ----------- + // implementations + // ----------- + + public long getTimeImpl() + { + return status.Time; + } + + public IGraphics getGraphicsImpl() + { + return graphicsProxy; + } + + protected override sealed void executeImpl() + { + if (execResults == null) + { + // this is to slow down undead robot after cleanup, from fast exception-loop + Thread.Sleep(1000); + } + + // Entering tick + if (testingCondition) + { + throw new RobotException( + "You cannot take action inside Condition.Test(). You should handle OnCustomEvent instead."); + } + + setSetCallCount(0); + setGetCallCount(0); + + // This stops autoscan from scanning... + if (waitCondition != null && waitCondition.Test()) + { + waitCondition = null; + commands.setScan(true); + } + + commands.setOutputText(GetOutTextAndReset()); + commands.setGraphicsCalls(graphicsProxy.readoutQueuedCalls()); + + // call server + SerializeCommands(); + peer.executeImplSerial(); + DeserializeResults(); + + if (execResults == null) + { + throw new InvalidOperationException(); + } + + updateStatus(execResults.getCommands(), execResults.getStatus()); + + graphicsProxy.setPaintingEnabled(execResults.isPaintEnabled()); + firedEnergy = 0; + firedHeat = 0; + + // add new events + eventManager.Add(new StatusEvent(execResults.getStatus())); + if (statics.IsPaintRobot() && execResults.isPaintEnabled()) + { + // Add paint event, if robot is a paint robot and its painting is enabled + eventManager.Add(new PaintEvent()); + } + + // add other events + if (execResults.getEvents() != null) + { + foreach (Event evnt in execResults.getEvents()) + { + eventManager.Add(evnt); + HiddenAccessN.UpdateBullets(evnt, bullets); + } + } + + if (execResults.getBulletUpdates() != null) + { + foreach (BulletStatus bulletStatus in execResults.getBulletUpdates()) + { + Bullet bullet; + if (bullets.TryGetValue(bulletStatus.bulletId, out bullet)) + { + HiddenAccessN.Update(bullet, bulletStatus.x, bulletStatus.y, bulletStatus.victimName, bulletStatus.isActive); + if (!bulletStatus.isActive) + { + bullets.Remove(bulletStatus.bulletId); + } + } + } + } + + // add new team messages + loadTeamMessages(execResults.getTeamMessages()); + + eventManager.ProcessEvents(); + } + + private string GetOutTextAndReset() + { + string res; + lock (output) + { + output.Flush(); + res = outputSb.ToString(); + outputSb.Length = 0; + } + return res; + } + + + private void SerializeCommands() + { + execNetBuffer.clear(); + rbSerializerN.serializeToBuffer(execNetBuffer, RbSerializerN.ExecCommands_TYPE, commands); + execJavaBuffer.Position(0); + execJavaBuffer.Limit(execNetBuffer.limit()); + } + + private void DeserializeResults() + { + execNetBuffer.position(0); + execNetBuffer.limit(execJavaBuffer.limit()); + execResults = (ExecResults) rbSerializerN.deserialize(execNetBuffer); + } + + protected override sealed void waitForBattleEndImpl() + { + eventManager.ClearAllEvents(false); + graphicsProxy.setPaintingEnabled(false); + do + { + commands.setOutputText(GetOutTextAndReset()); + commands.setGraphicsCalls(graphicsProxy.readoutQueuedCalls()); + + // call server + try + { + SerializeCommands(); + peer.waitForBattleEndImplSerial(); + DeserializeResults(); + } + catch (Exception ex) + { + LoggerN.logMessage(statics.getName() + ": Exception: " + ex); // without stack here + return; + } + + updateStatus(execResults.getCommands(), execResults.getStatus()); + + // add new events + if (execResults.getEvents() != null) + { + foreach (Event evnt in execResults.getEvents()) + { + if (evnt is BattleEndedEvent) + { + eventManager.Add(evnt); + } + } + } + eventManager.ResetCustomEvents(); + + eventManager.ProcessEvents(); + + } while (!execResults.isHalt() && execResults.isShouldWait()); + } + + private void updateStatus(ExecCommands commands, RobotStatus status) + { + this.status = status; + this.commands = commands; + } + + protected virtual void loadTeamMessages(List teamMessages) + { + } + + protected double getEnergyImpl() + { + return status.Energy - firedEnergy; + } + + protected double getGunHeatImpl() + { + return status.GunHeat + firedHeat; + } + + protected void setMoveImpl(double distance) + { + if (getEnergyImpl() == 0) + { + return; + } + commands.setDistanceRemaining(distance); + commands.setMoved(true); + } + + protected Bullet setFireImpl(double power) + { + if (Double.IsNaN(power)) + { + println("SYSTEM: You cannot call Fire(NaN)"); + return null; + } + if (getGunHeatImpl() > 0 || getEnergyImpl() == 0) + { + return null; + } + + power = Math.Min(getEnergyImpl(), Math.Min(Math.Max(power, Rules.MIN_BULLET_POWER), Rules.MAX_BULLET_POWER)); + + Bullet bullet; + BulletCommand wrapper; + Event currentTopEvent = eventManager.CurrentTopEvent; + + bulletCounter++; + + if (currentTopEvent != null && currentTopEvent.Time == status.Time && !statics.IsAdvancedRobot() + && status.GunHeadingRadians == status.RadarHeadingRadians + && typeof (ScannedRobotEvent).IsAssignableFrom(currentTopEvent.GetType())) + { + // this is angle assisted bullet + var e = (ScannedRobotEvent) currentTopEvent; + double fireAssistAngle = Utils.NormalAbsoluteAngle(status.HeadingRadians + e.BearingRadians); + + bullet = new Bullet(fireAssistAngle, GetX(), GetY(), power, statics.getName(), null, true, bulletCounter); + wrapper = new BulletCommand(power, true, fireAssistAngle, bulletCounter); + } + else + { + // this is normal bullet + bullet = new Bullet(status.GunHeadingRadians, GetX(), GetY(), power, statics.getName(), null, true, + bulletCounter); + wrapper = new BulletCommand(power, false, 0, bulletCounter); + } + + firedEnergy += power; + firedHeat += Rules.GetGunHeat(power); + + commands.getBullets().Add(wrapper); + + bullets.Add(bulletCounter, bullet); + + return bullet; + } + + protected void setTurnGunImpl(double radians) + { + commands.setGunTurnRemaining(radians); + } + + protected void setTurnBodyImpl(double radians) + { + if (getEnergyImpl() > 0) + { + commands.setBodyTurnRemaining(radians); + } + } + + protected void setTurnRadarImpl(double radians) + { + commands.setRadarTurnRemaining(radians); + } + + // ----------- + // battle driven methods + // ----------- + + private void setSetCallCount(int setCallCount) + { + this.setCallCount = setCallCount; + } + + private void setGetCallCount(int getCallCount) + { + this.getCallCount = getCallCount; + } + + // ----------- + // for robot thread + // ----------- + + public void setTestingCondition(bool testingCondition) + { + this.testingCondition = testingCondition; + } + + + public override String ToString() + { + return statics.getShortName() + "(" + (int) status.Energy + ") X" + (int) status.X + " Y" + + (int) status.Y; + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/GraphicsProxy.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/GraphicsProxy.cs new file mode 100644 index 0000000..b47450a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/GraphicsProxy.cs @@ -0,0 +1,1284 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using net.sf.robocode.nio; +using net.sf.robocode.serialization; +using Robocode; + +namespace net.sf.robocode.dotnet.host.proxies +{ + public class GraphicsProxy : IGraphics + { + private const int INITIAL_BUFFER_SIZE = 2*1024; + private const int MAX_BUFFER_SIZE = 64*1024; + + private readonly bool isDebugging; + private readonly RbSerializerN serializer = new RbSerializerN(); + private ByteBuffer calls; + private bool isPaintingEnabled; + private int unrecoveredBufferOverflowCount; + + public GraphicsProxy() + { + calls = ByteBuffer.allocate(INITIAL_BUFFER_SIZE); + calls.order(ByteOrder.LITTLE_ENDIAN); + calls.put(calls.order() == ByteOrder.BIG_ENDIAN ? (byte) 1 : (byte) 0); + isDebugging = java.lang.System.getProperty("debug", "false") == "true"; + } + + #region IGraphics Members + + public void DrawRectangle(Pen pen, RectangleF rect) + { + DrawRectangle(pen, (int) rect.X, (int) rect.Y, (int) rect.Width, (int) rect.Height); + } + + public void DrawRectangle(Pen pen, Rectangle rect) + { + DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void DrawRectangle(Pen pen, float x, float y, float width, float height) + { + DrawRectangle(pen, (int) x, (int) y, (int) width, (int) height); + } + + public void DrawRectangle(Pen pen, int x, int y, int width, int height) + { + if (isPaintingEnabled) + { + setColor(pen); + calls.mark(); // Mark for rollback + try + { + put(Method.DRAW_RECT); + put(x); + put(y); + put(width); + put(height); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + DrawRectangle(pen, x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + public void FillRectangle(Brush brush, RectangleF rect) + { + FillRectangle(brush, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void FillRectangle(Brush brush, float x, float y, float width, float height) + { + FillRectangle(brush, (int) x, (int) y, (int) width, (int) height); + } + + public void FillRectangle(Brush brush, Rectangle rect) + { + FillRectangle(brush, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void FillRectangle(Brush brush, int x, int y, int width, int height) + { + if (isPaintingEnabled) + { + setColor(brush); + calls.mark(); // Mark for rollback + try + { + put(Method.FILL_RECT); + put(x); + put(y); + put(width); + put(height); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + FillRectangle(brush, x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + + public void DrawEllipse(Pen pen, int x, int y, int width, int height) + { + if (isPaintingEnabled) + { + setColor(pen); + calls.mark(); // Mark for rollback + try + { + put(Method.DRAW_OVAL); + put(x); + put(y); + put(width); + put(height); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + DrawEllipse(pen, x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + public void DrawEllipse(Pen pen, RectangleF rect) + { + DrawEllipse(pen, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void DrawEllipse(Pen pen, float x, float y, float width, float height) + { + DrawEllipse(pen, (int) x, (int) y, (int) width, (int) height); + } + + public void DrawEllipse(Pen pen, Rectangle rect) + { + DrawEllipse(pen, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void FillEllipse(Brush brush, int x, int y, int width, int height) + { + if (isPaintingEnabled) + { + setColor(brush); + calls.mark(); // Mark for rollback + try + { + put(Method.FILL_OVAL); + put(x); + put(y); + put(width); + put(height); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + FillEllipse(brush, x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + public void FillEllipse(Brush brush, RectangleF rect) + { + FillEllipse(brush, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void FillEllipse(Brush brush, float x, float y, float width, float height) + { + FillEllipse(brush, (int) x, (int) y, (int) width, (int) height); + } + + public void FillEllipse(Brush brush, Rectangle rect) + { + FillEllipse(brush, rect.X, rect.Y, rect.Width, rect.Height); + } + + public void DrawLine(Pen pen, float x1, float y1, float x2, float y2) + { + DrawLine(pen, (int) x1, (int) y1, (int) x2, (int) y2); + } + + public void DrawLine(Pen pen, PointF pt1, PointF pt2) + { + DrawLine(pen, (int) pt1.X, (int) pt1.Y, (int) pt2.X, (int) pt2.Y); + } + + public void DrawLine(Pen pen, Point pt1, Point pt2) + { + DrawLine(pen, pt1.X, pt1.Y, pt2.X, pt2.Y); + } + + public void DrawLine(Pen pen, int x1, int y1, int x2, int y2) + { + if (isPaintingEnabled) + { + setColor(pen); + calls.mark(); // Mark for rollback + try + { + put(Method.DRAW_LINE); + put(x1); + put(y1); + put(x2); + put(y2); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + DrawLine(pen, x1, y1, x2, y2); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + public void DrawArc(Pen pen, float x, float y, float width, float height, float startAngle, float sweepAngle) + { + DrawArc(pen, (int) x, (int) y, (int) width, (int) height, (int) startAngle, (int) sweepAngle); + } + + public void DrawArc(Pen pen, RectangleF rect, float startAngle, float sweepAngle) + { + DrawArc(pen, rect.X, rect.Y, rect.Width, rect.Height, startAngle, sweepAngle); + } + + public void DrawArc(Pen pen, Rectangle rect, float startAngle, float sweepAngle) + { + DrawArc(pen, rect.X, rect.Y, rect.Width, rect.Height, startAngle, sweepAngle); + } + + public void DrawArc(Pen pen, int x, int y, int width, int height, int startAngle, int sweepAngle) + { + if (isPaintingEnabled) + { + setColor(pen); + calls.mark(); // Mark for rollback + try + { + put(Method.DRAW_ARC); + put(x); + put(y); + put(width); + put(height); + put(startAngle); + put(sweepAngle); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + DrawArc(pen, x, y, width, height, startAngle, sweepAngle); + // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + public void DrawPie(Pen pen, RectangleF rect, float startAngle, float sweepAngle) + { + //for now redirected to arc, I wonder if java have Pie as well + DrawArc(pen, rect, startAngle, sweepAngle); + } + + public void DrawPie(Pen pen, float x, float y, float width, float height, float startAngle, float sweepAngle) + { + //for now redirected to arc, I wonder if java have Pie as well + DrawArc(pen, x, y, width, height, startAngle, sweepAngle); + } + + public void DrawPie(Pen pen, Rectangle rect, float startAngle, float sweepAngle) + { + //for now redirected to arc, I wonder if java have Pie as well + DrawArc(pen, rect, startAngle, sweepAngle); + } + + public void DrawPie(Pen pen, int x, int y, int width, int height, int startAngle, int sweepAngle) + { + //for now redirected to arc, I wonder if java have Pie as well + DrawArc(pen, x, y, width, height, startAngle, sweepAngle); + } + + public void FillPie(Brush brush, Rectangle rect, float startAngle, float sweepAngle) + { + FillPie(brush, rect.X, rect.Y, rect.Width, rect.Height, startAngle, sweepAngle); + } + + public void FillPie(Brush brush, float x, float y, float width, float height, float startAngle, float sweepAngle) + { + FillPie(brush, (int) x, (int) y, (int) width, (int) height, (int) startAngle, (int) sweepAngle); + } + + public void FillPie(Brush brush, int x, int y, int width, int height, int startAngle, int sweepAngle) + { + if (isPaintingEnabled) + { + setColor(brush); + calls.mark(); // Mark for rollback + try + { + put(Method.DRAW_ARC); + put(x); + put(y); + put(width); + put(height); + put(startAngle); + put(sweepAngle); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + FillPie(brush, x, y, width, height, startAngle, sweepAngle); + // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + public void DrawPolygon(Pen pen, PointF[] points) + { + if (isPaintingEnabled) + { + int[] xPoints = new int[points.Length]; + int[] yPoints = new int[points.Length]; + for (int i = 0; i < points.Length; i++) + { + xPoints[i] = (int) points[i].X; + yPoints[i] = (int) points[i].Y; + } + setColor(pen); + calls.mark(); // Mark for rollback + try + { + put(Method.DRAW_POLYGON); + put(xPoints); + put(yPoints); + put(points.Length); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + DrawPolygon(pen, points); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + public void DrawPolygon(Pen pen, Point[] points) + { + if (isPaintingEnabled) + { + int[] xPoints = new int[points.Length]; + int[] yPoints = new int[points.Length]; + for (int i = 0; i < points.Length; i++) + { + xPoints[i] = points[i].X; + yPoints[i] = points[i].Y; + } + setColor(pen); + calls.mark(); // Mark for rollback + try + { + put(Method.DRAW_POLYGON); + put(xPoints); + put(yPoints); + put(points.Length); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + DrawPolygon(pen, points); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + + public void FillPolygon(Brush brush, PointF[] points) + { + if (isPaintingEnabled) + { + int[] xPoints = new int[points.Length]; + int[] yPoints = new int[points.Length]; + for (int i = 0; i < points.Length; i++) + { + xPoints[i] = (int) points[i].X; + yPoints[i] = (int) points[i].Y; + } + setColor(brush); + calls.mark(); // Mark for rollback + try + { + put(Method.FILL_POLYGON); + put(xPoints); + put(yPoints); + put(points.Length); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + FillPolygon(brush, points); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + public void FillPolygon(Brush brush, Point[] points) + { + if (isPaintingEnabled) + { + int[] xPoints = new int[points.Length]; + int[] yPoints = new int[points.Length]; + for (int i = 0; i < points.Length; i++) + { + xPoints[i] = points[i].X; + yPoints[i] = points[i].Y; + } + setColor(brush); + calls.mark(); // Mark for rollback + try + { + put(Method.FILL_POLYGON); + put(xPoints); + put(yPoints); + put(points.Length); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + FillPolygon(brush, points); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + public void DrawString(string s, Font font, Brush brush, float x, float y) + { + DrawString(s, font, brush, (int) x, (int) y); + } + + public void DrawString(string s, Font font, Brush brush, PointF point) + { + DrawString(s, font, brush, point.X, point.Y); + } + + public void DrawString(string s, Font font, Brush brush, Point point) + { + DrawString(s, font, brush, point.X, point.Y); + } + + public void DrawString(string s, Font font, Brush brush, int x, int y) + { + if (string.IsNullOrEmpty(s)) + { + return; + } + if (isPaintingEnabled) + { + setColor(brush); + calls.mark(); // Mark for rollback + try + { + put(Method.DRAW_STRING_INT); + put(s); + put(x); + put(y); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + DrawString(s, font, brush, x, y); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + #endregion + + #region TODO + /* + + public void FillPolygon(Brush brush, PointF[] points, FillMode fillMode) + { + throw new NotImplementedException(); + } + + public void FillPolygon(Brush brush, Point[] points, FillMode fillMode) + { + throw new NotImplementedException(); + } + + public void ResetTransform() + { + throw new NotImplementedException(); + } + + public void MultiplyTransform(Matrix matrix) + { + throw new NotImplementedException(); + } + + public void MultiplyTransform(Matrix matrix, MatrixOrder order) + { + throw new NotImplementedException(); + } + + public void TranslateTransform(float dx, float dy) + { + throw new NotImplementedException(); + } + + public void TranslateTransform(float dx, float dy, MatrixOrder order) + { + throw new NotImplementedException(); + } + + public void ScaleTransform(float sx, float sy) + { + throw new NotImplementedException(); + } + + public void ScaleTransform(float sx, float sy, MatrixOrder order) + { + throw new NotImplementedException(); + } + + public void RotateTransform(float angle) + { + throw new NotImplementedException(); + } + + public void RotateTransform(float angle, MatrixOrder order) + { + throw new NotImplementedException(); + } + + public void TransformPoints(CoordinateSpace destSpace, CoordinateSpace srcSpace, PointF[] pts) + { + throw new NotImplementedException(); + } + + public void TransformPoints(CoordinateSpace destSpace, CoordinateSpace srcSpace, Point[] pts) + { + throw new NotImplementedException(); + } + + public void DrawLines(Pen pen, PointF[] points) + { + throw new NotImplementedException(); + } + + public void DrawLines(Pen pen, Point[] points) + { + throw new NotImplementedException(); + } + + public void DrawRectangles(Pen pen, RectangleF[] rects) + { + throw new NotImplementedException(); + } + + public void DrawRectangles(Pen pen, Rectangle[] rects) + { + throw new NotImplementedException(); + } + + public void DrawPath(Pen pen, GraphicsPath path) + { + throw new NotImplementedException(); + } + + public void DrawCurve(Pen pen, PointF[] points) + { + throw new NotImplementedException(); + } + + public void DrawCurve(Pen pen, PointF[] points, float tension) + { + throw new NotImplementedException(); + } + + public void DrawCurve(Pen pen, PointF[] points, int offset, int numberOfSegments) + { + throw new NotImplementedException(); + } + + public void DrawCurve(Pen pen, PointF[] points, int offset, int numberOfSegments, float tension) + { + throw new NotImplementedException(); + } + + public void DrawCurve(Pen pen, Point[] points) + { + throw new NotImplementedException(); + } + + public void DrawCurve(Pen pen, Point[] points, float tension) + { + throw new NotImplementedException(); + } + + public void DrawCurve(Pen pen, Point[] points, int offset, int numberOfSegments, float tension) + { + throw new NotImplementedException(); + } + + public void DrawClosedCurve(Pen pen, PointF[] points) + { + throw new NotImplementedException(); + } + + public void DrawClosedCurve(Pen pen, PointF[] points, float tension, FillMode fillmode) + { + throw new NotImplementedException(); + } + + public void DrawClosedCurve(Pen pen, Point[] points) + { + throw new NotImplementedException(); + } + + public void DrawClosedCurve(Pen pen, Point[] points, float tension, FillMode fillmode) + { + throw new NotImplementedException(); + } + + public void FillRectangles(Brush brush, RectangleF[] rects) + { + throw new NotImplementedException(); + } + + public void FillRectangles(Brush brush, Rectangle[] rects) + { + throw new NotImplementedException(); + } + + public void FillPath(Brush brush, GraphicsPath path) + { + throw new NotImplementedException(); + } + + public void FillClosedCurve(Brush brush, PointF[] points) + { + throw new NotImplementedException(); + } + + public void FillClosedCurve(Brush brush, PointF[] points, FillMode fillmode) + { + throw new NotImplementedException(); + } + + public void FillClosedCurve(Brush brush, PointF[] points, FillMode fillmode, float tension) + { + throw new NotImplementedException(); + } + + public void FillClosedCurve(Brush brush, Point[] points) + { + throw new NotImplementedException(); + } + + public void FillClosedCurve(Brush brush, Point[] points, FillMode fillmode) + { + throw new NotImplementedException(); + } + + public void FillClosedCurve(Brush brush, Point[] points, FillMode fillmode, float tension) + { + throw new NotImplementedException(); + } + + public void FillRegion(Brush brush, Region region) + { + throw new NotImplementedException(); + } + + public void DrawString(string s, Font font, Brush brush, float x, float y, StringFormat format) + { + throw new NotImplementedException(); + } + + public void DrawString(string s, Font font, Brush brush, PointF point, StringFormat format) + { + throw new NotImplementedException(); + } + + public void DrawString(string s, Font font, Brush brush, RectangleF layoutRectangle) + { + throw new NotImplementedException(); + } + + public void DrawString(string s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat format) + { + throw new NotImplementedException(); + } + + public SizeF MeasureString(string text, Font font, SizeF layoutArea, StringFormat stringFormat, + out int charactersFitted, out int linesFilled) + { + throw new NotImplementedException(); + } + + public SizeF MeasureString(string text, Font font, PointF origin, StringFormat stringFormat) + { + throw new NotImplementedException(); + } + + public SizeF MeasureString(string text, Font font, SizeF layoutArea) + { + throw new NotImplementedException(); + } + + public SizeF MeasureString(string text, Font font, SizeF layoutArea, StringFormat stringFormat) + { + throw new NotImplementedException(); + } + + public SizeF MeasureString(string text, Font font) + { + throw new NotImplementedException(); + } + + public SizeF MeasureString(string text, Font font, int width) + { + throw new NotImplementedException(); + } + + public SizeF MeasureString(string text, Font font, int width, StringFormat format) + { + throw new NotImplementedException(); + } + + public Region[] MeasureCharacterRanges(string text, Font font, RectangleF layoutRect, StringFormat stringFormat) + { + throw new NotImplementedException(); + } + + public void SetClip(Graphics g) + { + throw new NotImplementedException(); + } + + public void SetClip(Graphics g, CombineMode combineMode) + { + throw new NotImplementedException(); + } + + public void SetClip(Rectangle rect) + { + throw new NotImplementedException(); + } + + public void SetClip(Rectangle rect, CombineMode combineMode) + { + throw new NotImplementedException(); + } + + public void SetClip(RectangleF rect) + { + throw new NotImplementedException(); + } + + public void SetClip(RectangleF rect, CombineMode combineMode) + { + throw new NotImplementedException(); + } + + public void SetClip(GraphicsPath path) + { + throw new NotImplementedException(); + } + + public void SetClip(GraphicsPath path, CombineMode combineMode) + { + throw new NotImplementedException(); + } + + public void SetClip(Region region, CombineMode combineMode) + { + throw new NotImplementedException(); + } + + public void IntersectClip(Rectangle rect) + { + throw new NotImplementedException(); + } + + public void IntersectClip(RectangleF rect) + { + throw new NotImplementedException(); + } + + public void IntersectClip(Region region) + { + throw new NotImplementedException(); + } + + public void ExcludeClip(Rectangle rect) + { + throw new NotImplementedException(); + } + + public void ExcludeClip(Region region) + { + throw new NotImplementedException(); + } + + public void ResetClip() + { + throw new NotImplementedException(); + } + + public void TranslateClip(float dx, float dy) + { + throw new NotImplementedException(); + } + + public void TranslateClip(int dx, int dy) + { + throw new NotImplementedException(); + } + + public bool IsVisible(int x, int y) + { + throw new NotImplementedException(); + } + + public bool IsVisible(Point point) + { + throw new NotImplementedException(); + } + + public bool IsVisible(float x, float y) + { + throw new NotImplementedException(); + } + + public bool IsVisible(PointF point) + { + throw new NotImplementedException(); + } + + public bool IsVisible(int x, int y, int width, int height) + { + throw new NotImplementedException(); + } + + public bool IsVisible(Rectangle rect) + { + throw new NotImplementedException(); + } + + public bool IsVisible(float x, float y, float width, float height) + { + throw new NotImplementedException(); + } + + public bool IsVisible(RectangleF rect) + { + throw new NotImplementedException(); + } + + public CompositingMode CompositingMode + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public Point RenderingOrigin + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public CompositingQuality CompositingQuality + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public TextRenderingHint TextRenderingHint + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public int TextContrast + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public SmoothingMode SmoothingMode + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public PixelOffsetMode PixelOffsetMode + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public InterpolationMode InterpolationMode + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public Matrix Transform + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public GraphicsUnit PageUnit + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public float PageScale + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public float DpiX + { + get { throw new NotImplementedException(); } + } + + public float DpiY + { + get { throw new NotImplementedException(); } + } + + public Region Clip + { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public RectangleF ClipBounds + { + get { throw new NotImplementedException(); } + } + + public bool IsClipEmpty + { + get { throw new NotImplementedException(); } + } + + public RectangleF VisibleClipBounds + { + get { throw new NotImplementedException(); } + } + + public bool IsVisibleClipEmpty + { + get { throw new NotImplementedException(); } + } + */ + + #endregion + + #region Helpers + + public void setPaintingEnabled(bool value) + { + isPaintingEnabled = value; + } + + public byte[] readoutQueuedCalls() + { + if (calls == null || calls.position() == 0) + { + return null; + } + var res = new byte[calls.position()]; + + calls.flip(); + calls.get(res); + + calls.clear(); + calls.put(calls.order() == ByteOrder.BIG_ENDIAN ? (byte) 1 : (byte) 0); + + return res; + } + + private void setColor(Brush brush) + { + var sb = brush as SolidBrush; + if (sb != null) + { + setColor(sb.Color); + } + } + + private void setColor(Pen p) + { + setColor(p.Color); + } + + private void setColor(Color c) + { + if (isPaintingEnabled) + { + calls.mark(); // Mark for rollback + try + { + put(Method.SET_COLOR); + put(c); + } + catch (BufferOverflowException) + { + if (recoverFromBufferOverflow()) + { + setColor(c); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + + private bool reallocBuffer() + { + int bufferSize; + + if (calls == null) + { + // No buffer -> Use initial buffer size + bufferSize = INITIAL_BUFFER_SIZE; + } + else + { + // Otherwise, double up capacity + bufferSize = 2*calls.capacity(); + } + + // Check if the max. buffer size has been reached + if (!isDebugging && bufferSize > MAX_BUFFER_SIZE) + { + return false; // not reallocated! + } + + // Allocate new buffer + ByteBuffer newBuffer = ByteBuffer.allocate(bufferSize); +// newBuffer.order(ByteOrder.LITTLE_ENDIAN); + + if (calls != null) + { + // Copy all bytes contained in the current buffer to the new buffer + + var copiedBytes = new byte[calls.position()]; + + calls.clear(); + calls.get(copiedBytes); + + newBuffer.put(copiedBytes); + } + + // Switch to the new buffer + calls = newBuffer; + + return true; // buffer was reallocated + } + + private bool recoverFromBufferOverflow() + { + calls.reset(); // Rollback buffer + + bool recovered = reallocBuffer(); + + if (!recovered) + { + if (unrecoveredBufferOverflowCount++ == 1) + { + // Prevent spamming + java.lang.System.@out.println( + "SYSTEM: This robot is painting too much between actions.\n" + + "SYSTEM: Max. buffer capacity (" + + MAX_BUFFER_SIZE + " bytes per turn) has been reached.\n" + + "SYSTEM: Last painting operations are being dropped.\n"); + } + } + return recovered; + } + + private void put(Method m) + { + // FOR-DEBUG calls.putInt(0xBADF00D); + calls.put((byte) m); + // FOR-DEBUG calls.putInt(0xBADF00D); + } + + private void put(String value) + { + serializer.serialize(calls, value); + } + + private void put(bool value) + { + serializer.serialize(calls, value); + } + + private void put(byte value) + { + calls.put(value); + } + + private void put(int value) + { + calls.putInt(value); + } + + private void put(int[] values) + { + serializer.serialize(calls, values); + } + + private void put(byte[] values) + { + serializer.serialize(calls, values); + } + + private void put(char[] values) + { + serializer.serialize(calls, values); + } + + private void put(double[] values) + { + serializer.serialize(calls, values); + } + + private void put(float[] values) + { + serializer.serialize(calls, values); + } + + private void put(double value) + { + calls.putDouble(value); + } + + private void put(float value) + { + calls.putFloat(value); + } + + private void put(Color value) + { + if (value == null) + { + calls.put((byte)0); + } + else + { + calls.put((byte)1); + calls.putInt(value.ToArgb()); + } + } + + private void put(Font font) + { + if (font == null) + { + calls.put((byte)0); + } + else + { + calls.put((byte)1); + serializer.serialize(calls, font.Name); + calls.putInt((int)font.Style); + calls.putInt((int)font.Size); + } + } + + #endregion + + #region Nested type: Method + + private enum Method + { + TRANSLATE_INT, // translate(int, int) + SET_COLOR, // setColor(Color) + SET_PAINT_MODE, // setPaintMode() + SET_XOR_MODE, // setXORMode(Color) + SET_FONT, // setFont(Font) + CLIP_RECT, // clipRect(int, int, int, int) + SET_CLIP, // setClip(int, int, int, int) + SET_CLIP_SHAPE, // setClip(Shape) + COPY_AREA, // copyArea(int, int, int, int, int, int) + DRAW_LINE, // drawLine(int, int, int, int) + FILL_RECT, // fillRect(int, int, int, int) + DRAW_RECT, // drawRect(int, int, int, int) + CLEAR_RECT, // clearRect(int, int, int, int) + DRAW_ROUND_RECT, // drawRoundRect(int, int, int, int, int, int) + FILL_ROUND_RECT, // fillRoundRect(int, int, int, int, int, int) + DRAW_3D_RECT, // draw3DRect(int, int, int, int, boolean) + FILL_3D_RECT, // draw3DRect(int, int, int, int, boolean) + DRAW_OVAL, // drawOval(int, int, int, int) + FILL_OVAL, // fillOval(int, int, int, int) + DRAW_ARC, // drawArc(int, int, int, int, int, int) + FILL_ARC, // fillArc(int, int, int, int, int, int) + DRAW_POLYLINE, // drawPolyline(int[], int[], int) + DRAW_POLYGON, // drawPolygon(int[], int[], int) + FILL_POLYGON, // fillPolygon(int[], int[], int) + DRAW_STRING_INT, // drawString(String, int, int) + DRAW_STRING_ACI_INT, // drawString(AttributedCharacterIterator, int, int) + DRAW_CHARS, // drawChars(char[], int, int, int, int) + DRAW_BYTES, // drawBytes(byte[], int, int, int, int) + DRAW_IMAGE_1, // drawImage(Image, int, int, ImageObserver) + DRAW_IMAGE_2, // drawImage(Image, int, int, int, int, ImageObserver) + DRAW_IMAGE_3, // drawImage(Image, int, int, Color, ImageObserver) + DRAW_IMAGE_4, // drawImage(Image, int, int, int, int, Color, ImageObserver) + DRAW_IMAGE_5, // drawImage(Image, int, int, int, int, int, int, int, int, ImageObserver) + DRAW_IMAGE_6, // drawImage(Image, int, int, int, int, int, int, int, int, Color, ImageObserver) + DRAW_SHAPE, // draw(Shape) + DRAW_IMAGE_7, // drawImage(Image, AffineTransform, ImageObserver) + DRAW_IMAGE_8, // drawImage(BufferedImage, BufferedImageOp, int, int) + DRAW_RENDERED_IMAGE, // drawRenderedImage(RenderedImage, AffineTransform) + DRAW_RENDERABLE_IMAGE, // drawRenderableImage(RenderableImage, AffineTransform) + DRAW_STRING_FLOAT, // drawString(String, float, float) + DRAW_STRING_ACI_FLOAT, // drawString(AttributedCharacterIterator, float, float) + DRAW_GLYPH_VECTOR, // drawGlyphVector(GlyphVector gv, float x, float y) + FILL_SHAPE, // fill(Shape) + SET_COMPOSITE, // setComposite(Composite) + SET_PAINT, // setPaint(Paint) + SET_STROKE, // setStroke(Stroke) + SET_RENDERING_HINT, // setRenderingHint(Key, Object) + SET_RENDERING_HINTS, // setRenderingHints(Map) + ADD_RENDERING_HINTS, // addRenderingHints(Map) + TRANSLATE_DOUBLE, // translate(double, double) + ROTATE, // rotate(double) + ROTATE_XY, // rotate(double, double, double) + SCALE, // scale(double, double) + SHEAR, // shear(double, double) + TRANSFORM, // transform(AffineTransform) + SET_TRANSFORM, // setTransform(AffineTransform Tx) + SET_BACKGROUND, // setBackground(Color) + CLIP, // clip(Shape) + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/HostingRobotProxy.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/HostingRobotProxy.cs new file mode 100644 index 0000000..ecbb9a2 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/HostingRobotProxy.cs @@ -0,0 +1,302 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Security; +using System.Security.Permissions; +using java.io; +using java.lang; +using net.sf.robocode.dotnet.host.events; +using net.sf.robocode.dotnet.host.security; +using net.sf.robocode.dotnet.peer; +using net.sf.robocode.host; +using net.sf.robocode.io; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using Robocode; +using robocode.exception; +using Robocode.Exception; +using Robocode.RobotInterfaces; +using Robocode.RobotInterfaces.Peer; +using Exception = System.Exception; +using String = System.String; +using StringBuilder = System.Text.StringBuilder; + +namespace net.sf.robocode.dotnet.host.proxies +{ + public abstract class HostingRobotProxy + { + private readonly IRobotItem robotSpecification; + + protected EventManager eventManager; + protected IHostManager hostManager; + protected RobotFileSystemManager robotFileSystemManager; + + protected IBasicRobot robot; + protected IRobotPeer peer; + private Type robotType; + + protected RobotStatics statics; + protected TextWriter output; + protected StringBuilder outputSb; + + private readonly Hashtable securityViolations = Hashtable.Synchronized(new Hashtable()); + + protected HostingRobotProxy(IRobotItem robotSpecification, IHostManager hostManager, IRobotPeer peer, + RobotStatics statics) + { + this.peer = peer; + this.statics = statics; + this.hostManager = hostManager; + this.robotSpecification = robotSpecification; + + outputSb = new StringBuilder(5000); + output = TextWriter.Synchronized(new StringWriter(outputSb)); + LoggerN.robotOut = output; + + robotFileSystemManager = new RobotFileSystemManager(this, (int) hostManager.getRobotFilesystemQuota(), + robotSpecification.getWritableDirectory(), + robotSpecification.getReadableDirectory()); + } + + public void setRobotType(Type robotType) + { + this.robotType = robotType; + } + + public virtual void cleanup() + { + robot = null; + + // Remove the file system and the manager + robotFileSystemManager.cleanup(); + robotFileSystemManager = null; + } + + public TextWriter GetOut() + { + return output; + } + + public void println(String s) + { + output.WriteLine(s); + } + + public void println(Exception ex) + { + output.WriteLine(ex); + } + + public void println(java.lang.String par0) + { + output.WriteLine(par0); + } + + public RobotStatics getStatics() + { + return statics; + } + + public RobotFileSystemManager getRobotFileSystemManager() + { + return robotFileSystemManager; + } + + public ClassLoader getRobotClassloader() + { + return null; + } + + // ----------- + // battle driven methods + // ----------- + + internal abstract void initializeRound(ExecCommands commands, RobotStatus status); + + [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)] + private bool loadRobotRound() + { + robot = null; + try + { + object instance = Activator.CreateInstance(robotType); + robot = instance as IBasicRobot; + if (robot == null) + { + println("SYSTEM: Skipping robot: " + statics.getName()); + return false; + } + robot.SetOut(output); + robot.SetPeer((IBasicRobotPeer) this); + Console.SetOut(output); + Console.SetError(output); + eventManager.SetRobot(robot); + } + + catch (MissingMethodException e) + { + punishSecurityViolation(statics.getName() + " " + e.Message); + return false; + } + catch (SecurityException e) + { + punishSecurityViolation(statics.getName() + " " + e.Message); + return false; + } + catch (Exception e) + { + if (e.InnerException is SecurityException) + { + + } + println("SYSTEM: An error occurred during initialization of " + statics.getName()); + println("SYSTEM: " + e); + println(e); + robot = null; + LoggerN.logMessage(e); + return false; + } + return true; + } + + protected abstract void executeImpl(); + + public void run() + { + peer.setRunning(true); + + if (robotSpecification.isValid() && loadRobotRound()) + { + try + { + if (robot != null) + { +// peer.setRunning(true); // Does not work with .NET version + + // Process all events for the first turn. + // This is done as the first robot status event must occur before the robot + // has started running. + eventManager.ProcessEvents(); + + // Call user code + CallUserCode(); + } + + // noinspection InfiniteLoopStatement + for (;;) + { + executeImpl(); + } + } + catch (WinException) + { + // Do nothing + } + catch (AbortedException) + { + // Do nothing + } + catch (DeathException) + { + println("SYSTEM: " + statics.getName() + " has died"); + } + catch (DisabledException e) + { + drainEnergy(); + + string msg = e.getMessage(); + if (msg == null) + { + msg = ""; + } + else + { + msg = ": " + msg; + } + println("SYSTEM: Robot disabled: " + msg); + LoggerN.logMessage("Robot disabled: " + statics.getName()); + } + catch (SecurityException e) + { + punishSecurityViolation(statics.getName() + " Exception: " + e); + } + catch (Exception e) + { + if (e.InnerException is SecurityException) + { + punishSecurityViolation(statics.getName() + " " + e.InnerException + " Exception: " + e); + } + else + { + drainEnergy(); + println(e); + LoggerN.logMessage(statics.getName() + ": Exception: " + e); // without stack here + } + } + finally + { + waitForBattleEndImpl(); + } + } + else + { + drainEnergy(); + peer.punishBadBehavior(BadBehavior.CANNOT_START); + waitForBattleEndImpl(); + } + + peer.setRunning(false); + } + + [SecurityPermission(SecurityAction.Deny)] + [ReflectionPermission(SecurityAction.Deny)] + [FileIOPermission(SecurityAction.Deny)] + [UIPermission(SecurityAction.Deny)] + private void CallUserCode() + { + IRunnable runnable = robot.GetRobotRunnable(); + + if (runnable != null) + { + runnable.Run(); + } + } + + protected abstract void waitForBattleEndImpl(); + + public void drainEnergy() + { + peer.drainEnergy(); + } + + public void punishSecurityViolation(java.lang.String message) + { + // Prevent unit tests of failing if multiple threads are calling this method in the same time. + // We only want the a specific type of security violation logged once so we only get one error + // per security violation. + lock (securityViolations) + { + if (!securityViolations.ContainsKey(message)) + { + securityViolations.Add(message, null); + LoggerN.logError(message); + println("SYSTEM: " + message); + + if (securityViolations.Count == 1) + { + peer.drainEnergy(); + peer.punishBadBehavior(BadBehavior.SECURITY_VIOLATION); + } + } + } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/JuniorRobotProxy.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/JuniorRobotProxy.cs new file mode 100644 index 0000000..c660779 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/JuniorRobotProxy.cs @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using net.sf.robocode.host; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using Robocode; +using Robocode.RobotInterfaces.Peer; +using Robocode.Util; + +namespace net.sf.robocode.dotnet.host.proxies +{ + internal class JuniorRobotProxy : BasicRobotProxy, IJuniorRobotPeer + { + public JuniorRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, + RobotStatics statics) + : base(specification, hostManager, peer, statics) + { + } + + #region IJuniorRobotPeer Members + + public void TurnAndMove(double distance, double radians) + { + if (distance == 0) + { + TurnBody(radians); + return; + } + + // Save current max. velocity and max. turn rate so they can be restored + double savedMaxVelocity = commands.getMaxVelocity(); + double savedMaxTurnRate = commands.getMaxTurnRate(); + + double absDegrees = Math.Abs(Utils.ToDegrees(radians)); + double absDistance = Math.Abs(distance); + + // -- Calculate max. velocity for moving perfect in a circle -- + + // maxTurnRate = 10 * 0.75 * velocity (Robocode rule), and + // maxTurnRate = velocity * degrees / distance (curve turn rate) + // + // Hence, max. velocity = 10 / (degrees / distance + 0.75) + + double maxVelocity = Math.Min(Rules.MAX_VELOCITY, 10/(absDegrees/absDistance + 0.75)); + + // -- Calculate number of turns for acceleration + deceleration -- + + double accDist = 0; // accumulated distance during acceleration + double decDist = 0; // accumulated distance during deceleration + + int turns = 0; // number of turns to it will take to move the distance + + // Calculate the amount of turn it will take to accelerate + decelerate + // up to the max. velocity, but stop if the distance for used for + // acceleration + deceleration gets bigger than the total distance to move + for (int t = 1; t < maxVelocity; t++) + { + // Add the current velocity to the acceleration distance + accDist += t; + + // Every 2nd time we add the deceleration distance needed to + // get to a velocity of 0 + if (t > 2 && (t%2) > 0) + { + decDist += t - 2; + } + + // Stop if the acceleration + deceleration > total distance to move + if ((accDist + decDist) >= absDistance) + { + break; + } + + // Increment turn for acceleration + turns++; + + // Every 2nd time we increment time for deceleration + if (t > 2 && (t%2) > 0) + { + turns++; + } + } + + // Add number of turns for the remaining distance at max velocity + if ((accDist + decDist) < absDistance) + { + turns += (int) ((absDistance - accDist - decDist)/maxVelocity + 1); + } + + // -- Move and turn in a curve -- + + // Set the calculated max. velocity + commands.setMaxVelocity(maxVelocity); + + // Set the robot to move the specified distance + setMoveImpl(distance); + // Set the robot to turn its body to the specified amount of radians + setTurnBodyImpl(radians); + + // Loop thru the number of turns it will take to move the distance and adjust + // the max. turn rate so it fit the current velocity of the robot + for (int t = turns; t >= 0; t--) + { + commands.setMaxTurnRate(GetVelocity()*radians/absDistance); + Execute(); // Perform next turn + } + + // Restore the saved max. velocity and max. turn rate + commands.setMaxVelocity(savedMaxVelocity); + commands.setMaxTurnRate(savedMaxTurnRate); + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/StandardRobotProxy.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/StandardRobotProxy.cs new file mode 100644 index 0000000..13162aa --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/StandardRobotProxy.cs @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using net.sf.robocode.dotnet.peer; +using net.sf.robocode.host; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using Robocode; +using Robocode.RobotInterfaces.Peer; + +namespace net.sf.robocode.dotnet.host.proxies +{ + internal class StandardRobotProxy : BasicRobotProxy, IStandardRobotPeer + { + private bool isStopped; + private double saveAngleToTurn; + private double saveDistanceToGo; + private double saveGunAngleToTurn; + private double saveRadarAngleToTurn; + + public StandardRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, + RobotStatics statics) + : base(specification, hostManager, peer, statics) + { + } + + + // blocking actions + + #region IStandardRobotPeer Members + + public void Stop(bool overwrite) + { + setStopImpl(overwrite); + Execute(); + } + + public void Resume() + { + setResumeImpl(); + Execute(); + } + + public void TurnRadar(double radians) + { + setTurnRadarImpl(radians); + do + { + Execute(); // Always tick at least once + } while (GetRadarTurnRemaining() != 0); + } + + // fast setters + public void SetAdjustGunForBodyTurn(bool newAdjustGunForBodyTurn) + { + SetCall(); + commands.setAdjustGunForBodyTurn(newAdjustGunForBodyTurn); + } + + public void SetAdjustRadarForGunTurn(bool newAdjustRadarForGunTurn) + { + SetCall(); + commands.setAdjustRadarForGunTurn(newAdjustRadarForGunTurn); + if (!commands.IsAdjustRadarForBodyTurnSet()) + { + commands.setAdjustRadarForBodyTurn(newAdjustRadarForGunTurn); + } + } + + public void SetAdjustRadarForBodyTurn(bool newAdjustRadarForBodyTurn) + { + SetCall(); + commands.setAdjustRadarForBodyTurn(newAdjustRadarForBodyTurn); + commands.setAdjustRadarForBodyTurnSet(true); + } + + public bool IsAdjustGunForBodyTurn() + { + GetCall(); + return commands.IsAdjustGunForBodyTurn(); + } + + public bool IsAdjustRadarForGunTurn() + { + GetCall(); + return commands.IsAdjustRadarForGunTurn(); + } + + public bool IsAdjustRadarForBodyTurn() + { + GetCall(); + return commands.IsAdjustRadarForBodyTurn(); + } + + #endregion + + internal override void initializeRound(ExecCommands commands, RobotStatus status) + { + base.initializeRound(commands, status); + isStopped = true; + } + + protected void setResumeImpl() + { + if (isStopped) + { + isStopped = false; + commands.setDistanceRemaining(saveDistanceToGo); + commands.setBodyTurnRemaining(saveAngleToTurn); + commands.setGunTurnRemaining(saveGunAngleToTurn); + commands.setRadarTurnRemaining(saveRadarAngleToTurn); + } + } + + protected void setStopImpl(bool overwrite) + { + if (!isStopped || overwrite) + { + saveDistanceToGo = GetDistanceRemaining(); + saveAngleToTurn = GetBodyTurnRemaining(); + saveGunAngleToTurn = GetGunTurnRemaining(); + saveRadarAngleToTurn = GetRadarTurnRemaining(); + } + isStopped = true; + + commands.setDistanceRemaining(0); + commands.setBodyTurnRemaining(0); + commands.setGunTurnRemaining(0); + commands.setRadarTurnRemaining(0); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/TeamRobotProxy.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/TeamRobotProxy.cs new file mode 100644 index 0000000..7215118 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/proxies/TeamRobotProxy.cs @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Security.Permissions; +using net.sf.robocode.dotnet.peer; +using net.sf.robocode.host; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using Robocode; +using Robocode.RobotInterfaces.Peer; + +namespace net.sf.robocode.dotnet.host.proxies +{ + internal class TeamRobotProxy : AdvancedRobotProxy, ITeamRobotPeer + { + private const int MAX_MESSAGE_SIZE = 32768; + + public TeamRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, + RobotStatics statics) + : base(specification, hostManager, peer, statics) + { + } + + // team + + #region ITeamRobotPeer Members + + public string[] GetTeammates() + { + GetCall(); + return statics.getTeammates(); + } + + public bool IsTeammate(String name) + { + GetCall(); + if (name == statics.getName()) + { + return true; + } + String[] teammates = statics.getTeammates(); + + if (teammates != null) + { + foreach (string mate in teammates) + { + if (mate == name) + { + return true; + } + } + } + return false; + } + + public void BroadcastMessage(object message) + { + SendMessage(null, message); + } + + [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)] + public void SendMessage(String name, object message) + { + SetCall(); + + try + { + if (!statics.IsTeamRobot()) + { + throw new IOException("You are not on a team."); + } + using (var byteStreamWriter = new MemoryStream(MAX_MESSAGE_SIZE)) + { + var bf = new BinaryFormatter(new SerializationGuard(), new StreamingContext()); + bf.Serialize(byteStreamWriter, message); + byte[] bytes = byteStreamWriter.ToArray(); + commands.getTeamMessages().Add(new TeamMessage(GetName(), name, bytes)); + } + } + catch (Exception e) + { + output.WriteLine(e); + throw; + } + } + + // events + public IList GetMessageEvents() + { + GetCall(); + return eventManager.GetMessageEvents(); + } + + #endregion + + [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)] + protected override sealed void loadTeamMessages(List teamMessages) + { + if (teamMessages == null) + { + return; + } + foreach (TeamMessage teamMessage in teamMessages) + { + try + { + using (var ms = new MemoryStream(teamMessage.message)) + { + var bf = new BinaryFormatter(); + object message = bf.Deserialize(ms); + var evnt = new MessageEvent(teamMessage.sender, message); + + eventManager.Add(evnt); + } + } + catch (Exception e) + { + output.WriteLine(e); + } + } + } + + #region Nested type: SerializationGuard + + private class SerializationGuard : SurrogateSelector + { + public override ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, + out ISurrogateSelector selector) + { + if (typeof (MarshalByRefObject).IsAssignableFrom(type)) + { + throw new AccessViolationException("Messages should not contain MarshalByRefObject objects"); + } + return base.GetSurrogate(type, context, out selector); + } + } + + #endregion + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/security/QuotaStream.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/security/QuotaStream.cs new file mode 100644 index 0000000..96e9df0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/security/QuotaStream.cs @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.IO; +using System.Runtime.Remoting; +using System.Threading; +using Microsoft.Win32.SafeHandles; + +namespace net.sf.robocode.dotnet.host.security +{ + internal class QuotaStream : FileStream + { + private readonly RobotFileSystemManager manager; + + public QuotaStream(RobotFileSystemManager manager, String path, FileMode mode, FileAccess access, + FileShare share) + : base(path, mode, access, share) + { + this.manager = manager; + } + + [Obsolete] + public override IntPtr Handle + { + get { throw new AccessViolationException(); } + } + + public override SafeFileHandle SafeFileHandle + { + get { throw new AccessViolationException(); } + } + + public override void SetLength(long value) + { + manager.appendQuotaUsed(value - Length); + base.SetLength(value); + } + + public override void WriteByte(byte value) + { + long delta = Position + 1 - Length; + if (delta > 0) + { + manager.appendQuotaUsed(delta); + } + base.WriteByte(value); + } + + public override void Write(byte[] array, int offset, int count) + { + long delta = Position + count - Length; + if (delta > 0) + { + manager.appendQuotaUsed(delta); + } + base.Write(array, offset, count); + } + + public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback userCallback, + object stateObject) + { + long delta = Position + numBytes - Length; + if (delta > 0) + { + manager.appendQuotaUsed(delta); + } + return base.BeginWrite(array, offset, numBytes, userCallback, stateObject); + } + + /*public override long Position + { + get { return base.Position; } + set + { + base.Position = value; + } + } + + public override long Seek(long offset, SeekOrigin origin) + { + return base.Seek(offset, origin); + }*/ + + public override ObjRef CreateObjRef(Type requestedType) + { + throw new AccessViolationException(); + } + + [Obsolete] + protected override WaitHandle CreateWaitHandle() + { + throw new AccessViolationException(); + } + + public override object InitializeLifetimeService() + { + throw new AccessViolationException(); + } + + public override void Lock(long position, long length) + { + throw new AccessViolationException(); + } + + public override void Unlock(long position, long length) + { + throw new AccessViolationException(); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/security/RobotFileSystemManager.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/security/RobotFileSystemManager.cs new file mode 100644 index 0000000..15f456c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/security/RobotFileSystemManager.cs @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Security.Permissions; +using net.sf.robocode.dotnet.host.proxies; +using net.sf.robocode.io; + +namespace net.sf.robocode.dotnet.host.security +{ + [FileIOPermission(SecurityAction.Assert, Unrestricted = true)] + public class RobotFileSystemManager + { + private long maxQuota; + private string readableRootDirectory; + private List streams = new List(); + private long usedQuota; + private string writableRootDirectory; + private HostingRobotProxy hostingProxy; + + public RobotFileSystemManager(HostingRobotProxy hostingProxy , int maxQuota, string writableRootDirectory, string readableRootDirectory) + { + this.hostingProxy = hostingProxy; + this.maxQuota = maxQuota; + this.writableRootDirectory = Path.GetFullPath(writableRootDirectory); + this.readableRootDirectory = Path.GetFullPath(readableRootDirectory); + + if (Directory.Exists(writableRootDirectory)) + { + var di = new DirectoryInfo(writableRootDirectory); + foreach (FileInfo file in di.GetFiles()) + { + usedQuota += file.Length; + } + } + } + + public long getMaxQuota() + { + return maxQuota; + } + + public long getQuotaUsed() + { + lock (this) + { + return usedQuota; + } + } + + public long appendQuotaUsed(long bytes) + { + lock (this) + { + if (usedQuota + bytes > maxQuota) + { + string message = "You have reached your filesystem quota: " + maxQuota + " bytes per robot."; + if (hostingProxy != null) + { + hostingProxy.punishSecurityViolation(message); + } + throw new AccessViolationException(message); + } + usedQuota += bytes; + return usedQuota; + } + } + + public long getDataQuotaAvailable() + { + return maxQuota - getQuotaUsed(); + } + + public Stream getDataFile(string filename) + { + lock (this) + { + if (Path.IsPathRooted(filename)) + { + filename = Path.GetFullPath(filename); + } + else + { + filename = Path.GetFullPath(Path.Combine(writableRootDirectory, Path.GetFileName(filename))); + } + if (Path.GetDirectoryName(filename).ToLower() != writableRootDirectory.ToLower()) + { + throw new AccessViolationException("Access is allowed only in " + writableRootDirectory + ". Use "); + } + if (!Directory.Exists(writableRootDirectory)) + { + Directory.CreateDirectory(writableRootDirectory); + } + var quotaStream = new QuotaStream(this, filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, + FileShare.ReadWrite); + streams.Add(quotaStream); + return quotaStream; + } + } + + public string getReadableDirectory() + { + return readableRootDirectory; + } + + public string getWritableDirectory() + { + return writableRootDirectory; + } + + public void cleanup() + { + foreach (QuotaStream stream in streams) + { + try + { + stream.Dispose(); + } + catch (Exception ex) + { + LoggerN.logError(ex); + } + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/AppDomainSeed.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/AppDomainSeed.cs new file mode 100644 index 0000000..a5030dc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/AppDomainSeed.cs @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.IO; +using System.Reflection; +using System.Security; +using System.Security.Permissions; +using java.nio; +using net.sf.jni4net; +using net.sf.jni4net.jni; +using net.sf.jni4net.nio; +using net.sf.jni4net.utils; +using net.sf.robocode.dotnet.utils; +using net.sf.robocode.io; +using net.sf.robocode.repository; +using net.sf.robocode.serialization; +using Buffer = java.nio.Buffer; +using ByteBuffer = java.nio.ByteBuffer; +using Exception = System.Exception; +using StringBuilder = System.Text.StringBuilder; +using robocode.control; + +namespace net.sf.robocode.dotnet.host.seed +{ + [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)] + [FileIOPermission(SecurityAction.Assert, Unrestricted = true)] + public class AppDomainSeed + { + protected static string robotAssemblyFileName; + protected static string robotAssemblyShadowFileName; + protected static AppDomain domain; + + public static void Load(string[] args) + { + try + { + domain = AppDomain.CurrentDomain; + domain.UnhandledException += (domain_UnhandledException); + domain.AssemblyLoad += (domain_AssemblyLoad); + } + catch (Exception ex) + { + LoggerN.logError(ex); + throw; + } + } + + static void domain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + LoggerN.logError(e.ExceptionObject.ToString()); + } + + static void domain_AssemblyLoad(object sender, AssemblyLoadEventArgs args) + { + bool knownLocation = args.LoadedAssembly.Location != null && + robotAssemblyShadowFileName != null && + Path.GetFullPath(args.LoadedAssembly.Location).ToLower() == + Path.GetFullPath(robotAssemblyShadowFileName).ToLower(); + if (args.LoadedAssembly != typeof(Bridge).Assembly && + args.LoadedAssembly != typeof(AppDomainSeed).Assembly && + args.LoadedAssembly != typeof(RobocodeEngine).Assembly && + !knownLocation && + !args.LoadedAssembly.GlobalAssemblyCache) + { + string message = "dependent assemblies are not alowed" + args.LoadedAssembly.Location; + LoggerN.logError(message); + throw new SecurityException(message); + } + } + + public static void Open() + { + try + { + robotAssemblyFileName = (string)domain.GetData("robotAssemblyFileName"); + robotAssemblyShadowFileName = (string)domain.GetData("robotAssemblyShadowFileName"); + } + catch (Exception ex) + { + LoggerN.logError(ex); + throw; + } + } + + public static void Bind() + { + try + { + bool fullBind = (bool)domain.GetData("fullBind"); + if (fullBind) + { + var setup = new BridgeSetup(false); + setup.BindCoreOnly = true; + setup.BindNative = false; + setup.BindStatic = false; + setup.JavaHome = (string)domain.GetData("JavaHome"); + Bridge.CreateJVM(setup); + JNIEnv env = JNIEnv.ThreadEnv; + Registry.RegisterType(typeof(ByteBuffer), true, env); + Registry.RegisterType(typeof(Buffer), true, env); + Registry.RegisterType(typeof(DirectByteBuffer), true, env); + Registry.RegisterType(typeof(java.lang.System), true, env); + Registry.RegisterType(typeof(ByteOrder), true, env); + Bridge.RegisterAssembly(typeof(RbSerializer).Assembly); + } + } + catch (Exception ex) + { + LoggerN.logError(ex); + throw; + } + } + + public static void FindRobots() + { + try + { + var sb = new StringBuilder(); + Assembly assembly = Assembly.LoadFrom(robotAssemblyShadowFileName); + foreach (Type type in assembly.GetTypes()) + { + if (Reflection.CheckInterfaces(type) != RobotTypeN.INVALID) + { + sb.Append("file://"); + sb.Append(robotAssemblyFileName); + sb.Append("!/"); + sb.Append(type.FullName); + sb.Append(";"); + } + } + if (sb.Length > 0) + { + sb.Length--; + } + domain.SetData("robotsFound", sb.ToString()); + } + catch (Exception ex) + { + LoggerN.logError(ex); + throw; + } + } + + + public static void GetRobotType() + { + try + { + var robotFullName = (string) domain.GetData("loadRobot"); + Assembly assembly = Assembly.LoadFrom(robotAssemblyShadowFileName); + Reflection.CheckAssembly(assembly); + Type robotType = assembly.GetType(robotFullName, false); + if (robotType != null) + { + domain.SetData("robotLoaded", (int)Reflection.CheckInterfaces(robotType)); + } + } + catch (Exception ex) + { + domain.SetData("robotLoaded", 0); + LoggerN.logError(ex); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/AppDomainShell.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/AppDomainShell.cs new file mode 100644 index 0000000..117db9e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/AppDomainShell.cs @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.IO; +using System.Reflection; +using System.Security; +using System.Security.Permissions; +using System.Security.Policy; +using net.sf.jni4net; +using net.sf.robocode.dotnet.utils; +using net.sf.robocode.io; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using Robocode; +using robocode.control; + +namespace net.sf.robocode.dotnet.host.seed +{ + public class AppDomainShell : IDisposable + { + private static readonly Assembly robocodeAssembly = typeof (Robot).Assembly; + private static readonly Assembly controlAssembly = typeof (RobocodeEngine).Assembly; + private static readonly Assembly hostAssembly = typeof(AppDomainShell).Assembly; + private static readonly Assembly jniAssembly = typeof(Bridge).Assembly; + protected AppDomain domain; + private string robotAssemblyFileName; + protected IRobotPeer robotPeer; + private string robotShadow; + private string tempDir; + + #region IDisposable Members + + public void Dispose() + { + if (domain != null) + { + try + { + AppDomain.Unload(domain); + domain = null; + GC.Collect(); + } + catch (Exception ex) + { + LoggerN.logError(ex); + if (robotPeer != null) + { + robotPeer.punishBadBehavior(BadBehavior.UNSTOPPABLE); + } + } + } + if (tempDir != null && Directory.Exists(tempDir)) + { + try + { + Directory.Delete(tempDir, true); + } + catch (IOException) + { + //ignore + } + catch (UnauthorizedAccessException) + { + //ignore + } + tempDir = null; + } + } + + #endregion + + public void Init(bool fullBind) + { + string name = Path.GetRandomFileName(); + tempDir = Path.Combine(Path.GetTempPath(), name); + string robocodeShadow = Path.Combine(tempDir, Path.GetFileName(robocodeAssembly.Location)); + string hostShadow = Path.Combine(tempDir, Path.GetFileName(hostAssembly.Location)); + string controlShadow = Path.Combine(tempDir, Path.GetFileName(controlAssembly.Location)); + string jniShadow = Path.Combine(tempDir, Path.GetFileName(jniAssembly.Location)); + + Directory.CreateDirectory(tempDir); + File.Copy(robocodeAssembly.Location, robocodeShadow); + File.Copy(controlAssembly.Location, controlShadow); + File.Copy(hostAssembly.Location, hostShadow); + File.Copy(jniAssembly.Location, jniShadow); + + var trustAssemblies = new[] + { + Reflection.GetStrongName(robocodeAssembly), + Reflection.GetStrongName(controlAssembly), + Reflection.GetStrongName(hostAssembly), + Reflection.GetStrongName(jniAssembly), + }; + var domainSetup = new AppDomainSetup(); + Evidence securityInfo = AppDomain.CurrentDomain.Evidence; + var permissionSet = new PermissionSet(PermissionState.None); + permissionSet.AddPermission( + new SecurityPermission(SecurityPermissionFlag.Execution | SecurityPermissionFlag.Assertion)); + permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, tempDir)); + permissionSet.AddPermission(new UIPermission(PermissionState.None)); + //permissionSet.AddPermission(HostProtection); + + domainSetup.ApplicationBase = tempDir; + + domainSetup.ApplicationName = name; + //domainSetup.SandboxInterop = true; + domainSetup.DisallowBindingRedirects = true; + domainSetup.DisallowCodeDownload = true; + domainSetup.DisallowPublisherPolicy = true; + domainSetup.AppDomainInitializer = AppDomainSeed.Load; + + + domain = AppDomain.CreateDomain(name, securityInfo, domainSetup, permissionSet, trustAssemblies); + domain.SetData("fullBind", fullBind); + domain.SetData("JavaHome", Bridge.Setup.JavaHome); + domain.DoCallBack(AppDomainSeed.Bind); + } + + public void Open(string dllName) + { + robotAssemblyFileName = Path.GetFullPath(dllName); + robotShadow = Path.Combine(tempDir, Path.GetFileName(robotAssemblyFileName)); + if (!File.Exists(robotShadow)) + { + File.Copy(robotAssemblyFileName, robotShadow); + } + domain.SetData("robotAssemblyFileName", robotAssemblyFileName); + domain.SetData("robotAssemblyShadowFileName", robotShadow); + domain.DoCallBack(AppDomainSeed.Open); + } + + + public string[] FindRobots() + { + domain.DoCallBack(AppDomainSeed.FindRobots); + object data = domain.GetData("robotsFound"); + string[] robotsFound = data == null ? new string[] {} : ((string) data).Split(';'); + return robotsFound; + } + + public RobotType GetRobotType(string typeFullName) + { + domain.SetData("loadRobot", typeFullName); + domain.DoCallBack(AppDomainSeed.GetRobotType); + object data = domain.GetData("robotLoaded"); + if (data==null) + { + return RobotType.Invalid; + } + var type = (int) data; + if (type == 0) + { + return RobotType.Invalid; + } + return new RobotType(type); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/HostingSeed.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/HostingSeed.cs new file mode 100644 index 0000000..b4e6c69 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/HostingSeed.cs @@ -0,0 +1,183 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Globalization; +using System.Reflection; +using System.Security.Permissions; +using System.Threading; +using net.sf.jni4net; +using net.sf.jni4net.jni; +using net.sf.jni4net.utils; +using net.sf.robocode.dotnet.host.proxies; +using net.sf.robocode.dotnet.nhost; +using net.sf.robocode.dotnet.peer; +using net.sf.robocode.dotnet.utils; +using net.sf.robocode.host; +using net.sf.robocode.io; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using net.sf.robocode.security; +using Robocode; +using Thread = System.Threading.Thread; + +namespace net.sf.robocode.dotnet.host.seed +{ + [ReflectionPermission(SecurityAction.Assert, Unrestricted = true)] + [FileIOPermission(SecurityAction.Assert, Unrestricted = true)] + [SecurityPermission(SecurityAction.Assert, Unrestricted = true)] + public class HostingSeed : AppDomainSeed + { + private static IHostManager hostManager; + private static IRobotPeer robotPeer; + private static RobotStatics statics; + private static IRobotItem specification; + private static Type robotType; + private static Thread robotThread; + private static HostingRobotProxy robotProxy; + + public static void Construct() + { + try + { + ModuleN.InitN(); + + JNIEnv env = JNIEnv.ThreadEnv; + JniGlobalHandle hmHandle = env.NewGlobalRef((JniHandle)domain.GetData("hostManager")); + JniGlobalHandle peerHandle = env.NewGlobalRef((JniHandle)domain.GetData("peer")); + JniGlobalHandle itemHandle = env.NewGlobalRef((JniHandle)domain.GetData("item")); + hostManager = Bridge.CreateProxy(hmHandle); + robotPeer = Bridge.CreateProxy(peerHandle); + specification = Bridge.CreateProxy(itemHandle); + + statics = ((RobotStatics)domain.GetData("statics")); + CreateProxy(); + + Assembly assembly = Assembly.LoadFrom(robotAssemblyShadowFileName); + Reflection.CheckAssembly(assembly); + string robotFullName = specification.getFullClassName(); + robotType = assembly.GetType(robotFullName, false); + robotProxy.setRobotType(robotType); + } + catch (Exception ex) + { + LoggerN.logError(ex); + throw; + } + } + + public static void StartRound() + { + try + { + var commands = (ExecCommands) domain.GetData("commands"); + var status = (RobotStatus) domain.GetData("status"); + + robotProxy.initializeRound(commands, status); + + robotThread = new Thread(RobotMain); + robotThread.CurrentCulture = CultureInfo.InvariantCulture; + robotThread.CurrentUICulture = CultureInfo.InvariantCulture; + robotThread.Start(null); + robotThread.Name = "Robot: "+robotProxy.getStatics().getName(); + } + catch (Exception ex) + { + LoggerN.logError(ex); + throw; + } + } + + private static void RobotMain(object param) + { + try + { + robotPeer.setupThread(); + robotProxy.run(); + } + catch(Exception ex) + { + robotProxy.println(ex); + } + finally + { + JNIEnv.ThreadEnv.GetJavaVM().DetachCurrentThread(); + } + } + + public static void ForceStopThread() + { + try + { + LoggerN.logMessage(HiddenAccessN.GetRobotName() + " is not stopping. Forcing a stop."); + robotThread.Priority = ThreadPriority.Lowest; + robotThread.Abort(); + robotThread.Interrupt(); + } + catch (Exception ex) + { + LoggerN.logError(ex); + throw; + } + } + + public static void WaitForStopThread() + { + try + { + if (!robotThread.Join(1000)) + { + LoggerN.logError("Unable to stop thread for "+statics.getName()); + robotPeer.punishBadBehavior(BadBehavior.UNSTOPPABLE); + robotPeer.setRunning(false); + } + } + catch (Exception ex) + { + LoggerN.logError(ex); + throw; + } + } + + public static void Cleanup() + { + try + { + robotProxy.cleanup(); + } + catch (Exception ex) + { + LoggerN.logError(ex); + throw; + } + } + + private static void CreateProxy() + { + if (specification.isTeamRobot()) + { + robotProxy = new TeamRobotProxy(specification, hostManager, robotPeer, statics); + } + else if (specification.isAdvancedRobot()) + { + robotProxy = new AdvancedRobotProxy(specification, hostManager, robotPeer, statics); + } + else if (specification.isStandardRobot()) + { + robotProxy = new StandardRobotProxy(specification, hostManager, robotPeer, statics); + } + else if (specification.isJuniorRobot()) + { + robotProxy = new JuniorRobotProxy(specification, hostManager, robotPeer, statics); + } + else + { + throw new AccessViolationException("Unknown robot type"); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/HostingShell.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/HostingShell.cs new file mode 100644 index 0000000..3495893 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/host/seed/HostingShell.cs @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using java.lang; +using net.sf.jni4net.jni; +using net.sf.jni4net.utils; +using net.sf.robocode.dotnet.peer; +using net.sf.robocode.host; +using net.sf.robocode.host.proxies; +using net.sf.robocode.peer; +using net.sf.robocode.repository; +using net.sf.robocode.serialization; +using Robocode; + +namespace net.sf.robocode.dotnet.host.seed +{ + public class HostingShell : AppDomainShell, IHostingRobotProxy + { + private readonly RbSerializer serializer = new RbSerializer(); + + public HostingShell(IRobotItem itemSpecification, + IHostManager hostManager, IRobotPeer peer, + IRobotStatics jstatics, string dllFileName) + { + robotPeer = peer; + + Init(true); + Open(dllFileName); + JniGlobalHandle hmHandle = ((IJvmProxy) hostManager).JvmHandle; + JniGlobalHandle peerhandle = ((IJvmProxy)peer).JvmHandle; + JniGlobalHandle itemHandle = ((IJvmProxy)itemSpecification).JvmHandle; + + domain.SetData("hostManager", hmHandle.DangerousGetHandle()); + domain.SetData("peer", peerhandle.DangerousGetHandle()); + domain.SetData("item", itemHandle.DangerousGetHandle()); + + var statics = serializer.ConvertJ2C(RbSerializerN.RobotStatics_TYPE, (Object) jstatics); + domain.SetData("statics", statics); + domain.SetData("robotName", statics.getName()); + try + { + domain.DoCallBack(HostingSeed.Construct); + } + catch (Exception) + { + robotPeer.punishBadBehavior(BadBehavior.SECURITY_VIOLATION); + } + + hmHandle.HoldThisHandle(); + peerhandle.HoldThisHandle(); + itemHandle.HoldThisHandle(); + } + + #region IHostingRobotProxy Members + + public void startRound(Object aCommands, Object aStatus) + { + var commands = serializer.ConvertJ2C(RbSerializerN.ExecCommands_TYPE, aCommands); + var status = serializer.ConvertJ2C(RbSerializerN.RobotStatus_TYPE, aStatus); + + domain.SetData("commands", commands); + domain.SetData("status", status); + domain.DoCallBack(HostingSeed.StartRound); + } + + public void forceStopThread() + { + domain.DoCallBack(HostingSeed.ForceStopThread); + } + + public void waitForStopThread() + { + domain.DoCallBack(HostingSeed.WaitForStopThread); + } + + public void cleanup() + { + domain.DoCallBack(HostingSeed.Cleanup); + Dispose(); + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/io/Logger.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/io/Logger.cs new file mode 100644 index 0000000..5e64e0a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/io/Logger.cs @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using java.lang; + +namespace net.sf.robocode.io +{ + partial class Logger : ILoggerN + { + public Logger(bool fakeInstance) + { + } + + #region ILoggerN Members + + public void logMessage(string s, bool newline) + { + logMessage((String) s, newline); + } + + public void logError(string s) + { + logError((String) s); + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/mono/reflection/CILReader.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/mono/reflection/CILReader.cs new file mode 100644 index 0000000..c864bdc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/mono/reflection/CILReader.cs @@ -0,0 +1,419 @@ +// +// MethodBaseRocks.cs +// +// Author: +// Jb Evain (jbevain@novell.com) +// +// (C) 2009 Novell, Inc. (http://www.novell.com) +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; + +namespace Mono.Reflection +{ + public sealed class Instruction + { + private readonly int offset; + private OpCode opcode; + private object operand; + + public int Offset + { + get { return offset; } + } + + public OpCode OpCode + { + get { return opcode; } + } + + public object Operand + { + get { return operand; } + internal set { operand = value; } + } + + public Instruction Previous { get; internal set; } + + public Instruction Next { get; internal set; } + + internal Instruction(int offset, OpCode opcode) + { + this.offset = offset; + this.opcode = opcode; + } + + public int GetSize() + { + int size = opcode.Size; + + switch (opcode.OperandType) + { + case OperandType.InlineSwitch: + size += (1 + ((int[]) operand).Length)*4; + break; + case OperandType.InlineI8: + case OperandType.InlineR: + size += 8; + break; + case OperandType.InlineBrTarget: + case OperandType.InlineField: + case OperandType.InlineI: + case OperandType.InlineMethod: + case OperandType.InlineString: + case OperandType.InlineTok: + case OperandType.InlineType: + case OperandType.ShortInlineR: + size += 4; + break; + case OperandType.InlineVar: + size += 2; + break; + case OperandType.ShortInlineBrTarget: + case OperandType.ShortInlineI: + case OperandType.ShortInlineVar: + size += 1; + break; + } + + return size; + } + + public override string ToString() + { + return opcode.Name; + } + } + + internal class MethodBodyReader + { + private static readonly OpCode[] one_byte_opcodes; + private static readonly OpCode[] two_bytes_opcodes; + + static MethodBodyReader() + { + one_byte_opcodes = new OpCode[0xe1]; + two_bytes_opcodes = new OpCode[0x1f]; + + var fields = GetOpCodeFields(); + + foreach (FieldInfo t in fields) + { + var opcode = (OpCode) t.GetValue(null); + if (opcode.OpCodeType == OpCodeType.Nternal) + continue; + + if (opcode.Size == 1) + one_byte_opcodes[opcode.Value] = opcode; + else + two_bytes_opcodes[opcode.Value & 0xff] = opcode; + } + } + + private static IEnumerable GetOpCodeFields() + { + return typeof (OpCodes).GetFields(BindingFlags.Public | BindingFlags.Static); + } + + private class ByteBuffer + { + internal readonly byte[] buffer; + internal int position; + + public ByteBuffer(byte[] buffer) + { + this.buffer = buffer; + } + + public byte ReadByte() + { + CheckCanRead(1); + return buffer[position++]; + } + + private byte[] ReadBytes(int length) + { + CheckCanRead(length); + var value = new byte[length]; + Buffer.BlockCopy(buffer, position, value, 0, length); + position += length; + return value; + } + + public short ReadInt16() + { + CheckCanRead(2); + short value = (short) (buffer[position] + | (buffer[position + 1] << 8)); + position += 2; + return value; + } + + public int ReadInt32() + { + CheckCanRead(4); + int value = buffer[position] + | (buffer[position + 1] << 8) + | (buffer[position + 2] << 16) + | (buffer[position + 3] << 24); + position += 4; + return value; + } + + public long ReadInt64() + { + CheckCanRead(8); + uint low = (uint) (buffer[position] + | (buffer[position + 1] << 8) + | (buffer[position + 2] << 16) + | (buffer[position + 3] << 24)); + + uint high = (uint) (buffer[position + 4] + | (buffer[position + 5] << 8) + | (buffer[position + 6] << 16) + | (buffer[position + 7] << 24)); + + long value = (((long) high) << 32) | low; + position += 8; + return value; + } + + public float ReadSingle() + { + if (!BitConverter.IsLittleEndian) + { + var bytes = ReadBytes(4); + Array.Reverse(bytes); + return BitConverter.ToSingle(bytes, 0); + } + + CheckCanRead(4); + float value = BitConverter.ToSingle(buffer, position); + position += 4; + return value; + } + + public double ReadDouble() + { + if (!BitConverter.IsLittleEndian) + { + var bytes = ReadBytes(8); + Array.Reverse(bytes); + return BitConverter.ToDouble(bytes, 0); + } + + CheckCanRead(8); + double value = BitConverter.ToDouble(buffer, position); + position += 8; + return value; + } + + private void CheckCanRead(int count) + { + if (position + count > buffer.Length) + throw new ArgumentOutOfRangeException(); + } + } + + private readonly MethodBase method; + private readonly MethodBody body; + private readonly Module module; + private readonly Type[] generic_type_arguments; + private readonly Type[] method_arguments; + private readonly ByteBuffer il; + private readonly ParameterInfo[] parameters; + private readonly IList locals; + private readonly List instructions = new List(); + + private MethodBodyReader(MethodBase method, MethodBody mb) + { + this.method = method; + + body = mb; + if (body == null) + throw new ArgumentException(); + + var bytes = body.GetILAsByteArray(); + if (bytes == null) + throw new ArgumentException(); + + if (!(method is ConstructorInfo)) + method_arguments = method.GetGenericArguments(); + + if (method.DeclaringType != null) + generic_type_arguments = method.DeclaringType.GetGenericArguments(); + + parameters = method.GetParameters(); + locals = body.LocalVariables; + module = method.Module; + il = new ByteBuffer(bytes); + } + + private void ReadInstructions() + { + Instruction previous = null; + + while (il.position < il.buffer.Length) + { + var instruction = new Instruction(il.position, ReadOpCode()); + + ReadOperand(instruction); + + if (previous != null) + { + instruction.Previous = previous; + previous.Next = instruction; + } + + instructions.Add(instruction); + previous = instruction; + } + } + + private void ReadOperand(Instruction instruction) + { + switch (instruction.OpCode.OperandType) + { + case OperandType.InlineNone: + break; + case OperandType.InlineSwitch: + int length = il.ReadInt32(); + int[] branches = new int[length]; + int[] offsets = new int[length]; + for (int i = 0; i < length; i++) + offsets[i] = il.ReadInt32(); + for (int i = 0; i < length; i++) + branches[i] = il.position + offsets[i]; + + instruction.Operand = branches; + break; + case OperandType.ShortInlineBrTarget: + instruction.Operand = (sbyte) (il.ReadByte() + il.position); + break; + case OperandType.InlineBrTarget: + instruction.Operand = il.ReadInt32() + il.position; + break; + case OperandType.ShortInlineI: + if (instruction.OpCode == OpCodes.Ldc_I4_S) + instruction.Operand = (sbyte) il.ReadByte(); + else + instruction.Operand = il.ReadByte(); + break; + case OperandType.InlineI: + instruction.Operand = il.ReadInt32(); + break; + case OperandType.ShortInlineR: + instruction.Operand = il.ReadSingle(); + break; + case OperandType.InlineR: + instruction.Operand = il.ReadDouble(); + break; + case OperandType.InlineI8: + instruction.Operand = il.ReadInt64(); + break; + case OperandType.InlineSig: + byte[] resolveSignature = module.ResolveSignature(il.ReadInt32()); + instruction.Operand = resolveSignature; + break; + case OperandType.InlineString: + string resolveString = module.ResolveString(il.ReadInt32()); + instruction.Operand = resolveString; + break; + case OperandType.InlineTok: + MemberInfo resolveMember = module.ResolveMember(il.ReadInt32(), generic_type_arguments, method_arguments); + instruction.Operand = resolveMember; + break; + case OperandType.InlineType: + Type resolveType = module.ResolveType(il.ReadInt32(), generic_type_arguments, method_arguments); + instruction.Operand = resolveType; + break; + case OperandType.InlineMethod: + MethodBase resolveMethod = module.ResolveMethod(il.ReadInt32(), generic_type_arguments, method_arguments); + instruction.Operand = resolveMethod; + break; + case OperandType.InlineField: + FieldInfo resolveField = module.ResolveField(il.ReadInt32(), generic_type_arguments, method_arguments); + instruction.Operand = resolveField; + break; + case OperandType.ShortInlineVar: + object variable = GetVariable(instruction, il.ReadByte()); + instruction.Operand = variable; + break; + case OperandType.InlineVar: + object operand = GetVariable(instruction, il.ReadInt16()); + instruction.Operand = operand; + break; + default: + throw new NotSupportedException(); + } + } + + private object GetVariable(Instruction instruction, int index) + { + if (TargetsLocalVariable(instruction.OpCode)) + return GetLocalVariable(index); + return GetParameter(index); + } + + private static bool TargetsLocalVariable(OpCode opcode) + { + return opcode.Name.Contains("loc"); + } + + private LocalVariableInfo GetLocalVariable(int index) + { + return locals[index]; + } + + private ParameterInfo GetParameter(int index) + { + if (!method.IsStatic) + index--; + + return parameters[index]; + } + + private OpCode ReadOpCode() + { + byte op = il.ReadByte(); + return op != 0xfe + ? one_byte_opcodes[op] + : two_bytes_opcodes[il.ReadByte()]; + } + + public static IList GetInstructions(MethodBase method) + { + var mb = method.GetMethodBody(); + if (mb == null) + { + return new List(); + } + var reader = new MethodBodyReader(method, mb); + reader.ReadInstructions(); + return reader.instructions; + } + + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/BulletCommand.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/BulletCommand.cs new file mode 100644 index 0000000..5784e15 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/BulletCommand.cs @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using net.sf.robocode.nio; +using net.sf.robocode.serialization; + +namespace net.sf.robocode.dotnet.peer +{ + [Serializable] + public class BulletCommand + { + private readonly int bulletId; + private readonly double fireAssistAngle; + private readonly bool fireAssistValid; + private readonly double power; + + public BulletCommand(double power, bool fireAssistValid, double fireAssistAngle, int bulletId) + { + this.fireAssistValid = fireAssistValid; + this.fireAssistAngle = fireAssistAngle; + this.bulletId = bulletId; + this.power = power; + } + + public bool isFireAssistValid() + { + return fireAssistValid; + } + + public int getBulletId() + { + return bulletId; + } + + public double getPower() + { + return power; + } + + public double getFireAssistAngle() + { + return fireAssistAngle; + } + + // ReSharper disable UnusedMember.Local + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + #region Nested type: SerializableHelper + + private class SerializableHelper : ISerializableHelperN + { + #region ISerializableHelperN Members + + public int sizeOf(RbSerializerN serializer, Object obje) + { + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_DOUBLE + RbSerializerN.SIZEOF_BOOL + + RbSerializerN.SIZEOF_DOUBLE + RbSerializerN.SIZEOF_INT; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, Object obje) + { + var obj = (BulletCommand) obje; + + serializer.serialize(buffer, obj.power); + serializer.serialize(buffer, obj.fireAssistValid); + serializer.serialize(buffer, obj.fireAssistAngle); + serializer.serialize(buffer, obj.bulletId); + } + + public Object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + double power = buffer.getDouble(); + bool fireAssistValid = serializer.deserializeBoolean(buffer); + double fireAssistAngle = buffer.getDouble(); + int bulletId = buffer.getInt(); + + return new BulletCommand(power, fireAssistValid, fireAssistAngle, bulletId); + } + + #endregion + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/BulletStatus.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/BulletStatus.cs new file mode 100644 index 0000000..fa25dd9 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/BulletStatus.cs @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using net.sf.robocode.nio; +using net.sf.robocode.serialization; + +namespace net.sf.robocode.dotnet.peer +{ + public class BulletStatus + { + public readonly int bulletId; + public readonly bool isActive; + public readonly String victimName; + public readonly double x; + public readonly double y; + + public BulletStatus(int bulletId, double x, double y, String victimName, bool isActive) + { + this.bulletId = bulletId; + this.x = x; + this.y = y; + this.isActive = isActive; + this.victimName = victimName; + } + + // ReSharper disable UnusedMember.Local + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + #region Nested type: SerializableHelper + + private class SerializableHelper : ISerializableHelperN + { + #region ISerializableHelperN Members + + public int sizeOf(RbSerializerN serializer, Object obje) + { + var obj = (BulletStatus) obje; + + return RbSerializerN.SIZEOF_TYPEINFO + RbSerializerN.SIZEOF_INT + serializer.sizeOf(obj.victimName) + + RbSerializerN.SIZEOF_BOOL + 2*RbSerializerN.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, Object obje) + { + var obj = (BulletStatus) obje; + + serializer.serialize(buffer, obj.bulletId); + serializer.serialize(buffer, obj.victimName); + serializer.serialize(buffer, obj.isActive); + serializer.serialize(buffer, obj.x); + serializer.serialize(buffer, obj.y); + } + + public Object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + int bulletId = buffer.getInt(); + String victimName = serializer.deserializeString(buffer); + bool isActive = serializer.deserializeBoolean(buffer); + double x = buffer.getDouble(); + double y = buffer.getDouble(); + + return new BulletStatus(bulletId, x, y, victimName, isActive); + } + + #endregion + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/DebugProperty.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/DebugProperty.cs new file mode 100644 index 0000000..4366913 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/DebugProperty.cs @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using net.sf.robocode.nio; +using net.sf.robocode.serialization; + +namespace net.sf.robocode.dotnet.peer +{ + [Serializable] + public class DebugProperty + { + private String key; + private String value; + + public DebugProperty() + { + } + + public DebugProperty(String key, String value) + { + setKey(key); + setValue(value); + } + + + public String getKey() + { + return key; + } + + public void setKey(String key) + { + this.key = key; + } + + public String getValue() + { + return value; + } + + public void setValue(String value) + { + this.value = value; + } + + // ReSharper disable UnusedMember.Local + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + #region Nested type: SerializableHelper + + private class SerializableHelper : ISerializableHelperN + { + #region ISerializableHelperN Members + + public int sizeOf(RbSerializerN serializer, Object obje) + { + var obj = (DebugProperty) obje; + + return RbSerializerN.SIZEOF_TYPEINFO + serializer.sizeOf(obj.key) + serializer.sizeOf(obj.value); + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, Object obje) + { + var obj = (DebugProperty) obje; + + serializer.serialize(buffer, obj.key); + serializer.serialize(buffer, obj.value); + } + + public Object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + String key = serializer.deserializeString(buffer); + String value = serializer.deserializeString(buffer); + + return new DebugProperty(key, value); + } + + #endregion + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/ExecCommands.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/ExecCommands.cs new file mode 100644 index 0000000..263357e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/ExecCommands.cs @@ -0,0 +1,490 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using net.sf.robocode.nio; +using net.sf.robocode.serialization; +using Robocode; + +namespace net.sf.robocode.dotnet.peer +{ + [Serializable] + public class ExecCommands + { + public const int defaultBodyColor = 0; //0xFF29298C; + public const int defaultGunColor = 0; //0xFF29298C; + public const int defaultRadarColor = 0; //0xFF29298C; + public const int defaultScanColor = 0; //0xFF0000FF; + public const int defaultBulletColor = 0; //0xFFFFFFFF; + private int bodyColor = defaultBodyColor; + + private double bodyTurnRemaining; + private int bulletColor = defaultBulletColor; + private List bullets = new List(); + private List debugProperties = new List(); + private double distanceRemaining; + [NonSerialized] private byte[] graphicsCalls; + private int gunColor = defaultGunColor; + private double gunTurnRemaining; + + private bool isAdjustGunForBodyTurn; + private bool isAdjustRadarForBodyTurn; + private bool isAdjustRadarForBodyTurnSet; + private bool isAdjustRadarForGunTurn; + private bool isIORobot; + private bool isTryingToPaint; + + private double maxTurnRate; + private double maxVelocity; + + private bool moved; + private String outputText; + private int radarColor = defaultRadarColor; + private double radarTurnRemaining; + private bool scan; + private int scanColor = defaultScanColor; + private List teamMessages = new List(); + + public ExecCommands() + { + setMaxVelocity(Double.MaxValue); + setMaxTurnRate(Double.MaxValue); + } + + public ExecCommands(ExecCommands origin, bool fromRobot) + { + bodyTurnRemaining = origin.bodyTurnRemaining; + radarTurnRemaining = origin.radarTurnRemaining; + gunTurnRemaining = origin.gunTurnRemaining; + distanceRemaining = origin.distanceRemaining; + isAdjustGunForBodyTurn = origin.isAdjustGunForBodyTurn; + isAdjustRadarForGunTurn = origin.isAdjustRadarForGunTurn; + isAdjustRadarForBodyTurn = origin.isAdjustRadarForBodyTurn; + isAdjustRadarForBodyTurnSet = origin.isAdjustRadarForBodyTurnSet; + maxTurnRate = origin.maxTurnRate; + maxVelocity = origin.maxVelocity; + copyColors(origin); + if (fromRobot) + { + debugProperties = origin.debugProperties; + bullets = origin.bullets; + scan = origin.scan; + moved = origin.moved; + graphicsCalls = origin.graphicsCalls; + outputText = origin.outputText; + teamMessages = origin.teamMessages; + isTryingToPaint = origin.isTryingToPaint; + } + } + + public void copyColors(ExecCommands origin) + { + if (origin != null) + { + bodyColor = origin.bodyColor; + gunColor = origin.gunColor; + radarColor = origin.radarColor; + bulletColor = origin.bulletColor; + scanColor = origin.scanColor; + } + } + + public int getBodyColor() + { + return bodyColor; + } + + public int getRadarColor() + { + return radarColor; + } + + public int getGunColor() + { + return gunColor; + } + + public int getBulletColor() + { + return bulletColor; + } + + public int getScanColor() + { + return scanColor; + } + + public void setBodyColor(int color) + { + bodyColor = color; + } + + public void setRadarColor(int color) + { + radarColor = color; + } + + public void setGunColor(int color) + { + gunColor = color; + } + + public void setBulletColor(int color) + { + bulletColor = color; + } + + public void setScanColor(int color) + { + scanColor = color; + } + + public double getBodyTurnRemaining() + { + return bodyTurnRemaining; + } + + public void setBodyTurnRemaining(double bodyTurnRemaining) + { + this.bodyTurnRemaining = bodyTurnRemaining; + } + + public double getRadarTurnRemaining() + { + return radarTurnRemaining; + } + + public void setRadarTurnRemaining(double radarTurnRemaining) + { + this.radarTurnRemaining = radarTurnRemaining; + } + + public double getGunTurnRemaining() + { + return gunTurnRemaining; + } + + public void setGunTurnRemaining(double gunTurnRemaining) + { + this.gunTurnRemaining = gunTurnRemaining; + } + + public double getDistanceRemaining() + { + return distanceRemaining; + } + + public void setDistanceRemaining(double distanceRemaining) + { + this.distanceRemaining = distanceRemaining; + } + + public bool IsAdjustGunForBodyTurn() + { + return isAdjustGunForBodyTurn; + } + + public void setAdjustGunForBodyTurn(bool adjustGunForBodyTurn) + { + isAdjustGunForBodyTurn = adjustGunForBodyTurn; + } + + public bool IsAdjustRadarForGunTurn() + { + return isAdjustRadarForGunTurn; + } + + public void setAdjustRadarForGunTurn(bool adjustRadarForGunTurn) + { + isAdjustRadarForGunTurn = adjustRadarForGunTurn; + } + + public bool IsAdjustRadarForBodyTurn() + { + return isAdjustRadarForBodyTurn; + } + + public void setAdjustRadarForBodyTurn(bool adjustRadarForBodyTurn) + { + isAdjustRadarForBodyTurn = adjustRadarForBodyTurn; + } + + public bool IsAdjustRadarForBodyTurnSet() + { + return isAdjustRadarForBodyTurnSet; + } + + public void setAdjustRadarForBodyTurnSet(bool adjustRadarForBodyTurnSet) + { + isAdjustRadarForBodyTurnSet = adjustRadarForBodyTurnSet; + } + + public double getMaxTurnRate() + { + return maxTurnRate; + } + + public void setMaxTurnRate(double maxTurnRate) + { + this.maxTurnRate = Math.Min(Math.Abs(maxTurnRate), Rules.MAX_TURN_RATE_RADIANS); + } + + public double getMaxVelocity() + { + return maxVelocity; + } + + public void setMaxVelocity(double maxVelocity) + { + this.maxVelocity = Math.Min(Math.Abs(maxVelocity), Rules.MAX_VELOCITY); + } + + public bool isMoved() + { + return moved; + } + + public void setMoved(bool moved) + { + this.moved = moved; + } + + public bool isScan() + { + return scan; + } + + public void setScan(bool scan) + { + this.scan = scan; + } + + public List getBullets() + { + return bullets; + } + + public Object getGraphicsCalls() + { + return graphicsCalls; + } + + public List getDebugProperties() + { + return debugProperties; + } + + public void setGraphicsCalls(byte[] graphicsCalls) + { + this.graphicsCalls = graphicsCalls; + } + + public string getOutputText() + { + return outputText; + } + + public void setOutputText(string output) + { + outputText = string.IsNullOrEmpty(output) ? null : output; + } + + public List getTeamMessages() + { + return teamMessages; + } + + public bool IsIORobot() + { + return isIORobot; + } + + public void setIORobot() + { + isIORobot = true; + } + + public void setDebugProperty(String key, String value) + { + debugProperties.Add(new DebugProperty(key, value)); + } + + public bool IsTryingToPaint() + { + return isTryingToPaint; + } + + public void setTryingToPaint(bool tryingToPaint) + { + isTryingToPaint = tryingToPaint; + } + + // ReSharper disable UnusedMember.Local + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + #region Nested type: SerializableHelper + + private class SerializableHelper : ISerializableHelperN + { + #region ISerializableHelperN Members + + public int sizeOf(RbSerializerN serializer, Object obje) + { + var obj = (ExecCommands) obje; + int size = RbSerializerN.SIZEOF_TYPEINFO + 4*RbSerializerN.SIZEOF_DOUBLE; + + size += 4*RbSerializerN.SIZEOF_BOOL; + size += 5*RbSerializerN.SIZEOF_INT; + size += 2*RbSerializerN.SIZEOF_DOUBLE; + size += 4*RbSerializerN.SIZEOF_BOOL; + size += serializer.sizeOf(obj.outputText); + + size += serializer.sizeOf(obj.graphicsCalls); + + // bullets + size += obj.bullets.Count*serializer.sizeOf(RbSerializerN.BulletCommand_TYPE, null); + size += 1; + + // messages + foreach (TeamMessage m in obj.teamMessages) + { + size += serializer.sizeOf(RbSerializerN.TeamMessage_TYPE, m); + } + size += 1; + + // properties + foreach (DebugProperty d in obj.debugProperties) + { + size += serializer.sizeOf(RbSerializerN.DebugProperty_TYPE, d); + } + size += 1; + + return size; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, Object obje) + { + var obj = (ExecCommands) obje; + + serializer.serialize(buffer, obj.bodyTurnRemaining); + serializer.serialize(buffer, obj.radarTurnRemaining); + serializer.serialize(buffer, obj.gunTurnRemaining); + serializer.serialize(buffer, obj.distanceRemaining); + + serializer.serialize(buffer, obj.isAdjustGunForBodyTurn); + serializer.serialize(buffer, obj.isAdjustRadarForGunTurn); + serializer.serialize(buffer, obj.isAdjustRadarForBodyTurn); + serializer.serialize(buffer, obj.isAdjustRadarForBodyTurnSet); + + serializer.serialize(buffer, obj.bodyColor); + serializer.serialize(buffer, obj.gunColor); + serializer.serialize(buffer, obj.radarColor); + serializer.serialize(buffer, obj.scanColor); + serializer.serialize(buffer, obj.bulletColor); + + serializer.serialize(buffer, obj.maxTurnRate); + serializer.serialize(buffer, obj.maxVelocity); + + serializer.serialize(buffer, obj.moved); + serializer.serialize(buffer, obj.scan); + serializer.serialize(buffer, obj.isIORobot); + serializer.serialize(buffer, obj.isTryingToPaint); + + serializer.serialize(buffer, obj.outputText); + + serializer.serialize(buffer, obj.graphicsCalls); + + foreach (BulletCommand bullet in obj.bullets) + { + serializer.serialize(buffer, RbSerializerN.BulletCommand_TYPE, bullet); + } + buffer.put(RbSerializerN.TERMINATOR_TYPE); + foreach (TeamMessage message in obj.teamMessages) + { + serializer.serialize(buffer, RbSerializerN.TeamMessage_TYPE, message); + } + buffer.put(RbSerializerN.TERMINATOR_TYPE); + foreach (DebugProperty prop in obj.debugProperties) + { + serializer.serialize(buffer, RbSerializerN.DebugProperty_TYPE, prop); + } + buffer.put(RbSerializerN.TERMINATOR_TYPE); + } + + public Object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + var res = new ExecCommands(); + + res.bodyTurnRemaining = buffer.getDouble(); + res.radarTurnRemaining = buffer.getDouble(); + res.gunTurnRemaining = buffer.getDouble(); + res.distanceRemaining = buffer.getDouble(); + + res.isAdjustGunForBodyTurn = serializer.deserializeBoolean(buffer); + res.isAdjustRadarForGunTurn = serializer.deserializeBoolean(buffer); + res.isAdjustRadarForBodyTurn = serializer.deserializeBoolean(buffer); + res.isAdjustRadarForBodyTurnSet = serializer.deserializeBoolean(buffer); + + res.bodyColor = buffer.getInt(); + res.gunColor = buffer.getInt(); + res.radarColor = buffer.getInt(); + res.scanColor = buffer.getInt(); + res.bulletColor = buffer.getInt(); + + res.maxTurnRate = buffer.getDouble(); + res.maxVelocity = buffer.getDouble(); + + res.moved = serializer.deserializeBoolean(buffer); + res.scan = serializer.deserializeBoolean(buffer); + res.isIORobot = serializer.deserializeBoolean(buffer); + res.isTryingToPaint = serializer.deserializeBoolean(buffer); + + res.outputText = serializer.deserializeString(buffer); + + res.graphicsCalls = serializer.deserializeBytes(buffer); + + Object item = serializer.deserializeAny(buffer); + + while (item != null) + { + if (item is BulletCommand) + { + res.bullets.Add((BulletCommand) item); + } + item = serializer.deserializeAny(buffer); + } + item = serializer.deserializeAny(buffer); + while (item != null) + { + if (item is TeamMessage) + { + res.teamMessages.Add((TeamMessage) item); + } + item = serializer.deserializeAny(buffer); + } + item = serializer.deserializeAny(buffer); + while (item != null) + { + if (item is DebugProperty) + { + res.debugProperties.Add((DebugProperty) item); + } + item = serializer.deserializeAny(buffer); + } + return res; + } + + #endregion + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/ExecResults.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/ExecResults.cs new file mode 100644 index 0000000..01bf7f0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/ExecResults.cs @@ -0,0 +1,253 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using net.sf.robocode.nio; +using net.sf.robocode.serialization; +using Robocode; + +namespace net.sf.robocode.dotnet.peer +{ + [Serializable] + public class ExecResults + { + private const long serialVersionUID = 1L; + private List bulletUpdates; + private ExecCommands commands; + private List events; + private bool halt; + private bool paintEnabled; + private bool shouldWait; + private RobotStatus status; + private List teamMessages; + + public ExecResults(ExecCommands commands, RobotStatus status, List events, List teamMessages, + List bulletUpdates, bool halt, bool shouldWait, bool paintEnabled) + { + this.commands = commands; + this.status = status; + this.events = events; + this.teamMessages = teamMessages; + this.bulletUpdates = bulletUpdates; + this.halt = halt; + this.shouldWait = shouldWait; + this.paintEnabled = paintEnabled; + } + + private ExecResults() + { + } + + public static long getSerialVersionUID() + { + return serialVersionUID; + } + + public ExecCommands getCommands() + { + return commands; + } + + public void setCommands(ExecCommands commands) + { + this.commands = commands; + } + + public RobotStatus getStatus() + { + return status; + } + + public void setStatus(RobotStatus status) + { + this.status = status; + } + + public List getEvents() + { + return events; + } + + public void setEvents(List events) + { + this.events = events; + } + + public List getTeamMessages() + { + return teamMessages; + } + + public void setTeamMessages(List teamMessages) + { + this.teamMessages = teamMessages; + } + + public List getBulletUpdates() + { + return bulletUpdates; + } + + public void setBulletUpdates(List bulletUpdates) + { + this.bulletUpdates = bulletUpdates; + } + + public bool isHalt() + { + return halt; + } + + public void setHalt(bool halt) + { + this.halt = halt; + } + + public bool isShouldWait() + { + return shouldWait; + } + + public void setShouldWait(bool shouldWait) + { + this.shouldWait = shouldWait; + } + + public bool isPaintEnabled() + { + return paintEnabled; + } + + public void setPaintEnabled(bool paintEnabled) + { + this.paintEnabled = paintEnabled; + } + + // ReSharper disable UnusedMember.Local + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + #region Nested type: SerializableHelper + + private class SerializableHelper : ISerializableHelperN + { + #region ISerializableHelperN Members + + public int sizeOf(RbSerializerN serializer, Object obje) + { + var obj = (ExecResults) obje; + int size = RbSerializerN.SIZEOF_TYPEINFO + 3*RbSerializerN.SIZEOF_BOOL; + + size += serializer.sizeOf(RbSerializerN.ExecCommands_TYPE, obj.commands); + size += serializer.sizeOf(RbSerializerN.RobotStatus_TYPE, obj.status); + + // events + foreach (Event evnt in obj.events) + { + size += serializer.sizeOf(evnt); + } + size += 1; + + // messages + foreach (TeamMessage m in obj.teamMessages) + { + size += serializer.sizeOf(RbSerializerN.TeamMessage_TYPE, m); + } + size += 1; + + // bullets + foreach (BulletStatus b in obj.bulletUpdates) + { + size += serializer.sizeOf(RbSerializerN.BulletStatus_TYPE, b); + } + size += 1; + + return size; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, Object obje) + { + var obj = (ExecResults) obje; + + serializer.serialize(buffer, obj.halt); + serializer.serialize(buffer, obj.shouldWait); + serializer.serialize(buffer, obj.paintEnabled); + + serializer.serialize(buffer, RbSerializerN.ExecCommands_TYPE, obj.commands); + serializer.serialize(buffer, RbSerializerN.RobotStatus_TYPE, obj.status); + + foreach (Event evnt in obj.events) + { + serializer.serialize(buffer, evnt); + } + buffer.put(RbSerializerN.TERMINATOR_TYPE); + foreach (TeamMessage message in obj.teamMessages) + { + serializer.serialize(buffer, RbSerializerN.TeamMessage_TYPE, message); + } + buffer.put(RbSerializerN.TERMINATOR_TYPE); + foreach (BulletStatus bulletStatus in obj.bulletUpdates) + { + serializer.serialize(buffer, RbSerializerN.BulletStatus_TYPE, bulletStatus); + } + buffer.put(RbSerializerN.TERMINATOR_TYPE); + } + + public Object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + var res = new ExecResults(); + + res.halt = serializer.deserializeBoolean(buffer); + res.shouldWait = serializer.deserializeBoolean(buffer); + res.paintEnabled = serializer.deserializeBoolean(buffer); + + res.commands = (ExecCommands) serializer.deserializeAny(buffer); + res.status = (RobotStatus) serializer.deserializeAny(buffer); + + Object item = serializer.deserializeAny(buffer); + + res.events = new List(); + res.teamMessages = new List(); + res.bulletUpdates = new List(); + while (item != null) + { + if (item is Event) + { + res.events.Add((Event) item); + } + item = serializer.deserializeAny(buffer); + } + item = serializer.deserializeAny(buffer); + while (item != null) + { + if (item is TeamMessage) + { + res.teamMessages.Add((TeamMessage) item); + } + item = serializer.deserializeAny(buffer); + } + item = serializer.deserializeAny(buffer); + while (item != null) + { + if (item is BulletStatus) + { + res.bulletUpdates.Add((BulletStatus) item); + } + item = serializer.deserializeAny(buffer); + } + return res; + } + + #endregion + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/TeamMessage.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/TeamMessage.cs new file mode 100644 index 0000000..2f31f0e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/peer/TeamMessage.cs @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using net.sf.robocode.nio; +using net.sf.robocode.serialization; + +namespace net.sf.robocode.dotnet.peer +{ + [Serializable] + public class TeamMessage + { + public byte[] message; + public String recipient; + public String sender; + + public TeamMessage(String sender, String recipient, byte[] message) + { + this.sender = sender; + this.recipient = recipient; + this.message = message; + } + + // ReSharper disable UnusedMember.Local + private static ISerializableHelperN createHiddenSerializer() + { + return new SerializableHelper(); + } + + #region Nested type: SerializableHelper + + private class SerializableHelper : ISerializableHelperN + { + #region ISerializableHelperN Members + + public int sizeOf(RbSerializerN serializer, Object obje) + { + var obj = (TeamMessage) obje; + int s = serializer.sizeOf(obj.sender); + int r = serializer.sizeOf(obj.recipient); + int m = serializer.sizeOf(obj.message); + + return RbSerializerN.SIZEOF_TYPEINFO + s + r + m; + } + + public void serialize(RbSerializerN serializer, ByteBuffer buffer, Object obje) + { + var obj = (TeamMessage) obje; + + serializer.serialize(buffer, obj.sender); + serializer.serialize(buffer, obj.recipient); + serializer.serialize(buffer, obj.message); + } + + public Object deserialize(RbSerializerN serializer, ByteBuffer buffer) + { + String sender = serializer.deserializeString(buffer); + String recipient = serializer.deserializeString(buffer); + byte[] message = serializer.deserializeBytes(buffer); + + return new TeamMessage(sender, recipient, message); + } + + #endregion + } + + #endregion + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/repository/RobotType.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/repository/RobotType.cs new file mode 100644 index 0000000..3e68dd0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/repository/RobotType.cs @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; + +namespace net.sf.robocode.repository +{ + [Flags] + public enum RobotTypeN + { + INVALID = 0, + JUNIOR = 1, + STANDARD = 2, + ADVANCED = 4, + TEAM = 8, + DROID = 16, + INTERACTIVE = 32, + PAINTING = 64, + SENTRY = 128 + } + + partial class RobotType + { + private static RobotType _Invalid; + + public static RobotType Invalid + { + get + { + if (_Invalid == null) + { + _Invalid = INVALID; + } + return _Invalid; + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/repository/root/DllRootHelper.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/repository/root/DllRootHelper.cs new file mode 100644 index 0000000..6b00054 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/repository/root/DllRootHelper.cs @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.IO; +using System.Threading; +using System.Web; +using net.sf.robocode.dotnet.host.seed; +using net.sf.robocode.repository; + +namespace net.sf.robocode.dotnet.repository.root +{ + public static class DllRootHelper + { + private static AppDomainShell shell; + + public static void Open() + { + if (shell!=null) + { + shell.Dispose(); + } + shell = new AppDomainShell(); + shell.Init(false); + } + + public static void Close() + { + } + + public static string[] findItems(string dllPath) + { + string uriPath = dllPath.Replace("#", "%23"); // All '#' occurrences must be replaced + string file = new Uri(uriPath).LocalPath; + if (!File.Exists(file)) + { + throw new FileNotFoundException("File not found: " + dllPath); + } + + if (shell != null) + { + shell.Open(file); + return shell.FindRobots(); + } + using (AppDomainShell localshell = new AppDomainShell()) + { + localshell.Init(false); + localshell.Open(file); + return localshell.FindRobots(); + } + } + + public static RobotType GetRobotType(IRobotItem robotItem) + { + string file = GetDllFileName(robotItem); + if (!File.Exists(file)) + { + return RobotType.Invalid; + } + if (shell != null) + { + shell.Open(file); + return shell.GetRobotType(robotItem.getFullClassName()); + } + using (AppDomainShell localshell = new AppDomainShell()) + { + localshell.Init(false); + localshell.Open(file); + return localshell.GetRobotType(robotItem.getFullClassName()); + } + } + + public static string GetDllFileName(IRobotItem robotItem) + { + string uriString = robotItem.getClassPathURL().toURI().toString(); + string trim = uriString.Substring(0, uriString.LastIndexOf(".dll!/") + 4); + return new Uri(trim).LocalPath; + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/robocode.dotnet.nhost.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/robocode.dotnet.nhost.csproj new file mode 100644 index 0000000..d9a87e7 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/robocode.dotnet.nhost.csproj @@ -0,0 +1,187 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {674AED55-B9EC-4C7D-8E0B-1B2481C578B2} + Library + net.sf.robocode.dotnet + robocode.dotnet.nhost-1.9.2.4 + v3.5 + 512 + true + ..\..\tools\keys\robocode.snk + + + 3.5 + + + + true + full + false + ..\target\ + ..\target\obj\ + DEBUG;TRACE + prompt + 4 + false + true + + + pdbonly + true + ..\target\ + ..\target\obj\ + + + prompt + 4 + true + + + + False + ..\..\tools\lib\jni4net.n-0.8.7.0.dll + + + + + + + + + + + + generated\AssemblyInfo.cs + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {7E0900D3-6E8F-48EB-86DB-AA767AA90B84} + robocode.dotnet.api + + + {674AED55-B9EC-4C7D-8E0B-1B2471C578B2} + robocode.dotnet.control.api + + + + + + if not exist $(OutDir)\build-sources\generated-sources\META-INF mkdir $(OutDir)\build-sources\generated-sources\META-INF\ +echo [assembly: System.Reflection.AssemblyVersion("1.9.2.4")] > $(OutDir)\build-sources\generated-sources\META-INF\AssemblyInfo.cs + + copy "$(TargetPath)" "$(SolutionDir)\robocode.dotnet.host\target" +copy "$(SolutionDir)\tools\lib\*.dll" "$(TargetDir)" +copy "$(SolutionDir)\tools\lib\*.dll" "$(SolutionDir)\robocode.dotnet.host\target" + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/serialization/RbSerializer.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/serialization/RbSerializer.cs new file mode 100644 index 0000000..c176eaf --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/serialization/RbSerializer.cs @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System.IO; +using java.lang; +using net.sf.jni4net.nio; +using ByteBuffer = net.sf.robocode.nio.ByteBuffer; + +namespace net.sf.robocode.serialization +{ + partial class RbSerializer + { + private const int byteOrder = -1059135839; //0xC0DEDEA1 + private static int currentVersion; + + public static void Init(int version) + { + if (currentVersion == 0) + { + currentVersion = version; + } + } + + public DirectByteBuffer serializeN(byte type, Object obj) + { + int length = sizeOf(type, obj); + + // header + int size = RbSerializerN.SIZEOF_INT*3 + length; + var sharedBuffer = new byte[size]; + var buffer = new DirectByteBuffer(sharedBuffer); + + buffer.putInt(byteOrder); + buffer.putInt(currentVersion); + buffer.putInt(length); + + // body + serialize(buffer, type, obj); + if (buffer.remaining() != 0) + { + throw new IOException("Serialization failed: bad size"); + } + return buffer; + } + + public T ConvertJ2C(byte type, Object javaObject) + { + DirectByteBuffer commandBuffer = serializeN(type, javaObject); + ByteBuffer byteBuffer = ByteBuffer.wrap(commandBuffer.GetSharedBuffer()); + return RbSerializerN.deserializeFromBuffer(byteBuffer); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/utils/Reflection.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/utils/Reflection.cs new file mode 100644 index 0000000..0f7e664 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/utils/Reflection.cs @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections; +using System.Diagnostics; +using System.Reflection; +using System.Security; +using System.Security.Permissions; +using System.Security.Policy; +using net.sf.robocode.repository; +using Robocode; +using Robocode.RobotInterfaces; + +namespace net.sf.robocode.dotnet.utils +{ + internal partial class Reflection + { + public static PermissionSet GetNamedPermissionSet(string name) + { + IEnumerator policyEnumerator = SecurityManager.PolicyHierarchy(); + + // Move through the policy levels to the machine policy level. + while (policyEnumerator.MoveNext()) + { + var currentLevel = (PolicyLevel) policyEnumerator.Current; + + if (currentLevel.Label == "Machine") + { + return currentLevel.GetNamedPermissionSet(name); + } + } + return null; + } + + public static StrongName GetStrongName(Assembly assembly) + { + if (assembly == null) + throw new ArgumentNullException("assembly"); + + AssemblyName assemblyName = assembly.GetName(); + Debug.Assert(assemblyName != null, "Could not get assembly name"); + + // Get the public key blob. + byte[] publicKey = assemblyName.GetPublicKey(); + if (publicKey == null || publicKey.Length == 0) + throw new InvalidOperationException("Assembly is not strongly named"); + + var keyBlob = new StrongNamePublicKeyBlob(publicKey); + + // Return the strong name. + return new StrongName(keyBlob, assemblyName.Name, assemblyName.Version); + } + + public static RobotTypeN CheckInterfaces(Type robotClass) + { + if (robotClass == null || robotClass.IsAbstract) + { + // this class is not robot + return RobotTypeN.INVALID; + } + bool isJuniorRobot = false; + bool isStandardRobot = false; + bool isInteractiveRobot = false; + bool isPaintRobot = false; + bool isAdvancedRobot = false; + bool isTeamRobot = false; + bool isDroid = false; + bool isSentryRobot = false; + + if (typeof (IDroid).IsAssignableFrom(robotClass)) + { + isDroid = true; + } + + if (typeof(IBorderSentry).IsAssignableFrom(robotClass)) + { + isSentryRobot = true; + } + + if (typeof (ITeamRobot).IsAssignableFrom(robotClass)) + { + isTeamRobot = true; + } + + if (typeof (IAdvancedRobot).IsAssignableFrom(robotClass)) + { + isAdvancedRobot = true; + } + + if (typeof (IInteractiveRobot).IsAssignableFrom(robotClass)) + { + // in this case we make sure that robot don't waste time + if (checkMethodOverride(robotClass, typeof (Robot), "GetInteractiveEventListener") + || checkMethodOverride(robotClass, typeof (Robot), "OnKeyPressed", typeof (KeyEvent)) + || checkMethodOverride(robotClass, typeof (Robot), "OnKeyReleased", typeof (KeyEvent)) + || checkMethodOverride(robotClass, typeof (Robot), "OnKeyTyped", typeof (KeyEvent)) + || checkMethodOverride(robotClass, typeof (Robot), "OnMouseClicked", typeof (MouseEvent)) + || checkMethodOverride(robotClass, typeof (Robot), "OnMouseEntered", typeof (MouseEvent)) + || checkMethodOverride(robotClass, typeof (Robot), "OnMouseExited", typeof (MouseEvent)) + || checkMethodOverride(robotClass, typeof (Robot), "OnMousePressed", typeof (MouseEvent)) + || checkMethodOverride(robotClass, typeof (Robot), "OnMouseReleased", typeof (MouseEvent)) + || checkMethodOverride(robotClass, typeof (Robot), "OnMouseMoved", typeof (MouseEvent)) + || checkMethodOverride(robotClass, typeof (Robot), "OnMouseDragged", typeof (MouseEvent)) + || + checkMethodOverride(robotClass, typeof (Robot), "OnMouseWheelMoved", typeof (MouseWheelMovedEvent)) + ) + { + isInteractiveRobot = true; + } + } + + if (typeof (IPaintRobot).IsAssignableFrom(robotClass)) + { + if (checkMethodOverride(robotClass, typeof (Robot), "GetPaintEventListener") + || checkMethodOverride(robotClass, typeof (Robot), "OnPaint", typeof (IGraphics)) + ) + { + isPaintRobot = true; + } + } + + if (typeof (Robot).IsAssignableFrom(robotClass) && !isAdvancedRobot) + { + isStandardRobot = true; + } + + if (typeof (IJuniorRobot).IsAssignableFrom(robotClass)) + { + isJuniorRobot = true; + if (isAdvancedRobot) + { + throw new AccessViolationException(robotClass.Name + + ": Junior robot should not implement IAdvancedRobot interface."); + } + } + + if (typeof (IBasicRobot).IsAssignableFrom(robotClass)) + { + if (!(isAdvancedRobot || isJuniorRobot)) + { + isStandardRobot = true; + } + } + if (!isAdvancedRobot && !isStandardRobot && !isJuniorRobot) + { + return RobotTypeN.INVALID; + } + + RobotTypeN type=0; + + if (isJuniorRobot) type |= RobotTypeN.JUNIOR; + if (isStandardRobot) type |= RobotTypeN.STANDARD; + if (isInteractiveRobot) type |= RobotTypeN.INTERACTIVE; + if (isPaintRobot) type |= RobotTypeN.PAINTING; + if (isAdvancedRobot) type |= RobotTypeN.ADVANCED; + if (isTeamRobot) type |= RobotTypeN.TEAM; + if (isDroid) type |= RobotTypeN.DROID; + if (isSentryRobot) type |= RobotTypeN.SENTRY; + return type; + } + + private static bool checkMethodOverride(Type robotClass, Type knownBase, String name, + params Type[] parameterTypes) + { + if (knownBase.IsAssignableFrom(robotClass)) + { + MethodInfo method; + + method = robotClass.GetMethod(name, parameterTypes); + if (method == null) + { + return false; + } + + + if (method.DeclaringType.Equals(knownBase)) + { + return false; + } + } + return true; + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/utils/Reflection.security.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/utils/Reflection.security.cs new file mode 100644 index 0000000..e0a4830 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.nhost/src/utils/Reflection.security.cs @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Reflection; +using System.Security; +using System.Threading; +using Mono.Reflection; + +namespace net.sf.robocode.dotnet.utils +{ + partial class Reflection + { + private const BindingFlags nextedFlags = BindingFlags.NonPublic | BindingFlags.Public; + private const BindingFlags memberFlags = + BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.CreateInstance | BindingFlags.GetProperty; + + public static void CheckAssembly(Assembly assembly) + { + foreach (Type type in assembly.GetTypes()) + { + CheckType(type); + } + } + + private static void CheckType(Type type) + { + foreach (MemberInfo member in type.GetMembers(memberFlags)) + { + MethodBase mb = member as MethodBase; + if (mb != null && member.DeclaringType == type) + { + CheckMethodBase(mb); + } + } + CheckUsedType(type.BaseType); + foreach (Type ifc in type.GetInterfaces()) + { + if (ifc.DeclaringType == type) + { + CheckUsedType(ifc); + } + } + foreach (Type nestedType in type.GetNestedTypes(nextedFlags)) + { + CheckType(nestedType); + } + } + + private static void CheckMethodBase(MethodBase methodBase) + { + foreach (Instruction i in MethodBodyReader.GetInstructions(methodBase)) + { + MethodBase mb = i.Operand as MethodBase; + MethodInfo mi = i.Operand as MethodInfo; + FieldInfo fi = i.Operand as FieldInfo; + + if (mb != null) + { + foreach (var parameter in mb.GetParameters()) + { + CheckUsedType(parameter.ParameterType); + } + CheckUsedType(mb.DeclaringType); + } + + if (mi != null) + { + CheckUsedType(mi.ReturnType); + } + + if (fi != null) + { + CheckUsedType(fi.FieldType); + } + + } + } + + private static void CheckUsedType(Type usedType) + { + if (typeof(Thread).IsAssignableFrom(usedType) || + typeof(ThreadPool).IsAssignableFrom(usedType) || + typeof(ThreadPriority).IsAssignableFrom(usedType) + ) + { + throw new SecurityException("System.Threading.Thread usage is banned here! Please use robocode.Thread instead"); + } + } + + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/.project new file mode 100644 index 0000000..dc0a099 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/.project @@ -0,0 +1,14 @@ + + + robocode.dotnet.ntests + .NET ntests for Robocode. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.dotnet.api + robocode.dotnet.control.api + robocode.dotnet.nhost + robocode.dotnet.robotscs + robocode.dotnet.samples + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..6687c7a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +#Tue Nov 27 22:34:11 CET 2012 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 +encoding/src/main/resources=8859_1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/test/resources=8859_1 +encoding/src=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/pom.xml new file mode 100644 index 0000000..bc91d59 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + robocode.dotnet.ntests + dotnet:library + Robocode .NET nTests + .NET ntests for Robocode + + robocode.dotnet + net.sf.robocode + ${robocode.dotnet.version} + + + + net.sf.robocode + robocode.dotnet.api + ${project.version} + dotnet:library + + + net.sf.robocode + robocode.dotnet.control.api + ${project.version} + dotnet:library + + + net.sf.robocode + robocode.dotnet.nhost + ${project.version} + dotnet:library + + + net.sf.robocode + robocode.dotnet.robotscs + ${project.version} + dotnet:library + + + net.sf.robocode + robocode.dotnet.samples + ${project.version} + dotnet:library + + + org.nunit + nunit.framework + 2.4.3.0 + dotnet:library + + + net.sf.jni4net + jni4net.n + 0.8.7.0 + dotnet:library + + + + src + + + org.sonatype.nmaven.plugins + maven-dotnet-compiler-plugin + + /warn:0 + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/robocode.dotnet.ntests.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/robocode.dotnet.ntests.iml new file mode 100644 index 0000000..96d01fd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/robocode.dotnet.ntests.iml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/AssemblyLoadTest.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/AssemblyLoadTest.cs new file mode 100644 index 0000000..6e7fdaa --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/AssemblyLoadTest.cs @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using net.sf.robocode.dotnet.host.seed; +using net.sf.robocode.dotnet.repository.root; +using net.sf.robocode.repository; +using NUnit.Framework; +using SampleCs; +using tested.robotscs; + +namespace net.sf.robocode.dotnet +{ + [TestFixture] + public class AssemblyLoadTest : TestBase + { + [Test] + public void testDomain() + { + string[] strings = DllRootHelper.findItems(@"file:/" + typeof(MyFirstRobot).Assembly.Location); + Assert.GreaterOrEqual(strings.Length, 5); + } + + [Test] + public void testType() + { + var shell = new AppDomainShell(); + shell.Init(false); + shell.Open(typeof(ThreadAttack).Assembly.Location); + RobotType robotType = shell.GetRobotType(typeof(ThreadAttack).FullName); + Assert.IsTrue(robotType.isAdvancedRobot()); + shell.Open(typeof(MyFirstRobot).Assembly.Location); + robotType = shell.GetRobotType(typeof(MyFirstRobot).FullName); + Assert.IsTrue(robotType.isStandardRobot()); + shell.Dispose(); + } + + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/SimpleTest.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/SimpleTest.cs new file mode 100644 index 0000000..e1334fc --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/SimpleTest.cs @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Drawing; +using System.IO; +using System.Reflection; +using net.sf.robocode.dotnet.host.proxies; +using net.sf.robocode.dotnet.host.security; +using NUnit.Framework; + +namespace net.sf.robocode.dotnet +{ + [TestFixture] + public class SimpleTest : TestBase + { + [Test] + public void Graphics() + { + var sg = new GraphicsProxy(); + sg.setPaintingEnabled(true); + /*sg.DrawArc(Pens.Red, new RectangleF(0,0,80,80),-30,10); + + GraphicsPath path = new GraphicsPath(); + path.AddLine(99,98,78,3); + sg.DrawPath(Pens.Blue, path); + sg.DrawRectangle(Pens.Yellow, 20,20,30,50); + + sg.DrawLine(Pens.Black, 99, 3, 78, 3); + sg.DrawRectangle(Pens.Black, 90, 20, 30, 50); + + Brush brush = new HatchBrush(HatchStyle.Vertical, Color.Cyan); + sg.FillRectangle(brush, new RectangleF(20, 70, 30, 50)); + sg.FillEllipse(brush, new RectangleF(70, 70, 30, 50 )); + */ + + sg.DrawEllipse(Pens.Red, (50), (50), 100, 100); + sg.FillEllipse(new SolidBrush(Color.FromArgb(0, 0xFF, 0, 30)), (100 - 60), (100 - 60), 120, + 120); + + + byte[] readoutQueuedCalls = sg.readoutQueuedCalls(); + Assert.Greater(readoutQueuedCalls.Length, 0); + } + + [Test] + [ExpectedException(typeof (AccessViolationException))] + public void StreamBig() + { + string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(tempDir); + var m = new RobotFileSystemManager(null, 100, tempDir, tempDir); + + using (Stream dataFile = m.getDataFile("test.txt")) + { + dataFile.WriteByte(0xFF); + dataFile.Position = 98; + dataFile.WriteByte(0xFF); + dataFile.WriteByte(0xFF); + dataFile.WriteByte(0xFF); + } + } + + [Test] + [ExpectedException(typeof (AccessViolationException))] + public void StreamBig2() + { + string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(tempDir); + var m = new RobotFileSystemManager(null, 100, tempDir, tempDir); + + using (Stream dataFile = m.getDataFile("test.txt")) + { + dataFile.WriteByte(0xFF); + dataFile.Position = 97; + dataFile.WriteByte(0xFF); + using (Stream dataFile2 = m.getDataFile("test.txt")) + { + dataFile2.WriteByte(0xFF); + dataFile2.Position = 98; + dataFile2.WriteByte(0xFF); + } + } + } + + [Test] + [ExpectedException(typeof (AccessViolationException))] + public void StreamBig3() + { + string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(tempDir); + var m = new RobotFileSystemManager(null, 100, tempDir, tempDir); + + using (Stream dataFile = m.getDataFile("test.txt")) + { + dataFile.WriteByte(0xFF); + dataFile.Position = 97; + dataFile.WriteByte(0xFF); + dataFile.Write(new byte[] {0xFF, 0xFF, 0xFF}, 0, 3); + } + } + + [Test] + public void StreamOk() + { + string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + Directory.CreateDirectory(tempDir); + var m = new RobotFileSystemManager(null, 100, tempDir, tempDir); + + using (Stream dataFile = m.getDataFile("test.txt")) + { + dataFile.WriteByte(0xFF); + dataFile.Position = 97; + dataFile.WriteByte(0xFF); + dataFile.Write(new byte[] {0xFF, 0xFF, 0xFF}, 0, 2); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/TestBase.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/TestBase.cs new file mode 100644 index 0000000..452858c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/TestBase.cs @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System; +using System.Globalization; +using System.Threading; +using net.sf.jni4net; +using net.sf.jni4net.jni; +using net.sf.robocode.dotnet.repository.root; +using NUnit.Framework; + +namespace net.sf.robocode.dotnet +{ + public abstract class TestBase + { + protected JNIEnv env; + + [TestFixtureSetUp] + public virtual void Setup() + { + Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; + Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; + var setup = new BridgeSetup(false) { Verbose = true, Debug = true }; + string prefix; + if (Environment.CurrentDirectory.EndsWith("target")) + { + prefix = "../../"; + } + else + { + prefix = "../../../"; + } + string userHome = Environment.GetEnvironmentVariable("USERPROFILE"); + string version = typeof (BridgeSetup).Assembly.GetName().Version.ToString(); + setup.AddClassPath(userHome + @"/.m2/repository/org/picocontainer/picocontainer/2.14.2/picocontainer-2.14.2.jar"); + setup.AddClassPath(userHome + @"/.m2/repository/net/sf/jni4net/jni4net.j/" + version + "/jni4net.j-" + + version + ".jar"); + setup.AddClassPath(prefix + "../../robocode.api/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.api/target/classes"); + setup.AddClassPath(prefix + "../../robocode.battle/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.battle/target/classes"); + setup.AddClassPath(prefix + "../../robocode.core/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.core/target/classes"); + setup.AddClassPath(prefix + "../../robocode.host/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.host/target/classes"); + setup.AddClassPath(prefix + "../../robocode.repository/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.repository/target/classes"); + setup.AddClassPath(prefix + "../../robocode.roborumble/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.roborumble/target/classes"); + setup.AddClassPath(prefix + "../../robocode.samples/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.samples/target/classes"); + setup.AddClassPath(prefix + "../../robocode.sound/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.sound/target/classes"); + setup.AddClassPath(prefix + "../../robocode.tests/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.tests/target/classes"); + setup.AddClassPath(prefix + "../../robocode.ui/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.ui/target/classes"); + setup.AddClassPath(prefix + "../../robocode.ui.editor/target/Test-classes"); + setup.AddClassPath(prefix + "../../robocode.ui.editor/target/classes"); + setup.AddClassPath(prefix + "robocode.dotnet.api/target/Test-classes"); + setup.AddClassPath(prefix + "robocode.dotnet.api/target/classes"); + setup.AddClassPath(prefix + "robocode.dotnet.host/target/Test-classes"); + setup.AddClassPath(prefix + "robocode.dotnet.host/target/classes"); + setup.AddClassPath(prefix + "robocode.dotnet.nhost/target/Test-classes"); + setup.AddClassPath(prefix + "robocode.dotnet.nhost/target/classes"); + setup.AddClassPath(prefix + "robocode.dotnet.samples/target/Test-classes"); + setup.AddClassPath(prefix + "robocode.dotnet.samples/target/classes"); + setup.AddClassPath(prefix + "robocode.dotnet.tests/target/Test-classes"); + setup.AddClassPath(prefix + "robocode.dotnet.tests/target/classes"); + env = Bridge.CreateJVM(setup); + Bridge.RegisterAssembly(typeof (TestBase).Assembly); + Bridge.RegisterAssembly(typeof (DllRootHelper).Assembly); + } + + [TestFixtureTearDown] + public void TearDown() + { + //Assert.AreEqual(JNIResult.JNI_OK, vm.DestroyJavaVM()); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/robocode.dotnet.ntests.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/robocode.dotnet.ntests.csproj new file mode 100644 index 0000000..d0f9444 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.ntests/src/robocode.dotnet.ntests.csproj @@ -0,0 +1,108 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {B3487E2D-2737-4C04-AA71-B9A726B3F781} + Library + net.sf.robocode.dotnet + robocode.dotnet.ntests-1.9.2.4 + v3.5 + 512 + false + ..\..\tools\keys\robocode.snk + + + + + 3.5 + + + + true + full + false + ..\target\ + ..\target\obj\ + DEBUG;TRACE + prompt + 4 + false + true + + + pdbonly + true + ..\target\ + ..\target\obj\ + + + prompt + 4 + true + + + + False + ..\..\tools\lib\jni4net.n-0.8.7.0.dll + + + False + ..\..\tools\lib\nunit.framework-2.4.3.0.dll + + + + + + + + + + + + + + {7E0900D3-6E8F-48EB-86DB-AA767AA90B84} + robocode.dotnet.api + + + {674AED55-B9EC-4C7D-8E0B-1B2471C578B2} + robocode.dotnet.control.api + + + {674AED55-B9EC-4C7D-8E0B-1B2481C578B2} + robocode.dotnet.nhost + + + {B3487E2D-2737-4C04-AA71-B9A726B3F787} + robocode.dotnet.robotscs + + + {80857B97-6397-487B-A9F5-B07026DCBB66} + robocode.dotnet.samples + + + + + + + + + + + if not exist $(OutDir)\build-sources\generated-sources\META-INF mkdir $(OutDir)\build-sources\generated-sources\META-INF\ +echo [assembly: System.Reflection.AssemblyVersion("0.0.0.0")] > $(OutDir)\build-sources\generated-sources\META-INF\AssemblyInfo.cs + + copy "$(SolutionDir)\tools\lib\*.dll" "$(TargetDir)" +copy "$(SolutionDir)\tools\lib\*.jar" "$(TargetDir)" + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/.project new file mode 100644 index 0000000..21402e0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/.project @@ -0,0 +1,10 @@ + + + robocode.dotnet.robotscs + .NET test robots for Robocode. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.dotnet.api + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..6687c7a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,10 @@ +#Tue Nov 27 22:34:11 CET 2012 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 +encoding/src/main/resources=8859_1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/test/resources=8859_1 +encoding/src=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/pom.xml new file mode 100644 index 0000000..ba58d91 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + robocode.dotnet.robotscs + dotnet:library + Robocode .NET Test Robots + .NET test robots for Robocode + + robocode.dotnet + net.sf.robocode + ${robocode.dotnet.version} + + + + net.sf.robocode + robocode.dotnet.api + ${project.version} + dotnet:library + + + + src + + + org.sonatype.nmaven.plugins + maven-dotnet-compiler-plugin + + /warn:0 + + + + org.jvnet.maven-antrun-extended-plugin + maven-antrun-extended-plugin + + + process-classes + + + + + + + run + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/robocode.dotnet.robotscs.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/robocode.dotnet.robotscs.iml new file mode 100644 index 0000000..3d67425 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/robocode.dotnet.robotscs.iml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLongerCs.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLongerCs.cs new file mode 100644 index 0000000..4f690cf --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLongerCs.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +public class NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLongerCs : Robot +{ + public override void Run() + { + while (true) + { + Ahead(1); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(1); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/NoPackageShortNameCs.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/NoPackageShortNameCs.cs new file mode 100644 index 0000000..0d79f89 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/NoPackageShortNameCs.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +public class NoPackageShortNameCs : Robot +{ + public override void Run() + { + while (true) + { + Ahead(1); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(1); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/SampleCs.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/SampleCs.csproj new file mode 100644 index 0000000..478e6ae --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/SampleCs.csproj @@ -0,0 +1,91 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {80857B97-6397-487B-A9F5-B07026DCB666} + Library + SampleCs + samplescs-1.9.2.4 + v4.0 + 512 + + + 3.5 + + + + true + full + false + .\ + obj\ + DEBUG;TRACE + prompt + 4 + false + false + + + pdbonly + true + .\ + obj\ + + + prompt + 4 + true + + + + False + ..\libs\robocode.dll + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/SampleCs.sln b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/SampleCs.sln new file mode 100644 index 0000000..66ab900 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/SampleCs.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleCs", "SampleCs.csproj", "{80857B97-6397-487B-A9F5-B07026DCB666}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {80857B97-6397-487B-A9F5-B07026DCB666}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80857B97-6397-487B-A9F5-B07026DCB666}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80857B97-6397-487B-A9F5-B07026DCB666}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80857B97-6397-487B-A9F5-B07026DCB666}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/robocode.dotnet.robotscs.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/robocode.dotnet.robotscs.csproj new file mode 100644 index 0000000..9405ace --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/robocode.dotnet.robotscs.csproj @@ -0,0 +1,114 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {B3487E2D-2737-4C04-AA71-B9A726B3F787} + Library + net.sf.robocode.dotnet + robocode.dotnet.robotscs-1.9.2.4 + v3.5 + 512 + false + ..\..\tools\keys\robocode.snk + + + 3.5 + + + + true + full + false + ..\target\ + ..\target\obj\ + DEBUG;TRACE + prompt + 4 + false + false + + + pdbonly + true + ..\target\ + ..\target\obj\ + + + prompt + 4 + true + + + + False + ..\..\robocode.dotnet.api\target\robocode.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + + if not exist $(OutDir)\build-sources\generated-sources\META-INF mkdir $(OutDir)\build-sources\generated-sources\META-INF\ +echo [assembly: System.Reflection.AssemblyVersion("0.0.0.0")] > $(OutDir)\build-sources\generated-sources\META-INF\AssemblyInfo.cs + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/robocode/BadNamespaceCs.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/robocode/BadNamespaceCs.cs new file mode 100644 index 0000000..9e3711d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/robocode/BadNamespaceCs.cs @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +namespace Robocode +{ + public class BadNamespaceCs : Robot + { + public override void Run() + { + while (true) + { + Ahead(1); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(1); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/Ahead.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/Ahead.cs new file mode 100644 index 0000000..e8e1c62 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/Ahead.cs @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + /** + * @author Pavel Savara (original) + */ + + public class Ahead : AdvancedRobot + { + public override void Run() + { + Ahead(100); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BadFirePower.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BadFirePower.cs new file mode 100644 index 0000000..ae07ab0 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BadFirePower.cs @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + /** + * @author Pavel Savara (original) + */ + + public class BadFirePower : AdvancedRobot + { + public override void Run() + { + while (true) + { + Bullet bullet = SetFireBullet(Time - 12.0); + + if (bullet != null) + { + Out.WriteLine(Time + " Bullet power: " + bullet.Power); + } + else + { + Out.WriteLine(Time + " No bullet"); + } + Execute(); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BattleLost.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BattleLost.cs new file mode 100644 index 0000000..3fda29b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BattleLost.cs @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class BattleLost : Robot + { + public override void Run() + { + while (true) + { + Ahead(1); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(1); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } + + + public override void OnWin(WinEvent e) + { + Out.WriteLine("Win!"); + } + + public override void OnDeath(DeathEvent e) + { + Out.WriteLine("Death!"); + } + + public override void OnBattleEnded(BattleEndedEvent evnt) + { + Out.WriteLine("BattleEnded!"); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BattleWin.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BattleWin.cs new file mode 100644 index 0000000..64115f4 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BattleWin.cs @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class BattleWin : Robot + { + public override void Run() + { + while (true) + { + Ahead(100); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(100); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } + + + public override void OnScannedRobot(ScannedRobotEvent e) + { + Fire(1); + } + + + public override void OnHitByBullet(HitByBulletEvent e) + { + TurnLeft(90 - e.Bearing); + } + + + public override void OnWin(WinEvent e) + { + Out.WriteLine("Win!"); + } + + + public override void OnDeath(DeathEvent e) + { + Out.WriteLine("Death!"); + } + + + public override void OnBattleEnded(BattleEndedEvent evnt) + { + Out.WriteLine("BattleEnded!"); + } + + public override void OnRoundEnded(RoundEndedEvent evnt) + { + Out.WriteLine("RoundEnded!"); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BodyTurnRate.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BodyTurnRate.cs new file mode 100644 index 0000000..1ab0988 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/BodyTurnRate.cs @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; +using Robocode.Util; + +namespace tested.robotscs +{ + /** + * @author Flemming N. Larsen (original) + */ + + public class BodyTurnRate : AdvancedRobot + { + public override void Run() + { + // Test turn rate at all speed moving ahead and turning left + + SetAhead(1000); + SetTurnLeft(360); + executeAndDumpTurnRate9turns(); + + stopMoving(); + + // Test turn rate at all speed moving ahead and turning right + + SetAhead(1000); + SetTurnRight(360); + executeAndDumpTurnRate9turns(); + + stopMoving(); + + // Test turn rate at all speed moving back and turning right + + SetBack(1000); + SetTurnRight(360); + executeAndDumpTurnRate9turns(); + + stopMoving(); + + // Test turn rate at all speed moving back and turning left + + SetBack(1000); + SetTurnLeft(360); + executeAndDumpTurnRate9turns(); + + stopMoving(); + } + + private void executeAndDumpTurnRate9turns() + { + for (int i = 0; i < 9; i++) + { + executeAndDumpTurnRate(); + } + } + + private void executeAndDumpTurnRate() + { + double lastHeading = Heading; + double lastVelocity = Velocity; + + Execute(); + + double turnRate = Utils.NormalRelativeAngleDegrees(Heading - lastHeading); + + lastHeading = Heading; + + Out.WriteLine(Time + ": " + lastVelocity + ", " + turnRate); + } + + private void stopMoving() + { + SetAhead(0); + SetTurnLeft(0); + + for (int i = 0; i < 6; i++) + { + executeAndDumpTurnRate(); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/CustomEvents.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/CustomEvents.cs new file mode 100644 index 0000000..3557f26 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/CustomEvents.cs @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class CustomEvents : AdvancedRobot + { + public override void Run() + { + AddCustomEvent("onTick99", 99, c => true); + AddCustomEvent("onTick30", 30, c => true); + + AddCustomEvent("onLowEnergy98", 98, c => Energy < 20); + + while (true) + { + Ahead(100); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(100); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } + + public override void OnCustomEvent(CustomEvent e) + { + Out.WriteLine(Time + " " + e.Condition.Name); + } + + public override void OnScannedRobot(ScannedRobotEvent e) + { + Out.WriteLine(Time + " onScannedRobot10"); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/DieFast.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/DieFast.cs new file mode 100644 index 0000000..d660e5d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/DieFast.cs @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; +using Robocode.Exception; + +namespace tested.robotscs +{ + public class DieFast : Robot + { + public override void Run() + { + throw new RobotException(); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/EnvAttack.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/EnvAttack.cs new file mode 100644 index 0000000..b7595f5 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/EnvAttack.cs @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using Robocode; + +namespace tested.robotscs +{ + public class EnvAttack : AdvancedRobot + { + public override void Run() + { + // attack + Environment.SetEnvironmentVariable("NOSECURITY", "true"); + + // noinspection InfiniteLoopStatement + for (;;) + { + TurnLeft(100); + Ahead(10); + TurnLeft(100); + Back(10); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/EventPriorityFilter.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/EventPriorityFilter.cs new file mode 100644 index 0000000..cc8f570 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/EventPriorityFilter.cs @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class EventPriorityFilter : AdvancedRobot + { + public override void Run() + { + // noinspection InfiniteLoopStatement + for (;;) + { + Ahead(10); // make sure we eventually hits a wall to receive onHitWall + } + } + + + public override void OnScannedRobot(ScannedRobotEvent evnt) + { + Out.WriteLine("Scanned!!!"); // a robot was Scanned -> problem! + } + + + public override void OnHitWall(HitWallEvent e) + { + // when the radar is turned here, at least another robot should be Scanned + // but Event should not be dispatched because we are in handler with higher priority + TurnRadarRight(360); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FairPlay.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FairPlay.cs new file mode 100644 index 0000000..bfceb70 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FairPlay.cs @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; +using Robocode.Util; + +namespace tested.robotscs +{ + public class FairPlay : AdvancedRobot + { + public override void Run() + { + SetTurnRadarRightRadians(1d/0d); + } + + public override void OnScannedRobot(ScannedRobotEvent e) + { + SetTurnRadarLeft(RadarTurnRemaining); + SetTurnGunRightRadians( + Utils.NormalRelativeAngle(e.BearingRadians + HeadingRadians - GunHeadingRadians)); + SetFire(3); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FileAttack.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FileAttack.cs new file mode 100644 index 0000000..b7ddd28 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FileAttack.cs @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.IO; +using Robocode; + +namespace tested.robotscs +{ + public class FileAttack : AdvancedRobot + { + public override void Run() + { + for (;;) + { + TurnLeft(100); + Ahead(10); + TurnLeft(100); + Back(10); + } + } + + + public override void OnScannedRobot(ScannedRobotEvent evnt) + { + readAttack(); + writeAttack(); + } + + private void readAttack() + { + try + { + FileStream fs = new FileStream(@"C:\MSDOS.SYS", FileMode.OpenOrCreate, FileAccess.Read); + + Out.WriteLine(fs.ReadByte()); + Out.WriteLine(fs.ReadByte()); + Out.WriteLine(fs.ReadByte()); + Out.WriteLine(fs.ReadByte()); + fs.Close(); + } + catch (Exception e) + { + Out.WriteLine(e); + } + } + + private void writeAttack() + { + try + { + FileStream fs = new FileStream(@"C:\MSDOS.SYS", FileMode.OpenOrCreate, FileAccess.ReadWrite); + fs.WriteByte(0xBA); + fs.WriteByte(0xDF); + fs.WriteByte(0x00); + fs.WriteByte(0xD0); + fs.Close(); + } + catch (Exception e) + { + Out.WriteLine(e); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FileWriteSize.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FileWriteSize.cs new file mode 100644 index 0000000..79fd89b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FileWriteSize.cs @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.IO; +using Robocode; + +namespace tested.robotscs +{ + public class FileWriteSize : AdvancedRobot + { + public override void Run() + { + Out.WriteLine("Data quota: " + DataQuotaAvailable); + Out.WriteLine("Data directory: " + GetDataDirectory()); + + using (Stream dataFile = GetDataFile("test.txt")) + { + byte[] buf = new byte[100000]; + for (int i = 0; i < 3; i++) + { + dataFile.Write(buf, 0, buf.Length); + } + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FormsAttack.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FormsAttack.cs new file mode 100644 index 0000000..90419d4 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/FormsAttack.cs @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.IO; +using System.Windows.Forms; +using Robocode; + +namespace tested.robotscs +{ + public class FormsAttack : AdvancedRobot + { + public override void Run() + { + for (;;) + { + TurnLeft(100); + Ahead(10); + TurnLeft(100); + Back(10); + } + } + + private Form f; + + public override void OnScannedRobot(ScannedRobotEvent evnt) + { + f = new Form(); + f.Show(); + f.Shown += f_Shown; + } + + private void f_Shown(object sender, EventArgs e) + { + f.Invoke(new Action(writeAttack)); + } + + private void writeAttack(int i) + { + try + { + FileStream fs = new FileStream(@"C:\MSDOS.SYS", FileMode.OpenOrCreate, FileAccess.ReadWrite); + fs.WriteByte(0xBA); + fs.WriteByte(0xDF); + fs.WriteByte(0x00); + fs.WriteByte(0xD0); + fs.Close(); + } + catch (Exception e) + { + Out.WriteLine(e); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/GunHeat.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/GunHeat.cs new file mode 100644 index 0000000..05b10c6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/GunHeat.cs @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class GunHeat : AdvancedRobot + { + public override void Run() + { + while (true) + { + SetFireBullet(3.0); + Out.WriteLine(Time + " gunHeat after fire: " + GunHeat); + Execute(); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/GunTurnRate.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/GunTurnRate.cs new file mode 100644 index 0000000..48cbc6c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/GunTurnRate.cs @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using Robocode; +using Robocode.Util; + +namespace tested.robotscs +{ + /** + * @author Flemming N. Larsen (original) + */ + + public class GunTurnRate : AdvancedRobot + { + public override void Run() + { + MaxTurnRate = (5); + + SetTurnGunLeft(Double.PositiveInfinity); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + SetTurnGunRight(Double.PositiveInfinity); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + SetTurnLeft(Double.PositiveInfinity); + SetTurnGunLeft(Double.PositiveInfinity); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + SetTurnRight(Double.PositiveInfinity); + SetTurnGunRight(Double.PositiveInfinity); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + MaxTurnRate = (20); + + SetTurnLeft(Double.PositiveInfinity); + SetTurnGunLeft(Double.PositiveInfinity); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + SetTurnRight(Double.PositiveInfinity); + SetTurnGunRight(Double.PositiveInfinity); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + IsAdjustGunForRobotTurn = (false); + + SetTurnRight(Double.PositiveInfinity); + SetTurnGunLeft(Double.PositiveInfinity); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + SetTurnLeft(Double.PositiveInfinity); + SetTurnGunRight(Double.PositiveInfinity); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + } + + private void executeAndDumpTurnRate() + { + double lastHeading = GunHeading; + + Execute(); + + double turnRate = Utils.NormalRelativeAngleDegrees(GunHeading - lastHeading); + + Out.WriteLine(Time + ": " + turnRate); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/HttpAttack.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/HttpAttack.cs new file mode 100644 index 0000000..18fd910 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/HttpAttack.cs @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Net; +using Robocode; + +namespace tested.robotscs +{ + public class HttpAttack : AdvancedRobot + { + private static string HTTP_ADDR = "http://robocode.sourceforge.net/"; + + public override void Run() + { + WebClient req = new WebClient(); + using (var res = req.OpenRead(HTTP_ADDR)) + { + res.Read(new byte[100000], 0, 100000); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/InteruptibleEvent.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/InteruptibleEvent.cs new file mode 100644 index 0000000..5c07a3a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/InteruptibleEvent.cs @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class InteruptibleEvent : AdvancedRobot + { + public override void Run() + { + SetEventPriority("HitWallEvent", GetEventPriority("ScannedRobotEvent")); // make same as scan + + // noinspection InfiniteLoopStatement + for (;;) + { + Ahead(10); // make sure we eventually hits a wall to receive onHitWall + } + } + + public override void OnScannedRobot(ScannedRobotEvent evnt) + { + Out.WriteLine("Scanned!!!"); // a robot was Scanned -> success! + } + + public override void OnHitWall(HitWallEvent e) + { + IsInterruptible = (true); // make sure that the Event handler can be interrupted and restarted + TurnRadarRight(360); // when the radar is turned here, at least another robot should be Scanned + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/JuniorEvents.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/JuniorEvents.cs new file mode 100644 index 0000000..5df75fb --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/JuniorEvents.cs @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using Robocode; +using Robocode.RobotInterfaces; +using Robocode.RobotInterfaces.Peer; +using Robocode.Util; + +namespace tested.robotscs +{ + public class JuniorEvents : IJuniorRobot, IBasicEvents, IRunnable + { + private IBasicRobotPeer peer; + private TextWriter Out; + private readonly Dictionary counts = new Dictionary(); + private Bullet bullet; + + public void Run() + { + // noinspection InfiniteLoopStatement + while (true) + { + peer.Move(100); // Move ahead 100 + peer.TurnGun(Math.PI*2); // Spin gun around + peer.Move(-100); // Move back 100 + peer.TurnGun(Math.PI*2); // Spin gun around + } + } + + public IRunnable GetRobotRunnable() + { + return this; + } + + public IBasicEvents GetBasicEventListener() + { + return this; + } + + public void SetPeer(IBasicRobotPeer peer) + { + this.peer = peer; + } + + public void SetOut(TextWriter output) + { + Out = output; + } + + public void OnStatus(StatusEvent evnt) + { + count(evnt); + IGraphics g = peer.GetGraphics(); + + g.DrawEllipse(Pens.Orange, (int) (peer.GetX() - 55), (int) (peer.GetY() - 55), 110, 110); + } + + public void OnBulletHit(BulletHitEvent evnt) + { + count(evnt); + } + + public void OnBulletHitBullet(BulletHitBulletEvent evnt) + { + count(evnt); + } + + public void OnBulletMissed(BulletMissedEvent evnt) + { + count(evnt); + } + + public void OnDeath(DeathEvent evnt) + { + count(evnt); + } + + public void OnHitByBullet(HitByBulletEvent evnt) + { + count(evnt); + } + + public void OnHitRobot(HitRobotEvent evnt) + { + count(evnt); + } + + public void OnHitWall(HitWallEvent evnt) + { + count(evnt); + } + + public void OnRobotDeath(RobotDeathEvent evnt) + { + count(evnt); + } + + public void OnWin(WinEvent evnt) + { + count(evnt); + + // this is tested output + foreach (KeyValuePair s in counts) + { + Out.WriteLine(s.Key + " " + s.Value); + } + + Out.WriteLine("last bullet heading " + bullet.HeadingRadians.ToString("F5")); + } + + public void OnScannedRobot(ScannedRobotEvent evnt) + { + count(evnt); + + // Turn gun to point at the Scanned robot + peer.TurnGun(Utils.NormalAbsoluteAngle(peer.GetBodyHeading() + evnt.BearingRadians - peer.GetGunHeading())); + // + + // Fire! + const double power = 1; + + Bullet firedBullet = peer.Fire(power); + + if (firedBullet != null) + { + bullet = firedBullet; + } + } + + private void count(Event evnt) + { + String name = evnt.GetType().FullName; + object curr; + + if (!counts.TryGetValue(name, out curr)) + { + curr = 0; + } + counts[name] = ((int) curr) + 1; + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/MaxTurnRate.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/MaxTurnRate.cs new file mode 100644 index 0000000..80f7e04 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/MaxTurnRate.cs @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using Robocode; +using Robocode.Util; + +namespace tested.robotscs +{ + public class MaxTurnRate : AdvancedRobot + { + public override void Run() + { + SetTurnLeft(Double.PositiveInfinity); + + for (int i = 0; i < 13; i++) + { + MaxTurnRate = (i); + executeAndDumpTurnRate(); + } + + SetTurnRight(Double.PositiveInfinity); + + for (int i = 0; i < 13; i++) + { + MaxTurnRate = (i); + executeAndDumpTurnRate(); + } + } + + private void executeAndDumpTurnRate() + { + double lastHeading = Heading; + + Execute(); + + double turnRate = Utils.NormalRelativeAngleDegrees(Heading - lastHeading); + + Out.WriteLine(Time + ": " + Velocity.ToString("F1") + ", " + turnRate.ToString("F1")); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/MaxVelocity.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/MaxVelocity.cs new file mode 100644 index 0000000..0faa940 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/MaxVelocity.cs @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class MaxVelocity : AdvancedRobot + { + public override void Run() + { + for (;;) + { + int time = (int) Time; + + if (time < 200) + { + Out.WriteLine(time + ": " + Velocity); + } + + switch (time) + { + case 1: + SetAhead(1000); + break; + + case 20: + SetBack(1000); + break; + + case 40: + MaxVelocity = (4.2); + SetAhead(1000); + break; + + case 60: + SetBack(1000); + break; + + case 80: + MaxVelocity = (100); + SetAhead(1000); + break; + + case 100: + SetBack(1000); + break; + + case 120: + MaxVelocity = (-2); + SetAhead(1000); + break; + + case 140: + SetBack(1000); + break; + + case 160: + MaxVelocity = (0); + SetAhead(1000); + break; + + case 180: + SetBack(1000); + break; + } + Execute(); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/PrivateConstructor.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/PrivateConstructor.cs new file mode 100644 index 0000000..976b31f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/PrivateConstructor.cs @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class PrivateConstructor : Robot + { + private PrivateConstructor() + { + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RadarTurnRateAndSetAdjust.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RadarTurnRateAndSetAdjust.cs new file mode 100644 index 0000000..d9f578d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RadarTurnRateAndSetAdjust.cs @@ -0,0 +1,138 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using Robocode; +using Robocode.Util; + +namespace tested.robotscs +{ + public class RadarTurnRateAndIsAdjust : AdvancedRobot + { + public override void Run() + { + // -- Turn 1 -- + SetTurnRadarRight(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. radar turn rate = 45 + + // -- Turn 2 -- + SetTurnGunRight(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. gun + radar turn rate = 20 + 45 = 65 + + // -- Turn 3 -- + SetTurnRight(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. robot + gun + radar turn rate = 10 + 20 + 45 = 75 + + // -- Turn 4 -- + SetTurnRadarLeft(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. robot + gun - radar turn rate = 10 + 20 - 45 = -15 + + // -- Turn 5 -- + SetTurnGunLeft(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. robot + gun - radar turn rate = 10 - 20 - 45 = -55 + + // -- Turn 6 -- + SetTurnLeft(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. robot + gun - radar turn rate = -10 - 20 - 45 = -75 + + // -- Turn 7 -- + IsAdjustRadarForGunTurn = (false); + SetTurnRight(14); + SetTurnGunRight(15); + SetTurnRadarRight(7); + executeAndDumpTurnRate(); + // Expected turn rate: robot + gun + radar turn rate = 14 + 15 + 7 = 32 + + // -- Turn 8 -- + IsAdjustGunForRobotTurn = (false); + IsAdjustRadarForRobotTurn = (false); + IsAdjustRadarForGunTurn = (true); + SetTurnRight(14); + SetTurnGunLeft(15); + SetTurnRadarRight(7); + executeAndDumpTurnRate(); + // Expected turn rate: robot (max) + radar turn rate (ignoring gun turn rate, but not robot turn rate) = 10 + 7 = 17 + + // -- Turn 9 -- + IsAdjustGunForRobotTurn = (false); + IsAdjustRadarForRobotTurn = (true); + IsAdjustRadarForGunTurn = (true); + SetTurnRight(14); + SetTurnGunLeft(15); + SetTurnRadarRight(35); + executeAndDumpTurnRate(); + // Expected turn rate: robot turn rate (ignoring both gun and body turn rate) = 35 + + // -- Turn 10 -- + IsAdjustGunForRobotTurn = (false); + IsAdjustRadarForRobotTurn = (false); + IsAdjustRadarForGunTurn = (true); + SetTurnRight(14); + SetTurnGunLeft(15); + SetTurnRadarLeft(7); + executeAndDumpTurnRate(); + // Expected turn rate: robot (max) + radar turn rate (ignoring gun turn rate, but not robot turn rate) = 10 - 7 = 3 + + // -- Turn 11 -- + IsAdjustGunForRobotTurn = (false); + IsAdjustRadarForRobotTurn = (true); + IsAdjustRadarForGunTurn = (true); + SetTurnRight(4); + SetTurnGunRight(60); + SetTurnRadarLeft(100); + executeAndDumpTurnRate(); + // Expected turn rate: robot (max) turn rate (ignoring both gun and body turn rate) = -20 + + // -- Turn 12 -- + IsAdjustGunForRobotTurn = (false); + IsAdjustRadarForRobotTurn = (false); + IsAdjustRadarForGunTurn = (true); + SetTurnRight(Double.PositiveInfinity); + SetTurnGunRight(Double.PositiveInfinity); + SetTurnRadarRight(Double.PositiveInfinity); + executeAndDumpTurnRate(); + // Expected turn rate: IsAdjusts are all ignored, max. robot + gun + radar turn rate = 10 + 20 + 45 = 75 + + // -- Turn 13 -- + IsAdjustGunForRobotTurn = (true); + IsAdjustRadarForRobotTurn = (false); + IsAdjustRadarForGunTurn = (true); + SetTurnRight(Double.NegativeInfinity); + SetTurnGunRight(Double.NegativeInfinity); + SetTurnRadarRight(Double.NegativeInfinity); + executeAndDumpTurnRate(); + // Expected turn rate: IsAdjusts are all ignored, max. robot + gun + radar turn rate = -10 - 20 - 45 = -75 + + // -- Turn 14 -- + IsAdjustGunForRobotTurn = (true); + IsAdjustRadarForRobotTurn = (true); + IsAdjustRadarForGunTurn = (true); + SetTurnLeft(Double.NegativeInfinity); + SetTurnGunLeft(Double.NegativeInfinity); + SetTurnRadarLeft(Double.NegativeInfinity); + executeAndDumpTurnRate(); + // Expected turn rate: IsAdjusts are all ignored, max. robot + gun + radar turn rate = -(-10) - (-20) - 45 = -15 + } + + private void executeAndDumpTurnRate() + { + double lastHeading = RadarHeading; + + Execute(); + + double turnRate = Utils.NormalRelativeAngleDegrees(RadarHeading - lastHeading); + + Out.WriteLine(Time + ": " + turnRate); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/Random.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/Random.cs new file mode 100644 index 0000000..d8bc2d3 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/Random.cs @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; +using Robocode.Util; + +namespace tested.robotscs +{ + public class Random : Robot + { + private readonly System.Random random = Utils.GetRandom(); + + public override void Run() + { + while (true) + { + Ahead(100*random.Next()); + TurnRight(180*random.Next()); + Back(100*random.Next()); + TurnLeft(360*random.Next()); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RateControl.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RateControl.cs new file mode 100644 index 0000000..1703a4a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RateControl.cs @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class RateControl : RateControlRobot + { + public override void Run() + { + for (int turnNumber = 0; turnNumber < 80; turnNumber++) + { + if (turnNumber == 0) + { + TurnRate = (4.5); + } + else if (turnNumber == 10) + { + TurnRate = (-9); + } + else if (turnNumber == 20) + { + TurnRate = (0); + VelocityRate = (2); + } + else if (turnNumber == 25) + { + VelocityRate = (-8); + } + else if (turnNumber == 35) + { + VelocityRate = (0); + GunRotationRate = (9); + } + else if (turnNumber == 45) + { + GunRotationRate = (-4.5); + } + else if (turnNumber == 55) + { + GunRotationRate = (0); + RadarRotationRate = (9); + } + else if (turnNumber == 65) + { + RadarRotationRate = (-4.5); + } + else if (turnNumber == 75) + { + RadarRotationRate = (0); + } + Execute(); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/ReflectionAttack.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/ReflectionAttack.cs new file mode 100644 index 0000000..4ba2594 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/ReflectionAttack.cs @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Reflection; +using Robocode; + +namespace tested.robotscs +{ + public class ReflectionAttack : AdvancedRobot + { + public override void Run() + { + FieldInfo fieldInfo = typeof(Console).GetField("_out", BindingFlags.Static | BindingFlags.NonPublic); + object obj = fieldInfo.GetValue(null); + fieldInfo.SetValue(null, null); + + MethodInfo method = obj.GetType().GetMethod("Write", new[] { typeof(string) }); + method.Invoke(obj, new Object[] { "Hello World" }); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RobotDeathEvents.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RobotDeathEvents.cs new file mode 100644 index 0000000..eed772e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/RobotDeathEvents.cs @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; +using Robocode.Exception; + +namespace tested.robotscs +{ + public class RobotDeathEvents : AdvancedRobot + { + private bool dead; + private long enemyCount; + + public override void Run() + { + enemyCount = Others; + while (!dead) + { + if (enemyCount != Others) + { + throw new RobotException("enemyCount != GetOthers()"); + } + Execute(); + } + } + + public override void OnRobotDeath(RobotDeathEvent e) + { + enemyCount--; + } + + public override void OnDeath(DeathEvent e) + { + dead = true; + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/SkipTurns.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/SkipTurns.cs new file mode 100644 index 0000000..582530b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/SkipTurns.cs @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Threading; +using Robocode; +using Robocode.Exception; +using Thread = Robocode.Thread; + +namespace tested.robotscs +{ + public class SkipTurns : AdvancedRobot + { + private volatile int skipped = 0; + + private const int limit = 5; + + public override void Run() + { + // noinspection InfiniteLoopStatement + for (;;) + { + if (skipped > limit) + { + throw new RobotException("satisfied, end battle please"); + } + TurnLeft(10); + if (skipped > limit) + { + // satisfied, end battle please + throw new RobotException(); + } + Ahead(1); + if (skipped > limit) + { + // satisfied, end battle please + throw new RobotException(); + } + TurnLeft(10); + if (skipped > limit) + { + // satisfied, end battle please + throw new RobotException(); + } + Back(1); + } + } + + + public override void OnStatus(StatusEvent e) + { + Out.WriteLine("live"); + slowResponse(); + } + + + public override void OnSkippedTurn(SkippedTurnEvent evnt) + { + Out.WriteLine("Skipped!!!"); + + skipped++; + } + + private void slowResponse() + { + try + { + if (skipped > 3) + { + Thread.Sleep(3000); + } + else + { + Thread.Sleep(100); + } + } + catch (Exception ex) + { + // eat interrupt + Out.WriteLine(ex); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/TestTeam.team b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/TestTeam.team new file mode 100644 index 0000000..69457ad --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/TestTeam.team @@ -0,0 +1,7 @@ +#Robocode robot CS team +#Sat Oct 25 22:23:58 CEST 2008 +team.members=SampleCsTeam.MyFirstLeader,SampleCsTeam.MyFirstDroid,SampleCs.Fire +team.author.name= +robocode.version=unknown +uuid=8abd63e8-1156-4fb4-a81f-eb10fca9596d +team.description=testteam diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/ThreadAttack.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/ThreadAttack.cs new file mode 100644 index 0000000..9cdce98 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/ThreadAttack.cs @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Threading; +using Robocode; +using Thread = Robocode.Thread; + +namespace tested.robotscs +{ + public class ThreadAttack : AdvancedRobot + { + public override void Run() + { + // noinspection InfiniteLoopStatement + for (;;) + { + TurnLeft(100); + Ahead(10); + TurnLeft(100); + Back(10); + } + } + + + public override void OnScannedRobot(ScannedRobotEvent evnt) + { + runAttack(); + } + + private void runAttack() + { + Thread t2 = new Thread(attack); + t2.Start(); + } + + private readonly Semaphore s = new Semaphore(0, 1); + + private int counter; + + public void attack() + { + int id = counter++; + + Out.WriteLine("Running id:" + id); + + try + { + s.WaitOne(); + } + catch (Exception e) + { + Out.WriteLine("Interrupted id:" + id + e.Message); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/TooLongNameThisIsReallyTooLongNameCs.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/TooLongNameThisIsReallyTooLongNameCs.cs new file mode 100644 index 0000000..6f30aed --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/TooLongNameThisIsReallyTooLongNameCs.cs @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tested.robotscs +{ + public class TooLongNameThisIsReallyTooLongNameCs : Robot + { + public override void Run() + { + while (true) + { + Ahead(1); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(1); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/UndeadThread.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/UndeadThread.cs new file mode 100644 index 0000000..4c05a89 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/UndeadThread.cs @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using Robocode; + +namespace tested.robotscs +{ + /** + * @author Pavel Savara (original) + */ + + public class UndeadThread : AdvancedRobot + { + public override void Run() + { + Out.WriteLine("I will live forever!"); + // noinspection InfiniteLoopStatement + while (true) + { + body(); + } + } + + private void body() + { + bool normal=false; + try + { + loop(); + } + catch(Exception) + { + Out.WriteLine("that's my time"); + normal = true; + } + finally + { + if (!normal) + { + // spamming the console + Out.WriteLine("Swalowed it, HA HA HA HA HAAAAA !!!!!"); + loop(); + body(); + } + } + } + + private void loop() + { + while (true) + { + TurnLeft(100); + Ahead(10); + TurnLeft(100); + Back(10); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/WatchBullets.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/WatchBullets.cs new file mode 100644 index 0000000..c096e60 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tested/robotscs/WatchBullets.cs @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Globalization; +using Robocode; +using Robocode.Util; + +namespace tested.robotscs +{ + /* + * @author Pavel Savara (original) + */ + + public class WatchBullets : AdvancedRobot + { + public override void Run() + { + while (true) + { + Ahead(100); + TurnGunRight(360); + Back(100); + TurnGunRight(360); + } + } + + private Bullet bullet; + + public override void OnStatus(StatusEvent evnt) + { + dump(); + } + + + public override void OnBulletHit(BulletHitEvent evnt) + { + if (bullet != evnt.Bullet) + { + Out.WriteLine("Failed bullet identity"); + } + } + + + public override void OnScannedRobot(ScannedRobotEvent e) + { + // Calculate exact location of the robot + double absoluteBearing = Heading + e.Bearing; + double bearingFromGun = Utils.NormalRelativeAngle(absoluteBearing - GunHeading); + + // If it's close enough, fire! + if (Math.Abs(bearingFromGun) <= 3) + { + TurnGunRight(bearingFromGun); + // We check gun heat here, because calling Fire() + // uses a turn, which could cause us to lose track + // of the other robot. + if (GunHeat == 0 && bullet == null) + { + Bullet lbullet = FireBullet(Math.Min(3 - Math.Abs(bearingFromGun), Energy - .1)); + + bullet = lbullet; + } + } // otherwise just set the gun to turn. + // Note: This will have no effect until we call Scan() + else + { + TurnGunRight(bearingFromGun); + } + // Generates another scan event if we see a robot. + // We only need to call this if the gun (and therefore radar) + // are not turning. Otherwise, scan is called automatically. + if (bearingFromGun == 0) + { + Scan(); + } + } + + private void dump() + { + if (bullet != null) + { + Out.WriteLine( + Time + " " + bullet.X.ToString("F5", CultureInfo.InvariantCulture) + " " + bullet.Y.ToString("F5", CultureInfo.InvariantCulture) + " " + bullet.Heading.ToString("F5", CultureInfo.InvariantCulture) + " " + + bullet.IsActive); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tooLongNamespaceThisIsReallyTooLongNamespace/TooLongNamespaceCs.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tooLongNamespaceThisIsReallyTooLongNamespace/TooLongNamespaceCs.cs new file mode 100644 index 0000000..4279c08 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.robotscs/src/tooLongNamespaceThisIsReallyTooLongNamespace/TooLongNamespaceCs.cs @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace tooLongNamespaceThisIsReallyTooLongNamespace +{ + public class TooLongNamespaceCs : Robot + { + public override void Run() + { + while (true) + { + Ahead(1); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(1); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/.project new file mode 100644 index 0000000..350b981 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/.project @@ -0,0 +1,10 @@ + + + robocode.dotnet.samples + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.dotnet.api + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..554237f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Tue Nov 27 22:34:11 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/pom.xml new file mode 100644 index 0000000..31a2de2 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + robocode.dotnet.samples + Robocode .NET Samples + dotnet:library + + robocode.dotnet + net.sf.robocode + ${robocode.dotnet.version} + + + + net.sf.robocode + robocode.dotnet.api + ${project.version} + dotnet:library + + + + samplescs-${project.version} + src + + + org.sonatype.nmaven.plugins + maven-dotnet-compiler-plugin + + /warn:0 + samplescs-${project.version}.dll + + + + + + src + false + + **/*.vb + **/*.cs + **/*.fs + **/*.fsproj + **/*.properties + **/*.team + **/*.html + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/robocode.dotnet.samples.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/robocode.dotnet.samples.iml new file mode 100644 index 0000000..e5ededf --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/robocode.dotnet.samples.iml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs.csproj new file mode 100644 index 0000000..478e6ae --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs.csproj @@ -0,0 +1,91 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {80857B97-6397-487B-A9F5-B07026DCB666} + Library + SampleCs + samplescs-1.9.2.4 + v4.0 + 512 + + + 3.5 + + + + true + full + false + .\ + obj\ + DEBUG;TRACE + prompt + 4 + false + false + + + pdbonly + true + .\ + obj\ + + + prompt + 4 + true + + + + False + ..\libs\robocode.dll + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs.sln b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs.sln new file mode 100644 index 0000000..66ab900 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleCs", "SampleCs.csproj", "{80857B97-6397-487B-A9F5-B07026DCB666}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {80857B97-6397-487B-A9F5-B07026DCB666}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80857B97-6397-487B-A9F5-B07026DCB666}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80857B97-6397-487B-A9F5-B07026DCB666}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80857B97-6397-487B-A9F5-B07026DCB666}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Corners.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Corners.cs new file mode 100644 index 0000000..f4d4a97 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Corners.cs @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Drawing; +using Robocode; +using Robocode.Util; + +namespace SampleCs +{ + /// + /// Corners - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// This robot moves to a corner, then swings the gun back and forth. + /// If it dies, it tries a new corner in the next round. + ///

+ public class Corners : Robot + { + private int others; // Number of other robots in the game + private static int corner; // Which corner we are currently using + // static so that it keeps it between rounds. + private bool stopWhenSeeRobot; // See goCorner() + + /// + /// run: Corners' main run function. + /// + public override void Run() + { + // Set colors + BodyColor = (Color.Red); + GunColor = (Color.Black); + RadarColor = (Color.Yellow); + BulletColor = (Color.Green); + ScanColor = (Color.Green); + + // Save # of other bots + others = Others; + + // Move to a corner + goCorner(); + + // Initialize gun turn speed to 3 + int gunIncrement = 3; + + // Spin gun back and forth + while (true) + { + for (int i = 0; i < 30; i++) + { + TurnGunLeft(gunIncrement); + } + gunIncrement *= -1; + } + } + + /// + /// goCorner: A very inefficient way to get to a corner. Can you do better? + /// + public void goCorner() + { + // We don't want to stop when we're just turning... + stopWhenSeeRobot = false; + // turn to face the wall to the "right" of our desired corner. + TurnRight(Utils.NormalRelativeAngleDegrees(corner - Heading)); + // Ok, now we don't want to crash into any robot in our way... + stopWhenSeeRobot = true; + // Move to that wall + Ahead(5000); + // Turn to face the corner + TurnLeft(90); + // Move to the corner + Ahead(5000); + // Turn gun to starting point + TurnGunLeft(90); + } + + /// + /// onScannedRobot: Stop and Fire! + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + // Should we stop, or just Fire? + if (stopWhenSeeRobot) + { + // Stop everything! You can safely call stop multiple times. + Stop(); + // Call our custom firing method + smartFire(e.Distance); + // Look for another robot. + // NOTE: If you call scan() inside onScannedRobot, and it sees a robot, + // the game will interrupt the event handler and start it over + Scan(); + // We won't get here if we saw another robot. + // Okay, we didn't see another robot... start moving or turning again. + Resume(); + } + else + { + smartFire(e.Distance); + } + } + + /// + /// smartFire: Custom Fire method that determines firepower based on distance. + /// + /// + /// the distance to the robot to Fire at + /// + public void smartFire(double robotDistance) + { + if (robotDistance > 200 || Energy < 15) + { + Fire(1); + } + else if (robotDistance > 50) + { + Fire(2); + } + else + { + Fire(3); + } + } + + /// + /// onDeath: We died. Decide whether to try a different corner next game. + /// + public override void OnDeath(DeathEvent e) + { + // Well, others should never be 0, but better safe than sorry. + if (others == 0) + { + return; + } + + // If 75% of the robots are still alive when we die, we'll switch corners. + if ((others - Others)/(double) others < .75) + { + corner += 90; + if (corner == 270) + { + corner = -90; + } + Out.WriteLine("I died and did poorly... switching corner to " + corner); + } + else + { + Out.WriteLine("I died but did well. I will still use corner " + corner); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Crazy.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Crazy.cs new file mode 100644 index 0000000..69df1b8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Crazy.cs @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Drawing; +using Robocode; + +namespace SampleCs +{ + /// + /// Crazy - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + /// This robot moves around in a crazy pattern + /// + public class Crazy : AdvancedRobot + { + private bool movingForward; + + /// + /// run: Crazy's main run function + /// + public override void Run() + { + BodyColor = (Color.FromArgb(0, 200, 0)); + GunColor = (Color.FromArgb(0, 150, 50)); + RadarColor = (Color.FromArgb(0, 100, 100)); + BulletColor = (Color.FromArgb(255, 255, 100)); + ScanColor = (Color.FromArgb(255, 200, 200)); + + // Loop forever + while (true) + { + // Tell the game we will want to move ahead 40000 -- some large number + SetAhead(40000); + movingForward = true; + // Tell the game we will want to turn right 90 + SetTurnRight(90); + // At this point, we have indicated to the game that *when we do something*, + // we will want to move ahead and turn right. That's what "set" means. + // It is important to realize we have not done anything yet! + // In order to actually move, we'll want to call a method that + // takes real time, such as WaitFor. + // WaitFor actually starts the action -- we start moving and turning. + // It will not return until we have finished turning. + WaitFor(new TurnCompleteCondition(this)); + // Note: We are still moving ahead now, but the turn is complete. + // Now we'll turn the other way... + SetTurnLeft(180); + // ... and wait for the turn to finish ... + WaitFor(new TurnCompleteCondition(this)); + // ... then the other way ... + SetTurnRight(180); + // .. and wait for that turn to finish. + WaitFor(new TurnCompleteCondition(this)); + // then back to the top to do it all again + } + } + + /// + /// onHitWall: Handle collision with wall. + /// + public override void OnHitWall(HitWallEvent e) + { + // Bounce off! + reverseDirection(); + } + + /// + /// reverseDirection: Switch from ahead to back & vice versa + /// + public void reverseDirection() + { + if (movingForward) + { + SetBack(40000); + movingForward = false; + } + else + { + SetAhead(40000); + movingForward = true; + } + } + + /// + /// onScannedRobot: Fire! + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + Fire(1); + } + + /// + /// onHitRobot: Back up! + /// + public override void OnHitRobot(HitRobotEvent e) + { + // If we're moving the other robot, reverse! + if (e.IsMyFault) + { + reverseDirection(); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Fire.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Fire.cs new file mode 100644 index 0000000..205454a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Fire.cs @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Drawing; +using Robocode; +using Robocode.Util; + +namespace SampleCs +{ + /// + /// Fire - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + /// Sits still. Spins gun around. Moves when hit. + /// + public class Fire : Robot + { + private int dist = 50; // distance to move when we're hit + + /// + /// run: Fire's main run function + /// + public override void Run() + { + // Set colors + BodyColor = (Color.Orange); + GunColor = (Color.Orange); + RadarColor = (Color.Red); + ScanColor = (Color.Red); + BulletColor = (Color.Red); + + // Spin the gun around slowly... forever + while (true) + { + TurnGunRight(5); + } + } + + /// + /// onScannedRobot: Fire! + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + // If the other robot is close by, and we have plenty of life, + // Fire hard! + if (e.Distance < 50 && Energy > 50) + { + Fire(3); + } // otherwise, Fire 1. + else + { + Fire(1); + } + // Call scan again, before we turn the gun + Scan(); + } + + /// + /// onHitByBullet: Turn perpendicular to the bullet, and move a bit. + /// + public override void OnHitByBullet(HitByBulletEvent e) + { + TurnRight(Utils.NormalRelativeAngleDegrees(90 - (Heading - e.Heading))); + + Ahead(dist); + dist *= -1; + Scan(); + } + + /// + /// onHitRobot: Aim at it. Fire Hard! + /// + public override void OnHitRobot(HitRobotEvent e) + { + double turnGunAmt = Utils.NormalRelativeAngleDegrees(e.Bearing + Heading - GunHeading); + + TurnGunRight(turnGunAmt); + Fire(3); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Interactive.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Interactive.cs new file mode 100644 index 0000000..eaa38ef --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Interactive.cs @@ -0,0 +1,218 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using Robocode; +using Robocode.Util; + +namespace SampleCs +{ + /// + /// Interactive - a sample robot by Flemming N. Larsen. + ///

+ /// This is a robot that is controlled using the arrow keys and mouse only. + ///

+ /// Keys: + /// - Arrow up: Move forward + /// - Arrow down: Move backward + /// - Arrow right: Turn right + /// - Arrow left: Turn left + /// Mouse: + /// - Moving: Moves the aim, which the gun will follow + /// - Wheel up: Move forward + /// - Wheel down: Move backward + /// - Button 1: Fire a bullet with power = 1 + /// - Button 2: Fire a bullet with power = 2 + /// - Button 3: Fire a bullet with power = 3 + ///

+ /// The bullet color depends on the Fire power: + /// - Power = 1: Yellow + /// - Power = 2: Orange + /// - Power = 3: Red + ///

+ /// Note that the robot will continue firing as long as the mouse button is + /// pressed down. + ///

+ /// By enabling the "Paint" button on the robot console window for this robot, + /// a cross hair will be painted for the robots current aim (controlled by the + /// mouse). + ///

+ public class Interactive : AdvancedRobot + { + // Move direction: 1 = move forward, 0 = stand still, -1 = move backward + private int moveDirection; + + // Turn direction: 1 = turn right, 0 = no turning, -1 = turn left + private int turnDirection; + + // Amount of pixels/units to move + private double moveAmount; + + // The coordinate of the aim (x,y) + private int aimX, aimY; + + // Fire power, where 0 = don't Fire + private int firePower; + + // Called when the robot must run + public override void Run() + { + // Sets the colors of the robot + // body = black, gun = white, radar = red + SetColors(Color.Black, Color.White, Color.Red); + + // Loop forever + for (;;) + { + // Sets the robot to move forward, backward or stop moving depending + // on the move direction and amount of pixels to move + SetAhead(moveAmount*moveDirection); + + // Decrement the amount of pixels to move until we reach 0 pixels + // This way the robot will automatically stop if the mouse wheel + // has stopped it's rotation + moveAmount = Math.Max(0, moveAmount - 1); + + // Sets the robot to turn right or turn left (at maximum speed) or + // stop turning depending on the turn direction + SetTurnRight(45*turnDirection); // degrees + + // Turns the gun toward the current aim coordinate (x,y) controlled by + // the current mouse coordinate + double angle = Utils.NormalAbsoluteAngle(Math.Atan2(aimX - X, aimY - Y)); + + SetTurnGunRightRadians(Utils.NormalRelativeAngle(angle - GunHeadingRadians)); + + // Fire the gun with the specified Fire power, unless the Fire power = 0 + if (firePower > 0) + { + SetFire(firePower); + } + + // Execute all pending set-statements + Execute(); + + // Next turn is processed in this loop.. + } + } + + // Called when a key has been pressed + public override void OnKeyPressed(KeyEvent e) + { + switch (e.KeyCode) + { + case Keys.VK_UP: + // Arrow up key: move direction = forward (infinitely) + moveDirection = 1; + moveAmount = Double.PositiveInfinity; + break; + + case Keys.VK_DOWN: + // Arrow down key: move direction = backward (infinitely) + moveDirection = -1; + moveAmount = Double.PositiveInfinity; + break; + + case Keys.VK_RIGHT: + // Arrow right key: turn direction = right + turnDirection = 1; + break; + + case Keys.VK_LEFT: + // Arrow left key: turn direction = left + turnDirection = -1; + break; + } + } + + // Called when a key has been released (after being pressed) + public override void OnKeyReleased(KeyEvent e) + { + switch (e.KeyCode) + { + case Keys.VK_UP: + case Keys.VK_DOWN: + // Arrow up and down keys: move direction = stand still + moveDirection = 0; + moveAmount = 0; + break; + + case Keys.VK_RIGHT: + case Keys.VK_LEFT: + // Arrow right and left keys: turn direction = stop turning + turnDirection = 0; + break; + } + } + + // Called when the mouse wheel is rotated + public override void OnMouseWheelMoved(MouseWheelMovedEvent e) + { + // If the wheel rotation is negative it means that it is moved forward. + // Set move direction = forward, if wheel is moved forward. + // Otherwise, set move direction = backward + moveDirection = (e.WheelRotation < 0) ? 1 : -1; + + // Set the amount to move = absolute wheel rotation amount * 5 (speed) + // Here 5 means 5 pixels per wheel rotation step. The higher value, the + // more speed + moveAmount += Math.Abs(e.WheelRotation)*5; + } + + // Called when the mouse has been moved + public override void OnMouseMoved(MouseEvent e) + { + // Set the aim coordinate = the mouse pointer coordinate + aimX = e.X; + aimY = e.Y; + } + + // Called when a mouse button has been pressed + public override void OnMousePressed(MouseEvent e) + { + if (e.Button == Keys.BUTTON3) + { + // Button 3: Fire power = 3 energy points, bullet color = red + firePower = 3; + BulletColor = (Color.Red); + } + else if (e.Button == Keys.BUTTON2) + { + // Button 2: Fire power = 2 energy points, bullet color = orange + firePower = 2; + BulletColor = (Color.Orange); + } + else + { + // Button 1 or unknown button: + // Fire power = 1 energy points, bullet color = yellow + firePower = 1; + BulletColor = (Color.Yellow); + } + } + + // Called when a mouse button has been released (after being pressed) + public override void OnMouseReleased(MouseEvent e) + { + // Fire power = 0, which means "don't Fire" + firePower = 0; + } + + // Called in order to paint graphics for this robot. + // "Paint" button on the robot console window for this robot must be + // enabled in order to see the paintings. + public override void OnPaint(IGraphics g) + { + // Draw a red cross hair with the center at the current aim + // coordinate (x,y) + g.DrawEllipse(Pens.Red, aimX - 15, aimY - 15, 30, 30); + g.DrawLine(Pens.Red, aimX, aimY - 4, aimX, aimY + 4); + g.DrawLine(Pens.Red, aimX - 4, aimY, aimX + 4, aimY); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/MyFirstJuniorRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/MyFirstJuniorRobot.cs new file mode 100644 index 0000000..2cd6050 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/MyFirstJuniorRobot.cs @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace SampleCs +{ + /// + /// MyFirstJuniorRobot - a sample robot by Flemming N. Larsen + ///

+ /// Moves in a seesaw motion, and spins the gun around at each end + /// when it cannot see any enemy robot. When the robot sees and enemy + /// robot, it will immediately turn the gun and Fire at it. + ///

+ public class MyFirstJuniorRobot : JuniorRobot + { + /// + /// MyFirstJuniorRobot's run method - Seesaw as default + /// + public override void Run() + { + // Set robot colors + SetColors(GREEN, BLACK, BLUE); + + // Seesaw forever + while (true) + { + Ahead(100); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(100); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } + + /// + /// When we see a robot, turn the gun towards it and Fire + /// + public override void OnScannedRobot() + { + // Turn gun to point at the scanned robot + TurnGunTo(ScannedAngle); + + // Fire! + Fire(1); + } + + /// + /// We were hit! Turn and move perpendicular to the bullet, + /// so our seesaw might avoid a future shot. + /// + public override void OnHitByBullet() + { + // Move ahead 100 and in the same time turn left papendicular to the bullet + TurnAheadLeft(100, 90 - HitByBulletBearing); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/MyFirstRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/MyFirstRobot.cs new file mode 100644 index 0000000..a79a791 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/MyFirstRobot.cs @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace SampleCs +{ + /// + /// MyFirstRobot - a sample robot by Mathew Nelson + ///

+ /// Moves in a seesaw motion, and spins the gun around at each end + ///

+ public class MyFirstRobot : Robot + { + /// + /// MyFirstRobot's run method - Seesaw + /// + public override void Run() + { + while (true) + { + Ahead(100); // Move ahead 100 + TurnGunRight(360); // Spin gun around + Back(100); // Move back 100 + TurnGunRight(360); // Spin gun around + } + } + + /// + /// Fire when we see a robot + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + Fire(1); + } + + /// + /// We were hit! Turn perpendicular to the bullet, + /// so our seesaw might avoid a future shot. + /// + public override void OnHitByBullet(HitByBulletEvent e) + { + TurnLeft(90 - e.Bearing); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/PaintingRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/PaintingRobot.cs new file mode 100644 index 0000000..c6822ef --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/PaintingRobot.cs @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Drawing; +using Robocode; + +namespace SampleCs +{ + /// + /// PaintingRobot - a sample robot that demonstrates the OnPaint() and + /// GetGraphics() methods. + /// Also demonstrate feature of debugging properties on RobotDialog + ///

+ /// Moves in a seesaw motion, and spins the gun around at each end. + /// When painting is enabled for this robot, a red circle will be painted + /// around this robot. + ///

+ public class PaintingRobot : Robot + { + /// + /// PaintingRobot's Run method - Seesaw + /// + public override void Run() + { + while (true) + { + Ahead(100); + TurnGunRight(360); + Back(100); + TurnGunRight(360); + } + } + + /// + /// Fire when we see a robot + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + // demonstrate feature of debugging properties on RobotDialog + DebugProperty["lastScannedRobot"] = e.Name + " at " + e.Bearing + " degrees at time " + Time; + + Fire(1); + } + + /// + /// We were hit! Turn perpendicular to the bullet, + /// so our seesaw might avoid a future shot. + /// In addition, draw orange circles where we were hit. + /// + public override void OnHitByBullet(HitByBulletEvent e) + { + // demonstrate feature of debugging properties on RobotDialog + DebugProperty["lastHitBy"] = e.Name + " with power of bullet " + e.Power + " at time " + Time; + + // show how to remove debugging property + DebugProperty["lastScannedRobot"] = null; + + // gebugging by painting to battle view + IGraphics g = Graphics; + + g.DrawEllipse(Pens.Orange, (int) (X - 55), (int) (Y - 55), 110, 110); + g.DrawEllipse(Pens.Orange, (int) (X - 56), (int) (Y - 56), 112, 112); + g.DrawEllipse(Pens.Orange, (int) (X - 59), (int) (Y - 59), 118, 118); + g.DrawEllipse(Pens.Orange, (int) (X - 60), (int) (Y - 60), 120, 120); + + TurnLeft(90 - e.Bearing); + } + + /// + /// Paint a red circle around our PaintingRobot + /// + public override void OnPaint(IGraphics graphics) + { + var transparentGreen = new SolidBrush(Color.FromArgb(30, 0, 0xFF, 0)); + graphics.FillEllipse(transparentGreen, (int) (X - 60), (int) (Y - 60), 120, 120); + graphics.DrawEllipse(Pens.Red, (int) (X - 50), (int) (Y - 50), 100, 100); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/PointD.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/PointD.cs new file mode 100644 index 0000000..433242d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/PointD.cs @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SampleCs +{ + [Serializable] + public class PointD + { + public PointD(double x, double y) + { + X = x; + Y = y; + } + + public double X { get; set; } + + public double Y { get; set; } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/RamFire.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/RamFire.cs new file mode 100644 index 0000000..f847cb9 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/RamFire.cs @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Drawing; +using Robocode; + +namespace SampleCs +{ + /// + /// RamFire - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// Drives at robots trying to ram them. + /// Fires when it hits them. + ///

+ public class RamFire : Robot + { + private int turnDirection = 1; // Clockwise or counterclockwise + + /// + /// run: Spin around looking for a target + /// + public override void Run() + { + // Set colors + BodyColor = (Color.LightGray); + GunColor = (Color.Gray); + RadarColor = (Color.DarkGray); + + while (true) + { + TurnRight(5*turnDirection); + } + } + + /// + /// onScannedRobot: We have a target. Go get it. + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + if (e.Bearing >= 0) + { + turnDirection = 1; + } + else + { + turnDirection = -1; + } + + TurnRight(e.Bearing); + Ahead(e.Distance + 5); + Scan(); // Might want to move ahead again! + } + + /// + /// onHitRobot: Turn to face robot, fire hard, and ram him again! + /// + public override void OnHitRobot(HitRobotEvent e) + { + if (e.Bearing >= 0) + { + turnDirection = 1; + } + else + { + turnDirection = -1; + } + TurnRight(e.Bearing); + + // Determine a shot that won't kill the robot... + // We want to ram him instead for bonus points + if (e.Energy > 16) + { + Fire(3); + } + else if (e.Energy > 10) + { + Fire(2); + } + else if (e.Energy > 4) + { + Fire(1); + } + else if (e.Energy > 2) + { + Fire(.5); + } + else if (e.Energy > .4) + { + Fire(.1); + } + Ahead(40); // Ram him again! + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/RobotColors.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/RobotColors.cs new file mode 100644 index 0000000..40c1d1d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/RobotColors.cs @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; + +namespace SampleCs +{ + [Serializable] + public class RobotColors + { + public Color bodyColor; + public Color bulletColor; + public Color gunColor; + public Color radarColor; + public Color scanColor; + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/SittingDuck.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/SittingDuck.cs new file mode 100644 index 0000000..aecf108 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/SittingDuck.cs @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using System.IO; +using Robocode; + +namespace SampleCs +{ + /// + /// SittingDuck - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// Along with sitting still doing nothing, this robot demonstrates persistency. + ///

+ public class SittingDuck : AdvancedRobot + { + private static bool incrementedBattles; + + public override void Run() + { + BodyColor = (Color.Yellow); + GunColor = (Color.Yellow); + + int roundCount = 0; + int battleCount = 0; + + // Read file "count.dat" which contains 2 integers, + try + { + using (Stream count = GetDataFile("count.dat")) + { + if (count.Length != 0) + { + using (TextReader tr = new StreamReader(count)) + { + roundCount = int.Parse(tr.ReadLine()); + battleCount = int.Parse(tr.ReadLine()); + } + } + } + } + catch (Exception) + { + // Something went wrong reading the file, reset to 0. + roundCount = 0; + battleCount = 0; + } + + // Increment the # of rounds + roundCount++; + // If we haven't incremented # of battles already, + // (Note: Because robots are only instantiated once per battle, + // member variables remain valid throughout it. + if (!incrementedBattles) + { + // Increment # of battles + battleCount++; + incrementedBattles = true; + } + + try + { + using (Stream count = GetDataFile("count.dat")) + { + count.SetLength(0); + using (TextWriter tw = new StreamWriter(count)) + { + tw.WriteLine(roundCount); + tw.WriteLine(battleCount); + } + } + } + catch (Exception) + { + Out.WriteLine("I could not write the count!"); + } + + Out.WriteLine("I have been a sitting duck for " + roundCount + " rounds, in " + battleCount + " battles."); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/SpinBot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/SpinBot.cs new file mode 100644 index 0000000..0939278 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/SpinBot.cs @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System.Drawing; +using Robocode; + +namespace SampleCs +{ + /// + /// SpinBot - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// Moves in a circle, firing hard when an enemy is detected + ///

+ public class SpinBot : AdvancedRobot + { + /// + /// SpinBot's run method - Circle + /// + public override void Run() + { + // Set colors + BodyColor = (Color.Blue); + GunColor = (Color.Blue); + RadarColor = (Color.Black); + ScanColor = (Color.Yellow); + + // Loop forever + while (true) + { + // Tell the game that when we take move, + // we'll also want to turn right... a lot. + SetTurnRight(10000); + // Limit our speed to 5 + MaxVelocity = 5; + // Start moving (and turning) + Ahead(10000); + // Repeat. + } + } + + /// + /// onScannedRobot: Fire hard! + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + Fire(3); + } + + /// + /// + /// onHitRobot: If it's our fault, we'll stop turning and moving, + /// so we need to turn again to keep spinning. + /// + public override void OnHitRobot(HitRobotEvent e) + { + if (e.Bearing > -10 && e.Bearing < 10) + { + Fire(3); + } + if (e.IsMyFault) + { + TurnRight(10); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Target.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Target.cs new file mode 100644 index 0000000..2079950 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Target.cs @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + + +using System.Drawing; +using Robocode; + +namespace SampleCs +{ + /// + /// Target - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// Sits still. Moves every time energy drops by 20. + /// This Robot demonstrates custom events. + ///

+ public class Target : AdvancedRobot + { + private int trigger; // Keeps track of when to move + + /// + /// TrackFire's run method + /// + public override void Run() + { + // Set colors + BodyColor = (Color.White); + GunColor = (Color.White); + RadarColor = (Color.White); + + // Initially, we'll move when life hits 80 + trigger = 80; + // Add a custom event named "trigger hit", + AddCustomEvent( + new Condition("triggerhit", + (c) => + { + return Energy <= trigger; + })); + } + + /// + /// onCustomEvent handler + /// + public override void OnCustomEvent(CustomEvent e) + { + // If our custom event "triggerhit" went off, + if (e.Condition.Name == "triggerhit") + { + // Adjust the trigger value, or + // else the event will fire again and again and again... + trigger -= 20; + Out.WriteLine("Ouch, down to " + (int) (Energy + .5) + " energy."); + // move around a bit. + TurnLeft(65); + Ahead(100); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/TrackFire.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/TrackFire.cs new file mode 100644 index 0000000..25ad660 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/TrackFire.cs @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using Robocode; +using Robocode.Util; + +namespace SampleCs +{ + /// + /// TrackFire - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// Sits still. Tracks and fires at the nearest robot it sees + ///

+ public class TrackFire : Robot + { + /// + /// TrackFire's run method + /// + public override void Run() + { + // Set colors + BodyColor = (Color.Pink); + GunColor = (Color.Pink); + RadarColor = (Color.Pink); + ScanColor = (Color.Pink); + BulletColor = (Color.Pink); + + // Loop forever + while (true) + { + TurnGunRight(10); // Scans automatically + } + } + + /// + /// onScannedRobot: We have a target. Go get it. + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + // Calculate exact location of the robot + double absoluteBearing = Heading + e.Bearing; + double bearingFromGun = Utils.NormalRelativeAngleDegrees(absoluteBearing - GunHeading); + + // If it's close enough, fire! + if (Math.Abs(bearingFromGun) <= 3) + { + TurnGunRight(bearingFromGun); + // We check gun heat here, because calling Fire() + // uses a turn, which could cause us to lose track + // of the other robot. + if (GunHeat == 0) + { + Fire(Math.Min(3 - Math.Abs(bearingFromGun), Energy - .1)); + } + } + else + { + // otherwise just set the gun to turn. + // Note: This will have no effect until we call scan() + TurnGunRight(bearingFromGun); + } + // Generates another scan event if we see a robot. + // We only need to call this if the gun (and therefore radar) + // are not turning. Otherwise, scan is called automatically. + if (bearingFromGun == 0) + { + Scan(); + } + } + + public override void OnWin(WinEvent e) + { + // Victory dance + TurnRight(36000); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Tracker.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Tracker.cs new file mode 100644 index 0000000..5396b95 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Tracker.cs @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using Robocode; +using Robocode.Util; + +namespace SampleCs +{ + /// + /// Tracker - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// Locks onto a robot, moves close, fires when close. + ///

+ public class Tracker : Robot + { + private int count; // Keeps track of how long we've + // been searching for our target + private double gunTurnAmt; // How much to turn our gun when searching + private String trackName; // Name of the robot we're currently tracking + + /// + /// run: Tracker's main run function + /// + public override void Run() + { + // Set colors + BodyColor = (Color.FromArgb(128, 128, 50)); + GunColor = (Color.FromArgb(50, 50, 20)); + RadarColor = (Color.FromArgb(200, 200, 70)); + ScanColor = (Color.White); + BulletColor = (Color.Blue); + + // Prepare gun + trackName = null; // Initialize to not tracking anyone + IsAdjustGunForRobotTurn = (true); // Keep the gun still when we turn + gunTurnAmt = 10; // Initialize gunTurn to 10 + + // Loop forever + while (true) + { + // turn the Gun (looks for enemy) + TurnGunRight(gunTurnAmt); + // Keep track of how long we've been looking + count++; + // If we've haven't seen our target for 2 turns, look left + if (count > 2) + { + gunTurnAmt = -10; + } + // If we still haven't seen our target for 5 turns, look right + if (count > 5) + { + gunTurnAmt = 10; + } + // If we *still* haven't seen our target after 10 turns, find another target + if (count > 11) + { + trackName = null; + } + } + } + + /// + /// onScannedRobot: Here's the good stuff + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + // If we have a target, and this isn't it, return immediately + // so we can get more ScannedRobotEvents. + if (trackName != null && e.Name != trackName) + { + return; + } + + // If we don't have a target, well, now we do! + if (trackName == null) + { + trackName = e.Name; + Out.WriteLine("Tracking " + trackName); + } + // This is our target. Reset count (see the run method) + count = 0; + // If our target is too far away, turn and move toward it. + if (e.Distance > 150) + { + gunTurnAmt = Utils.NormalRelativeAngleDegrees(e.Bearing + (Heading - RadarHeading)); + + TurnGunRight(gunTurnAmt); // Try changing these to setTurnGunRight, + TurnRight(e.Bearing); // and see how much Tracker improves... + // (you'll have to make Tracker an AdvancedRobot) + Ahead(e.Distance - 140); + return; + } + + // Our target is close. + gunTurnAmt = Utils.NormalRelativeAngleDegrees(e.Bearing + (Heading - RadarHeading)); + TurnGunRight(gunTurnAmt); + Fire(3); + + // Our target is too close! Back up. + if (e.Distance < 100) + { + if (e.Bearing > -90 && e.Bearing <= 90) + { + Back(40); + } + else + { + Ahead(40); + } + } + Scan(); + } + + /// + /// onHitRobot: Set him as our new target + /// + public override void OnHitRobot(HitRobotEvent e) + { + // Only print if he's not already our target. + if (trackName != null && trackName != e.Name) + { + Out.WriteLine("Tracking " + e.Name + " due to collision"); + } + // Set the target + trackName = e.Name; + // Back up a bit. + // Note: We won't get scan events while we're doing this! + // An AdvancedRobot might use setBack(); Execute(); + gunTurnAmt = Utils.NormalRelativeAngleDegrees(e.Bearing + (Heading - RadarHeading)); + TurnGunRight(gunTurnAmt); + Fire(3); + Back(50); + } + + /// + /// onWin: Do a victory dance + /// + public override void OnWin(WinEvent e) + { + for (int i = 0; i < 50; i++) + { + TurnRight(30); + TurnLeft(30); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/VelociRobot.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/VelociRobot.cs new file mode 100644 index 0000000..e5e70d8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/VelociRobot.cs @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using Robocode; + +namespace SampleCs +{ + /// + /// This is a sample of a robot using the RateControlRobot class by Joshua Galecki + /// + public class VelociRobot : RateControlRobot + { + private int turnCounter; + + public override void Run() + { + turnCounter = 0; + GunRotationRate = (15); + + while (true) + { + if (turnCounter%64 == 0) + { + // Straighten out, if we were hit by a bullet and are turning + TurnRate = 0; + // Go forward with a velocity of 4 + VelocityRate = 4; + } + if (turnCounter%64 == 32) + { + // Go backwards, faster + VelocityRate = -6; + } + turnCounter++; + Execute(); + } + } + + public override void OnScannedRobot(ScannedRobotEvent e) + { + Fire(1); + } + + public override void OnHitByBullet(HitByBulletEvent e) + { + // Turn to confuse the other robot + TurnRate = 5; + } + + public override void OnHitWall(HitWallEvent e) + { + // Move away from the wall + VelocityRate = (-1*VelocityRate); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Walls.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Walls.cs new file mode 100644 index 0000000..988a5da --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCs/Walls.cs @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using Robocode; + +namespace SampleCs +{ + /// + /// Walls - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// Moves around the outer edge with the gun facing in. + ///

+ public class Walls : Robot + { + private bool peek; // Don't turn if there's a robot there + private double moveAmount; // How much to move + + /// + /// run: Move around the walls + /// + public override void Run() + { + // Set colors + BodyColor = (Color.Black); + GunColor = (Color.Black); + RadarColor = (Color.Orange); + BulletColor = (Color.Cyan); + ScanColor = (Color.Cyan); + + // Initialize moveAmount to the maximum possible for this battlefield. + moveAmount = Math.Max(BattleFieldWidth, BattleFieldHeight); + // Initialize peek to false + peek = false; + + // turnLeft to face a wall. + // getHeading() % 90 means the remainder of + // getHeading() divided by 90. + TurnLeft(Heading%90); + Ahead(moveAmount); + // Turn the gun to turn right 90 degrees. + peek = true; + TurnGunRight(90); + TurnRight(90); + + while (true) + { + // Look before we turn when ahead() completes. + peek = true; + // Move up the wall + Ahead(moveAmount); + // Don't look now + peek = false; + // Turn to the next wall + TurnRight(90); + } + } + + /// + /// onHitRobot: Move away a bit. + /// + public override void OnHitRobot(HitRobotEvent e) + { + // If he's in front of us, set back up a bit. + if (e.Bearing > -90 && e.Bearing < 90) + { + Back(100); + } // else he's in back of us, so set ahead a bit. + else + { + Ahead(100); + } + } + + /// + /// onScannedRobot: Fire! + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + Fire(2); + // Note that scan is called automatically when the robot is moving. + // By calling it manually here, we make sure we generate another scan event if there's a robot on the next + // wall, so that we do not start moving up it until it's gone. + if (peek) + { + Scan(); + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsSentry/BorderGuard.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsSentry/BorderGuard.cs new file mode 100644 index 0000000..b2cec54 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsSentry/BorderGuard.cs @@ -0,0 +1,763 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using Robocode; +using Robocode.Util; + +namespace SampleCsSentry +{ + /// + /// BorderGuard - is a sample robot that demonstrates how the BorderSentry interface can be used for + /// creating a robot that guards the border area of the battle field, and which is efficient against + /// robots trying to hide at corners and robots sneaking around near the borders. + ///

+ /// This robot is somewhat advanced due to:
+ /// 1) it uses linear targeting for predicting how to hit robots that moves in straight lines.
+ /// 2) it will only fire at a robot, if it figures out that its bullets will do damage to that + /// particular robot, e.g. when the robots predicted future position will be within the sentry border + /// attack range.
+ /// 3) it has an efficient scanner that keeps the scan angle as little as possible to get as new + /// scanned data for enemy robots as possible.
+ /// 4) it picks a target robot to fire at, which is the nearest robot our robot will be able to + /// damage (by predicting its future position using linear targeting).
+ /// 5) it only moves along the borders of the battle field and constantly changes its direction, so + /// it is not an easy target, and it will try to get as close to its target robot as possible.
+ ///

+ /// Lots of improvements can be made to this robot by copying it - making it even stronger. The + /// intention with of this sample robot is to serve as a more advanced example of how a AdvancedRobot + /// can be made, and how it can be structured as most sample robots are far simpler. + ///

+ /// + /// Credits goes to the hard working Robocoders at the RoboWiki. :-) + ///

+ /// + /// This robot makes use of the Oldest Scanned melee scanner from the RoboWiki:
+ /// http://robowiki.net/wiki/Melee_Radar + ///

+ /// + /// In addition, it makes use of the Exact Non-iterative Solution for Linear Targeting from the + /// RoboWiki:
+ /// http://robowiki.net/wiki/Linear_Targeting + ///

+ /// + /// Author: Flemming N. Larsen + ///

+ /// Version: 1.0 + ///

+ /// Since 1.9.2.4 + ///

+ public class BorderGuard + : AdvancedRobot, IBorderSentry + { + // Constants + const double FIREPOWER = 3; // Max. power => violent as this robot can afford it! + const double HALF_ROBOT_SIZE = 18; // Robot size is 36x36 units, so the half size is 18 units + + // Dictionary containing data for all scanned robots. + // The key to the dictionary is a robot name and the value is an object containing robot data. + IDictionary enemyDictionary; + // List containing robot names where the order of names reflects the when these names was accessed the last time + // within the enemy dictionary. The first in the list is the name of the robot that was accessed the last time, + // and the last in the list is the oldest one. + IList accessedEnemyList; + + // Scanning direction, where the radar turns to the right with positive values, and turns + // to the left with negative values. + double scanDir = 1; + + // Oldest scanned robot. Can be null. + RobotData oldestScanned; + + // Target robot for the gun. Can be null meaning that there is currently no target robot. + RobotData target; + + // Last time when the robot shifted its direction + long lastDirectionShift; + + // Current direction, where 1 means ahead (forward) and -1 means back + int direction = 1; + + /// + /// Constructs this robot. + /// + public BorderGuard() + { + // We initialize a Dictionary containing robot data for each scanned robot, and also a + // List keeping track of the access order for the enemy dictionary. The last accessed robot + // entry is listed first in the List. + // This robot always sweep the radar towards the oldest scanned robot. + enemyDictionary = new Dictionary(); + accessedEnemyList = new List(); + } + + /// + /// Main method that is called by the game when the robot engage in the next round of a battle. + /// + public override void Run() + { + // Do initialization stuff here before the loop + Initialize(); + + // Loop forever. If the robot does not take action, the game will disable our robot! + while (true) + { + // Handle a single turn... + + // Handle the radar that scans enemy robots + HandleRadar(); + // Handle the gun by turning it and fire at our target + HandleGun(); + // Move the robot around on the battlefield + MoveRobot(); + + // Scan for other robots. Note that this method will execute all pending commands for + // the next turn. Hence, scan() ends the turn for our robot. + Scan(); + } + } + + /// + /// This method is called by the game when your robot sees another robot, i.e. when the robot's + /// radar scan "hits" another robot. + /// + /// The scanned robot event containing data about the scanned robot. + public override void OnScannedRobot(ScannedRobotEvent scannedRobotEvent) + { + // Check that the scanned robot is not a sentry robot + if (!scannedRobotEvent.IsSentryRobot) + { + // The scanned robot is not a sentry robot... + + // Update the enemy dictionary + UpdateEnemyDictionary(scannedRobotEvent); + + // Update the scan direction + UpdateScanDirection(scannedRobotEvent); + + // Update enemy target positions + UpdateEnemyTargetPositions(); + } + } + + /// + /// This method is called by the game when another robot dies. + /// + /// The robot death event containing data about the robot that died. + public override void OnRobotDeath(RobotDeathEvent robotDeathEvent) + { + // Gets the name of the robot that died + var deadRobotName = robotDeathEvent.Name; + + // Remove the robot data for the robot that died from the enemy dictionary and access list + enemyDictionary.Remove(deadRobotName); + accessedEnemyList.Remove(deadRobotName); + + // Remove the data entry for the oldest scanned robot, if we have such an entry + if (oldestScanned != null && oldestScanned.name.Equals(deadRobotName)) + { + oldestScanned = null; + } + if (target != null && target.name.Equals(deadRobotName)) + { + target = null; + } + } + + /// + /// This method is called by the every time the robot is painted. + /// + /// + /// In order to see the painting, make sure to enable the Paint button on the robot console for this robot. + /// + /// + /// The graphics context used for painting various shapes like rectangles, circles, lines etc. + /// on top of the battlefield for debugging graphics. + /// + public override void OnPaint(IGraphics g) + { + // Prepare colors for painting the scanned coordinate and target coordinate + var color1 = Color.FromArgb(0x40, 0x00, 0xFF, 0x00); // Green with 25% alpha blending + var color2 = Color.FromArgb(0x40, 0xFF, 0x00, 0x40); // Yellow with 25% alhpa blending + + // Prepare pen with color 1 and a width of 2 pixels + var pen = new Pen(color1, 2); + + // Paint a two circles for each robot in the enemy dictionary. One circle where the robot was + // scanned the last time, and another circle where our robot must point the gun in order to + // hit it (target coordinate). In addition, a line is drawn between these circles. + foreach (RobotData robot in enemyDictionary.Values) + { + // Paint the two circles and a line + FillCircle(g, robot.scannedX, robot.scannedY, color1); // scanned coordinate + FillCircle(g, robot.targetX, robot.targetY, color2); // target coordinate + g.DrawLine(pen, (float)robot.scannedX, (float)robot.scannedY, + (float)robot.targetX, (float)robot.targetY); + } + + // Paint a two circles for the target robot. One circle where the robot was + // scanned the last time, and another circle where our robot must point the gun in order to + // hit it (target coordinate). In addition, a line is drawn between these circles. + if (target != null) + { + // Prepare colors for painting the scanned coordinate and target coordinate + color1 = Color.FromArgb(0x40, 0xFF, 0x7F, 0x00); // Orange with 25% alpha blending + color2 = Color.FromArgb(0x80, 0xFF, 0x00, 0x00); // Red with 50% alpha blending + + // Prepare pen with color 1 and a width of 2 pixels + pen = new Pen(color1, 2); + + // Paint the two circles and a line + FillCircle(g, target.scannedX, target.scannedY, color1); // scanned coordinate + FillCircle(g, target.targetX, target.targetY, color2); // target coordinate + g.DrawLine(pen, (float)target.scannedX, (float)target.scannedY, + (float)target.targetX, (float)target.targetY); + } + } + + /// + /// Initializes this robot before a new round in a battle. + /// + private void Initialize() + { + // Let the robot body, gun, and radar turn independently of each other + IsAdjustRadarForGunTurn = true; + IsAdjustGunForRobotTurn = true; + + // Set robot colors + BodyColor = Color.FromArgb(0x5C, 0x33, 0x17); // Chocolate Brown + GunColor = Color.FromArgb(0x45, 0x8B, 0x74); // Aqua Marine + RadarColor = Color.FromArgb(0xD2, 0x69, 0x1E); // Orange Chocolate + BulletColor = Color.FromArgb(0xFF, 0xD3, 0x9B); // Burly wood + ScanColor = Color.FromArgb(0xCA, 0xFF, 0x70); // Olive Green + } + + /// + /// This method handles the radar that scans for enemy robots. + /// + private void HandleRadar() + { + // Set the radar to turn infinitely to the right if the scan direction is positive; + // otherwise the radar is moved to the left, if the scan direction is negative. + // Notice that onScannedRobot(ScannedRobotEvent) is responsible for determining the scan + // direction. + SetTurnRadarRightRadians(scanDir * Double.PositiveInfinity); + } + + /// + /// Method that handles the gun be turning it and fire at a target. + /// + private void HandleGun() + { + // Update our target robot to fire at + UpdateTarget(); + // Update the gun direction + UpdateGunDirection(); + // Fires the gun, when it is ready + FireGunWhenReady(); + } + + /// + /// Method that moves our robot around the battlefield. + /// + private void MoveRobot() + { + // The movement strategy is to move as close to our target robot as possible. + // Our robot should move along the borders all the time, vertically or horizontally. + // When we get close to our target, or have no where to go, our robot should shift its + // direction from side to side so it does not stand still at any time. + // If the robot stands still, it will be an easy target for enemy robots. + + int newDirection = direction; + + // Get closer to our target if we have a target robot + if (target != null) + { + // Calculate the range from the walls/borders, our robot should keep within + int borderRange = SentryBorderSize - 20; + + // The horizontal and vertical flags are used for determining, if our robot should + // move horizontal or vertical. + bool horizontal = false; + bool vertical = false; + + // Initialize the new heading of the robot to the current heading of the robot + double newHeading = HeadingRadians; + + // Check if our robot is at the upper or lower border and hence should move horizontally + if (X < borderRange || Y > BattleFieldHeight - borderRange) + { + horizontal = true; + } + // Check if our robot is at the left or right border and hence should move vertically + if (X < borderRange || X > BattleFieldWidth - borderRange) + { + vertical = true; + } + + // If we are in one of the corners of the battlefield, we could move both horizontally + // or vertically. + // In this situation, we need to choose one of the two directions. + if (horizontal && vertical) + { + // If the horizontal distance to our target is lesser than the vertical distance, + // then we choose to move vertically, and hence we clear the horizontal flag. + if (Math.Abs(target.targetX - X) <= Math.Abs(target.targetY - Y)) + { + horizontal = false; // Do not move horizontally => move vertically + } + } + // Adjust the heading of our robot with 90 degrees, if it must move horizontally. + // Otherwise the calculated heading is towards moving vertically. + if (horizontal) + { + newHeading -= Math.PI / 2; + } + // Set the robot to turn left the amount of radians we have just calculated + SetTurnLeftRadians(Utils.NormalRelativeAngle(newHeading)); + + // Check if our robot has finished turning, i.e. has less than 1 degrees left to turn + if (Math.Abs(TurnRemaining) < 1 || Math.Abs(Velocity) < 0.01) + { + // If we should move horizontally, the set the robot to move ahead with the + // horizontal distance to the target robot. Otherwise, use the vertical distance. + double delta; // delta is the delta distance to move + if (horizontal) + { + delta = target.targetX - X; + } + else + { + delta = target.targetY - Y; + } + SetAhead(delta); + + // Set the new direction of our robot to 1 (meaning move forward) if the delta + // distance is positive; otherwise it is set to -1 (meaning move backward). + newDirection = delta > 0 ? 1 : -1; + + // Check if more than 10 turns have past since we changed the direction the last + // time + if (Time - lastDirectionShift > 10) + { + // If so, set the new direction to be the reverse direction if the velocity < 1 + if (Math.Abs(Velocity) < 1) + { + newDirection = direction * -1; + } + // Check if the direction really changed + if (newDirection != direction) + { + // If the new direction != current direction, then set the current direction + // to be the new direction and save the current time so we know when we + // changed the direction the last time. + direction = newDirection; + lastDirectionShift = Time; + } + } + } + } + // Set ahead 100 units forward or backward depending on the direction + SetAhead(100 * direction); + } + + /// + /// Method the updates the enemy dictionary based on new scan data for a scanned robot. + /// + /// The scanned robot event containing data about the scanned robot. + private void UpdateEnemyDictionary(ScannedRobotEvent scannedRobotEvent) + { + var name = scannedRobotEvent.Name; + + // Check if data entry exists for the scanned robot + if (enemyDictionary.ContainsKey(name)) + { + // Data entry exists => Update the current entry with new scanned data + RobotData scannedRobot = enemyDictionary[name]; + scannedRobot.Update(scannedRobotEvent, this); + } + else + { + // No data entry exists => Create a new data entry for the scanned robot + RobotData scannedRobot = new RobotData(scannedRobotEvent, this); + // Put the new data entry into the enemy dictionary + enemyDictionary.Add(name, scannedRobot); + } + // Change the access order for the robot name, so the name is moved to, or added as the last entry + if (accessedEnemyList.Contains(name)) + { + accessedEnemyList.Remove(name); + } + accessedEnemyList.Add(name); + } + + /// + /// Method that updates the direction of the radar based on new scan data for a scanned robot. + /// + /// The scanned robot event containing data about the scanned robot. + private void UpdateScanDirection(ScannedRobotEvent scannedRobotEvent) + { + // Gets the name of the scanned robot + var scannedRobotName = scannedRobotEvent.Name; + + // Change the scanning direction if and only if we have no record for the oldest scanned + // robot or the scanned robot IS the oldest scanned robot (based on the name) AND the enemy + // dictionary contains scanned data entries for ALL robots (the size of the enemy dictionary is equal to + // the number of opponent robots found by calling the getOthers() method). + if ((oldestScanned == null || scannedRobotName.Equals(oldestScanned.name)) && accessedEnemyList.Count == Others) + { + // Get the oldest scanned robot data from our LinkedHashMap, where the first value + // contains the oldest accessed entry, which is the robot we need to get. + string oldestScannedName = accessedEnemyList[0]; + RobotData oldestScannedRobot = enemyDictionary[oldestScannedName]; + + // Get the recent scanned position (x,y) of the oldest scanned robot + double x = oldestScannedRobot.scannedX; + double y = oldestScannedRobot.scannedY; + + // Get the heading of our robot + double ourHeading = RadarHeadingRadians; + + // Calculate the bearing to the oldest scanned robot. + // The bearing is the delta angle between the heading of our robot and the other robot, + // which can be a positive or negative angle. + double bearing = BearingTo(ourHeading, x, y); + + // Update the scan direction based on the bearing. + // If the bearing is positive, the radar will be moved to the right. + // If the bearing is negative, the radar will be moved to the left. + scanDir = bearing; + } + } + + /// + /// Updates the target positions for all enemies. The target position is the position our robot + /// must fire at in order to hit the target robot. + /// + /// + /// This robot uses Linear Targeting (Exact Non-iterative Solution) as described on the RoboWiki here: + /// http://robowiki.net/wiki/Linear_Targeting + /// + private void UpdateEnemyTargetPositions() + { + // Go thru all robots in the enemy dictionary + foreach (RobotData enemy in enemyDictionary.Values) + { + // Variables prefixed with e- refer to enemy and b- refer to bullet + double bV = Rules.GetBulletSpeed(FIREPOWER); + double eX = enemy.scannedX; + double eY = enemy.scannedY; + double eV = enemy.scannedVelocity; + double eH = enemy.scannedHeading; + + // These constants make calculating the quadratic coefficients below easier + double A = (eX - X) / bV; + double B = (eY - Y) / bV; + double C = eV / bV * Math.Sin(eH); + double D = eV / bV * Math.Cos(eH); + + // Quadratic coefficients: a*(1/t)^2 + b*(1/t) + c = 0 + double a = A * A + B * B; + double b = 2 * (A * C + B * D); + double c = (C * C + D * D - 1); + + // If the discriminant of the quadratic formula is >= 0, we have a solution meaning that + // at some time, t, the bullet will hit the enemy robot if we fire at it now. + double discrim = b * b - 4 * a * c; + if (discrim >= 0) + { + // Reciprocal of quadratic formula. Calculate the two possible solution for the + // time, t + double t1 = 2 * a / (-b - Math.Sqrt(discrim)); + double t2 = 2 * a / (-b + Math.Sqrt(discrim)); + + // Choose the minimum positive time or select the one closest to 0, if the time is + // negative + double t = Math.Min(t1, t2) >= 0 ? Math.Min(t1, t2) : Math.Max(t1, t2); + + // Calculate the target position (x,y) for the enemy. That is the point that our gun + // should point at in order to hit the enemy at the time, t. + double targetX = eX + eV * t * Math.Sin(eH); + double targetY = eY + eV * t * Math.Cos(eH); + + // Assume enemy stops at walls. Hence, we limit that target position at the walls. + double minX = HALF_ROBOT_SIZE; + double minY = HALF_ROBOT_SIZE; + double maxX = BattleFieldWidth - HALF_ROBOT_SIZE; + double maxY = BattleFieldHeight - HALF_ROBOT_SIZE; + + enemy.targetX = Limit(targetX, minX, maxX); + enemy.targetY = Limit(targetY, minY, maxY); + } + } + } + + /// + /// Updates which enemy robot from the enemy dictionary that should be our current target. + /// + private void UpdateTarget() + { + // Set target to null, meaning that we have no target robot yet + target = null; + + // Create a list over possible target robots that is a copy of robot data from the enemy dictionary + List targets = new List(enemyDictionary.Values); + + // Run thru all the possible target robots and remove those that are outside the attack + // range for this border sentry robot as our robot cannot do harm to robots outside its + // range. + for (int i = targets.Count - 1; i >= 0; i--) // avoids error "Collection was modified" + { + RobotData robot = targets[i]; + if (IsOutsideAttackRange(robot.targetX, robot.targetY)) + { + targets.Remove(robot); + } + } + + // Set the target robot to be the one among all possible target robots that is closest to + // our robot. + double minDist = Double.PositiveInfinity; + foreach (RobotData robot in targets) + { + double dist = DistanceTo(robot.targetX, robot.targetY); + if (dist < minDist) + { + minDist = dist; + target = robot; + } + } + + // If we still haven't got a target robot, then take the first one from our list of target + // robots if the list is not empty. + if (target == null && targets.Count > 0) + { + target = targets[0]; + } + } + + /// + /// Method that updates the gun direction to point at the current target. + /// + private void UpdateGunDirection() + { + // Only update the gun direction, if we have a current target + if (target != null) + { + // Calculate the bearing between the gun and the target, which can be positive or + // negative + double targetBearing = BearingTo(GunHeadingRadians, target.targetX, target.targetY); + // Set the gun to turn right the amount of radians defined by the bearing to the target + SetTurnGunRightRadians(targetBearing); // positive => turn right, negative => turn left + } + } + + /// + /// Method that fires a bullet when the gun is ready to fire. + /// + private void FireGunWhenReady() + { + // We only fire the fun, when we have a target robot + if (target != null) + { + // Only fire when the angle of the gun is pointing at our (virtual) target robot + + // Calculate the distance between between our robot and the target robot + double dist = DistanceTo(target.targetX, target.targetY); + // Angle that "covers" the the target robot from its center to its edge + double angle = Math.Atan(HALF_ROBOT_SIZE / dist); + + // Check if the remaining angle (turn) to move the gun is less than our calculated cover + // angle + if (Math.Abs(GunTurnRemaining) < angle) + { + // If so, our gun should be pointing at our target so we can hit it => fire!! + SetFire(FIREPOWER); + } + } + } + + /// + /// Method that checks if a coordinate (x,y) is outside the Border Sentry's attack range. + /// + /// X coordinate. + /// Y coordinate. + /// true if the coordinate is outside the attack range; false otherwise. + private bool IsOutsideAttackRange(double x, double y) + { + double minBorderX = SentryBorderSize; + double minBorderY = SentryBorderSize; + double maxBorderX = BattleFieldWidth - SentryBorderSize; + double maxBorderY = BattleFieldHeight - SentryBorderSize; + + return (x > minBorderX) && (y > minBorderY) && (x < maxBorderX) && (y < maxBorderY); + } + + /// + /// Method that returns a value that is guaranteed to be within a value range defined by a + /// minimum and maximum value based on an input value.
+ /// If the input value is lesser than the minimum value, the returned value will be set to the + /// minimum value.
+ /// If the input value is greater than the maximum value, the returned value will be set to the + /// maximum value.
+ /// Otherwise the returned value will be equal to the input value. + ///
+ /// Input value to limit. + /// Allowed minimum value. + /// Allowed maximum value. + /// + /// The limited input value that is guaranteed to be within the specified minimum and maximum range. + /// + private double Limit(double value, double min, double max) + { + return Math.Min(max, Math.Max(min, value)); + } + + /// + /// Methods that returns the distance to a coordinate (x,y) from our robot. + /// + /// X coordinate. + /// Y coordinate. + /// + /// The distance to the coordinate (x,y). + /// + private double DistanceTo(double x, double y) + { + double dx = X - x; + double dy = Y - y; + return Math.Sqrt(dx * dx + dy * dy); + } + + /// + /// Method that returns the angle to a coordinate (x,y) from our robot. + /// + /// X coordinate. + /// Y coordinate. + /// + /// The angle to the coordinate (x,y). + /// + private double AngleTo(double x, double y) + { + return Math.Atan2(x - X, y - Y); + } + + /// + /// Method that returns the bearing to a coordinate (x,y) from the position and heading of our + /// robot. The bearing is the delta angle between the heading of our robot and the angle of the + /// specified coordinate. + /// + /// X coordinate. + /// Y coordinate. + /// + /// The angle to the coordinate (x,y). + /// + private double BearingTo(double heading, double x, double y) + { + return Utils.NormalRelativeAngle(AngleTo(x, y) - heading); + } + + /// + /// Method that paints a filled circle at the specified coordinate (x,y) and given color. The + /// circle will have a radius of 20 pixels (meaning that the diameter will be 40 pixels). + /// + /// X coordinate. + /// X coordinate for the center of the circle. + /// Y coordinate for the center of the circle. + /// Color of the filled circle. + private void FillCircle(IGraphics gfx, double x, double y, Color color) + { + // Prepare brush + Brush brush = new SolidBrush(color); + // Paint a filled circle (oval) that has a radius of 20 pixels with a center at the input + // coordinates. + gfx.FillEllipse(brush, (float)x - 20, (float)y - 20, 40f, 40f); + } + + /// + /// This class is used for storing data about a robot that has been scanned.
+ /// The data is mainly a snapshot of specific scanned data like the scanned position (x,y), + /// velocity and heading, put also the calculated predicted target position of the robot when our + /// robot needs to fire at the scanned robot.
+ /// Note that this class calculates the position (x,y) of the scanned robot as our robot moves, + /// and hence data like the angle and distance to the scanned robot will change over time. by + /// using the position, it is easy to calculate a new angle and distance to the robot. + ///
+ internal class RobotData + { + internal string name; // name of the scanned robot + internal double scannedX; // x coordinate of the scanned robot based on the last update + internal double scannedY; // y coordinate of the scanned robot based on the last update + internal double scannedVelocity; // velocity of the scanned robot from the last update + internal double scannedHeading; // heading of the scanned robot from the last update + internal double targetX; // predicated x coordinate to aim our gun at, when firing at the robot + internal double targetY; // predicated y coordinate to aim our gun at, when firing at the robot + + /// + /// Creates a new robot data entry based on new scan data for a scanned robot. + /// + /// + /// A ScannedRobotEvent event containing data about a scanned robot. + /// + /// Robot that creates this data entry. + public RobotData(ScannedRobotEvent scannedRobotEvent, AdvancedRobot robot) + { + // Store the name of the scanned robot + name = scannedRobotEvent.Name; + // Updates all scanned facts like position, velocity, and heading + Update(scannedRobotEvent, robot); + // Initialize the coordinates (x,y) to fire at to the updated scanned position + targetX = scannedX; + targetY = scannedY; + } + + /// + /// Updates the scanned data based on new scan data for a scanned robot. + /// + /// + /// A ScannedRobotEvent event containing data about a scanned robot. + /// + /// Robot that calls this method. + public void Update(ScannedRobotEvent scannedRobotEvent, AdvancedRobot robot) + { + // Get the position of the scanned robot based on the ScannedRobotEvent + PointF pos = GetPosition(scannedRobotEvent, robot); + // Store the scanned position (x,y) + scannedX = pos.X; + scannedY = pos.Y; + // Store the scanned velocity and heading + scannedVelocity = scannedRobotEvent.Velocity; + scannedHeading = scannedRobotEvent.HeadingRadians; + } + + /// + /// Returns the position of the scanned robot based on new scan data for a scanned robot. + /// + /// + /// A ScannedRobotEvent event containing data about a scanned robot. + /// + /// Robot that calls this method. + /// The position (x,y) of the scanned robot. + private PointF GetPosition(ScannedRobotEvent scannedRobotEvent, AdvancedRobot robot) + { + // Gets the distance to the scanned robot + double distance = scannedRobotEvent.Distance; + // Calculate the angle to the scanned robot (our robot heading + bearing to scanned robot) + double angle = robot.HeadingRadians + scannedRobotEvent.BearingRadians; + + // Calculate the coordinates (x,y) of the scanned robot + double x = robot.X + Math.Sin(angle) * distance; + double y = robot.Y + Math.Cos(angle) * distance; + + // Return the position as a point (x,y) + return new PointF((float)x, (float)y); + } + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyCsTeam.team b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyCsTeam.team new file mode 100644 index 0000000..057b59d --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyCsTeam.team @@ -0,0 +1,7 @@ +#Robocode robot team +#Sun Aug 20 23:26:53 EST 2006 +team.members=SampleCsTeam.MyFirstLeader,SampleCsTeam.MyFirstDroid,SampleCsTeam.MyFirstDroid,SampleCsTeam.MyFirstDroid,SampleCsTeam.MyFirstDroid +team.author.name=Pavel Savara +robocode.version=1.7.3 +team.webpage= +team.description=\ A sample team.\n MyFirstLeader scans for enemies,\n and orders the 4 droids to fire. diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyFirstDroid.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyFirstDroid.cs new file mode 100644 index 0000000..d92b945 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyFirstDroid.cs @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using Robocode; +using Robocode.Util; +using SampleCs; + +namespace SampleCsTeam +{ + /// + /// SimpleDroid - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// Follows orders of team leader + ///

+ public class MyFirstDroid : TeamRobot, IDroid + { + /// + /// Droid's default behavior + /// + public override void Run() + { + Out.WriteLine("MyFirstDroid ready."); + } + + /// + /// OnMessageReceived: What to do when our leader sends a message + /// + public override void OnMessageReceived(MessageEvent e) + { + // Fire at a point + if (e.Message is PointD) + { + var p = (PointD)e.Message; + // Calculate x and y to target + double dx = p.X - X; + double dy = p.Y - Y; + // Calculate angle to target + double theta = Utils.ToDegrees(Math.Atan2(dx, dy)); + + // Turn gun to target + TurnGunRight(Utils.NormalRelativeAngleDegrees(theta - GunHeading)); + // Fire hard! + Fire(3); + } + else if (e.Message is RobotColors) + { + // Set our colors + var c = (RobotColors) e.Message; + + BodyColor = c.bodyColor; + GunColor = c.gunColor; + RadarColor = c.radarColor; + ScanColor = c.scanColor; + BulletColor = c.bulletColor; + } + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyFirstLeader.cs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyFirstLeader.cs new file mode 100644 index 0000000..ccbf3f9 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleCsTeam/MyFirstLeader.cs @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +using System; +using System.Drawing; +using Robocode; +using Robocode.Util; +using SampleCs; + +namespace SampleCsTeam +{ + /// + /// MyFirstLeader - a sample team robot by Mathew Nelson, and maintained by Flemming N. Larsen + ///

+ /// Looks around for enemies, and orders teammates to Fire + ///

+ public class MyFirstLeader : TeamRobot + { + /// + /// Run: Leader's default behavior + /// + public override void Run() + { + // Prepare RobotColors object + var c = new RobotColors(); + + c.bodyColor = Color.Red; + c.gunColor = Color.Red; + c.radarColor = Color.Red; + c.scanColor = Color.Yellow; + c.bulletColor = Color.Yellow; + + // Set the color of this robot containing the RobotColors + BodyColor = c.bodyColor; + GunColor = c.gunColor; + RadarColor = c.radarColor; + ScanColor = c.scanColor; + BulletColor = c.bulletColor; + try + { + // Send RobotColors object to our entire team + BroadcastMessage(c); + } + catch (Exception) + { + } + + // Normal behavior + while (true) + { + SetTurnRadarRight(10000); + Ahead(100); + Back(100); + } + } + + + /// + /// OnScannedRobot: What to do when you see another robot + /// + public override void OnScannedRobot(ScannedRobotEvent e) + { + // Don't Fire on teammates + if (IsTeammate(e.Name)) + { + return; + } + // Calculate enemy bearing + double enemyBearing = Heading + e.Bearing; + // Calculate enemy's position + double enemyX = X + e.Distance*Math.Sin(Utils.ToRadians(enemyBearing)); + double enemyY = Y + e.Distance*Math.Cos(Utils.ToRadians(enemyBearing)); + + try + { + // Send enemy position to teammates + BroadcastMessage(new PointD(enemyX, enemyY)); + } + catch (Exception ex) + { + Out.WriteLine("Unable to send order: "); + Out.WriteLine(ex); + } + } + + /// + /// OnHitByBullet: Turn perpendicular to bullet path + /// + public override void OnHitByBullet(HitByBulletEvent e) + { + TurnLeft(90 - e.Bearing); + } + } +} \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleFs/MyFirstRobot.fs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleFs/MyFirstRobot.fs new file mode 100644 index 0000000..1ce76a9 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleFs/MyFirstRobot.fs @@ -0,0 +1,23 @@ +// Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// which accompanies this distribution, and is available at +// http://robocode.sourceforge.net/license/epl-v10.html + +namespace SampleFs + +open Robocode + +type MyFirstRobot() = + inherit Robot() + + override robot.Run() = + while true do + robot.TurnLeft(40.0) + robot.Ahead(20.0) + + override robot.OnScannedRobot(evnt : ScannedRobotEvent) = + robot.Fire(1.0) + + override robot.OnHitByBullet(evnt : HitByBulletEvent) = + robot.TurnLeft(90.0 - evnt.Bearing) diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleFs/robocode.dotnet.samplesfs.fsproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleFs/robocode.dotnet.samplesfs.fsproj new file mode 100644 index 0000000..2259662 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/SampleFs/robocode.dotnet.samplesfs.fsproj @@ -0,0 +1,57 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {f9be3471-d2fd-4d58-9991-7ad8ae7bd015} + Library + func + SampleFs + v3.5 + robocode.dotnet.samplesfs + + + true + full + false + false + bin\Debug\ + DEBUG;TRACE + 3 + bin\Debug\func.XML + + + pdbonly + true + true + bin\Release\ + TRACE + 3 + bin\Release\func.XML + + + + + + + + C:\robocode\libs\robocode.dll + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/robocode.dotnet.samples.csproj b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/robocode.dotnet.samples.csproj new file mode 100644 index 0000000..a2f4302 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.samples/src/robocode.dotnet.samples.csproj @@ -0,0 +1,93 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {80857B97-6397-487B-A9F5-B07026DCBB66} + Library + samplecs + samplescs-1.9.2.4 + v3.5 + 512 + + + 3.5 + + + + true + full + false + ..\target\ + ..\target\obj\ + DEBUG;TRACE + prompt + 4 + false + false + + + pdbonly + true + ..\target\ + ..\target\obj\ + + + prompt + 4 + true + + + + + + + + + + + + + + {7E0900D3-6E8F-48EB-86DB-AA767AA90B84} + robocode.dotnet.api + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.sln b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.sln new file mode 100644 index 0000000..e47c09c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.sln @@ -0,0 +1,50 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C# Express 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "robocode.dotnet.nhost", "robocode.dotnet.nhost\src\robocode.dotnet.nhost.csproj", "{674AED55-B9EC-4C7D-8E0B-1B2481C578B2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "robocode.dotnet.samples", "robocode.dotnet.samples\src\robocode.dotnet.samples.csproj", "{80857B97-6397-487B-A9F5-B07026DCBB66}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "robocode.dotnet.api", "robocode.dotnet.api\src\robocode.dotnet.api.csproj", "{7E0900D3-6E8F-48EB-86DB-AA767AA90B84}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "robocode.dotnet.ntests", "robocode.dotnet.ntests\src\robocode.dotnet.ntests.csproj", "{B3487E2D-2737-4C04-AA71-B9A726B3F781}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "robocode.dotnet.robotscs", "robocode.dotnet.robotscs\src\robocode.dotnet.robotscs.csproj", "{B3487E2D-2737-4C04-AA71-B9A726B3F787}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "robocode.dotnet.control.api", "robocode.dotnet.control.api\src\robocode.dotnet.control.api.csproj", "{674AED55-B9EC-4C7D-8E0B-1B2471C578B2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {674AED55-B9EC-4C7D-8E0B-1B2481C578B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {674AED55-B9EC-4C7D-8E0B-1B2481C578B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {674AED55-B9EC-4C7D-8E0B-1B2481C578B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {674AED55-B9EC-4C7D-8E0B-1B2481C578B2}.Release|Any CPU.Build.0 = Release|Any CPU + {80857B97-6397-487B-A9F5-B07026DCBB66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80857B97-6397-487B-A9F5-B07026DCBB66}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80857B97-6397-487B-A9F5-B07026DCBB66}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80857B97-6397-487B-A9F5-B07026DCBB66}.Release|Any CPU.Build.0 = Release|Any CPU + {7E0900D3-6E8F-48EB-86DB-AA767AA90B84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E0900D3-6E8F-48EB-86DB-AA767AA90B84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E0900D3-6E8F-48EB-86DB-AA767AA90B84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E0900D3-6E8F-48EB-86DB-AA767AA90B84}.Release|Any CPU.Build.0 = Release|Any CPU + {B3487E2D-2737-4C04-AA71-B9A726B3F781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B3487E2D-2737-4C04-AA71-B9A726B3F781}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3487E2D-2737-4C04-AA71-B9A726B3F781}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B3487E2D-2737-4C04-AA71-B9A726B3F781}.Release|Any CPU.Build.0 = Release|Any CPU + {B3487E2D-2737-4C04-AA71-B9A726B3F787}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B3487E2D-2737-4C04-AA71-B9A726B3F787}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B3487E2D-2737-4C04-AA71-B9A726B3F787}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B3487E2D-2737-4C04-AA71-B9A726B3F787}.Release|Any CPU.Build.0 = Release|Any CPU + {674AED55-B9EC-4C7D-8E0B-1B2471C578B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {674AED55-B9EC-4C7D-8E0B-1B2471C578B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {674AED55-B9EC-4C7D-8E0B-1B2471C578B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {674AED55-B9EC-4C7D-8E0B-1B2471C578B2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.classpath b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.classpath new file mode 100644 index 0000000..5dca659 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.classpath @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.project b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.project new file mode 100644 index 0000000..ab0fc6b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.project @@ -0,0 +1,21 @@ + + + robocode.dotnet.tests + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.dotnet.host + robocode.dotnet.nhost + robocode.dotnet.api + robocode.dotnet.control.api + robocode.dotnet.samples + robocode.dotnet.robotscs + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..764c3ab --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:34:11 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/test/java=8859_1 +encoding/src/main/resources=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/config/robocode.properties b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/config/robocode.properties new file mode 100644 index 0000000..cfebed7 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/config/robocode.properties @@ -0,0 +1,34 @@ +#Robocode Properties +#Mon Aug 17 23:43:36 CEST 2009 +robocode.cpu.constant=9994115 +robocode.options.battle.desiredTPS=30 +robocode.options.common.appendWhenSavingResults=true +robocode.options.common.dontHideRankings=true +robocode.options.common.enableReplayRecording=false +robocode.options.common.showResults=true +robocode.options.development.path=..\\robocode.dotnet.samples\\target; +robocode.options.rendering.antialiasing=0 +robocode.options.rendering.bufferImages=true +robocode.options.rendering.forceBulletColor=false +robocode.options.rendering.method=0 +robocode.options.rendering.noBuffers=2 +robocode.options.rendering.text.antialiasing=0 +robocode.options.sound.enableBulletHit=true +robocode.options.sound.enableGunshot=true +robocode.options.sound.enableMixerPan=true +robocode.options.sound.enableMixerVolume=true +robocode.options.sound.enableRobotCollision=true +robocode.options.sound.enableRobotDeath=true +robocode.options.sound.enableSound=false +robocode.options.sound.enableWallCollision=true +robocode.options.sound.mixer=DirectAudioDevice +robocode.options.view.FPS=true +robocode.options.view.TPS=true +robocode.options.view.explosionDebris=true +robocode.options.view.explosions=true +robocode.options.view.ground=true +robocode.options.view.robotEnergy=true +robocode.options.view.robotNames=true +robocode.options.view.scanArcs=false +robocode.version.lastrun=\ 1.7.1.3 +robocode.versionchecked=08/17/2009 23\:11\:46 diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/pom.xml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/pom.xml new file mode 100644 index 0000000..80c3e85 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + robocode.dotnet.tests + Robocode .NET Tests + + robocode.dotnet + net.sf.robocode + ${robocode.dotnet.version} + + + + net.sf.robocode + robocode.core + ${robocode.version} + + + net.sf.robocode + robocode.host + ${robocode.version} + + + net.sf.robocode + robocode.battle + ${robocode.version} + + + net.sf.robocode + robocode.repository + ${robocode.version} + + + net.sf.robocode + robocode.samples + ${robocode.version} + + + net.sf.robocode + robocode.tests + ${robocode.version} + + + net.sf.robocode + robocode.tests.robots + ${robocode.version} + + + net.sf.robocode + robocode.dotnet.host + ${robocode.version} + + + net.sf.robocode + robocode.dotnet.samples + ${project.version} + dotnet:library + + + net.sf.robocode + robocode.dotnet.robotscs + ${project.version} + dotnet:library + + + junit + junit + 4.11 + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/robocode.dotnet.tests.iml b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/robocode.dotnet.tests.iml new file mode 100644 index 0000000..cf654ee --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/robocode.dotnet.tests.iml @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestCustomEvents.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestCustomEvents.java new file mode 100644 index 0000000..828188c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestCustomEvents.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import org.junit.Test; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import net.sf.robocode.test.helpers.Assert; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestCustomEvents extends RobocodeTestBed { + + @Test + public void run() { + super.run(); + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + IRobotSnapshot gh = event.getTurnSnapshot().getRobots()[1]; + + switch (event.getTurnSnapshot().getTurn()) { + case 130: + test(gh, "130 onTick99\r\n130 onTick30"); + break; + + case 1451: + test(gh, "1451 onTick99\r\n1451 onLowEnergy98\r\n1451 onTick30\r\n1451 onScannedRobot10"); + + break; + + default: + break; + } + } + + private void test(IRobotSnapshot gh, String s) { + Assert.assertTrue("got: " + gh.getOutputStreamSnapshot() + ", expected: " + s, + gh.getOutputStreamSnapshot().contains(s)); + } + + @Override + public String getRobotNames() { + return "SampleCs.Target,tested.robotscs.CustomEvents"; + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestDuplicatesAndScore.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestDuplicatesAndScore.java new file mode 100644 index 0000000..2713b51 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestDuplicatesAndScore.java @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import org.junit.Test; +import org.junit.Ignore; +import robocode.BattleResults; +import robocode.control.events.BattleCompletedEvent; +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.RoundStartedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +@Ignore(".NET is little bit slow, so it gives skipped turns for battles with many robots sometimes") +public class TestDuplicatesAndScore extends RobocodeTestBed { + private IRobotSnapshot[] robots; + private BattleResults[] results; + + @Test + public void run() { + super.run(); + } + + @Override + public int getExpectedRobotCount(String list) { + return 8; + } + + @Override + public String getRobotNames() { + return "SampleCs.Fire,tested.robotscs.TestTeam,tested.robotscs.TestTeam,SampleCs.Crazy"; + } + + @Override + public void onRoundStarted(final RoundStartedEvent event) { + super.onRoundStarted(event); + if (event.getRound() == 0) { + robots = event.getStartSnapshot().getRobots(); + Assert.assertEquals(8, robots.length); + + net.sf.robocode.test.helpers.Assert.assertNear(566.2968069, robots[0].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(436.3146436, robots[1].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(317.3362130, robots[2].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(717.6994092, robots[3].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(145.5531935, robots[4].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(734.4305396, robots[5].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(335.7732607, robots[6].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(390.8076498, robots[7].getX()); + + net.sf.robocode.test.helpers.Assert.assertNear(100.000, robots[0].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(200.000, robots[1].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(120.000, robots[2].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(100.000, robots[3].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(200.000, robots[4].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(120.000, robots[5].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(100.000, robots[6].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(100.000, robots[7].getEnergy()); + } + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + int lastTurn = event.getTurnSnapshot().getTurn(); + + robots = event.getTurnSnapshot().getRobots(); + + if (lastTurn == 1) { + net.sf.robocode.test.helpers.Assert.assertNear(566.2968069, robots[0].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(437.1810299, robots[1].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(317.3362130, robots[2].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(717.6994092, robots[3].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(145.2637220, robots[4].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(734.4305396, robots[5].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(335.7732607, robots[6].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(389.8100070, robots[7].getX()); + } + + if (lastTurn == 1365) { + net.sf.robocode.test.helpers.Assert.assertNear(563.1336824, robots[0].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(572.9500601, robots[1].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(317.3362130, robots[2].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(578.2231942, robots[3].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(120.3355009, robots[4].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(734.4305396, robots[5].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(244.9583274, robots[6].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(333.1785378, robots[7].getX()); + } + + Assert.assertFalse("skipped", robots[0].getOutputStreamSnapshot().contains("skipped")); + Assert.assertFalse("skipped", robots[1].getOutputStreamSnapshot().contains("skipped")); + Assert.assertFalse("skipped", robots[2].getOutputStreamSnapshot().contains("skipped")); + Assert.assertFalse("skipped", robots[3].getOutputStreamSnapshot().contains("skipped")); + Assert.assertFalse("skipped", robots[4].getOutputStreamSnapshot().contains("skipped")); + Assert.assertFalse("skipped", robots[5].getOutputStreamSnapshot().contains("skipped")); + Assert.assertFalse("skipped", robots[6].getOutputStreamSnapshot().contains("skipped")); + Assert.assertFalse("skipped", robots[7].getOutputStreamSnapshot().contains("skipped")); + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + if (event.isAborted()) { + results = null; + } + } + + @Override + public void onBattleCompleted(BattleCompletedEvent event) { + results = event.getSortedResults(); + } + + @Override + protected void runTeardown() { + Assert.assertNotNull(results); + Assert.assertNotNull(robots); + Assert.assertThat(robots[0].getName(), is("SampleCs.Fire (1)")); + Assert.assertThat(robots[1].getName(), is("SampleCsTeam.MyFirstLeader (1)")); + Assert.assertThat(robots[2].getName(), is("SampleCsTeam.MyFirstDroid (1)")); + Assert.assertThat(robots[3].getName(), is("SampleCs.Fire (2)")); + Assert.assertThat(robots[4].getName(), is("SampleCsTeam.MyFirstLeader (2)")); + Assert.assertThat(robots[5].getName(), is("SampleCsTeam.MyFirstDroid (2)")); + Assert.assertThat(robots[6].getName(), is("SampleCs.Fire (3)")); + Assert.assertThat(robots[7].getName(), is("SampleCs.Crazy")); + + // the results are different from Java version because of strictfp in Java Math + // as oposed to FPU driven .NET, which gives better precision. + // difference acumulates to make big difference in results + Assert.assertThat(results[0].getTeamLeaderName(), is("tested.robotscs.TestTeam (2)")); + Assert.assertThat(results[1].getTeamLeaderName(), is("tested.robotscs.TestTeam (1)")); + Assert.assertThat(results[2].getTeamLeaderName(), is("SampleCs.Crazy")); + Assert.assertThat(results[3].getTeamLeaderName(), is("SampleCs.Fire (1)")); + + Assert.assertThat(results[0].getLastSurvivorBonus(), is(0)); + Assert.assertThat(results[1].getLastSurvivorBonus(), is(50)); + Assert.assertThat(results[2].getLastSurvivorBonus(), is(0)); + Assert.assertThat(results[3].getLastSurvivorBonus(), is(0)); + + Assert.assertThat(results[0].getRamDamage(), is(0)); + Assert.assertThat(results[1].getRamDamage(), is(5)); + Assert.assertThat(results[2].getRamDamage(), is(14)); + Assert.assertThat(results[3].getRamDamage(), is(1)); + + Assert.assertThat(results[0].getBulletDamageBonus(), is(55)); + Assert.assertThat(results[1].getBulletDamageBonus(), is(0)); + Assert.assertThat(results[2].getBulletDamageBonus(), is(0)); + Assert.assertThat(results[3].getBulletDamageBonus(), is(0)); + + Assert.assertThat(results[0].getBulletDamage(), is(480)); + Assert.assertThat(results[1].getBulletDamage(), is(124)); + Assert.assertThat(results[2].getBulletDamage(), is(148)); + Assert.assertThat(results[3].getBulletDamage(), is(152)); + + Assert.assertThat(results[0].getScore(), is(1135)); + Assert.assertThat(results[1].getScore(), is(434)); + Assert.assertThat(results[2].getScore(), is(312)); + Assert.assertThat(results[3].getScore(), is(253)); + + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestEnvAttack.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestEnvAttack.java new file mode 100644 index 0000000..f479d00 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestEnvAttack.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Pavel Savara (original) + */ +public class TestEnvAttack extends RobocodeTestBed { + boolean messagedAttack; + + @Test + public void run() { + super.run(); + } + + @Override + public String getRobotNames() { + return "tested.robotscs.BattleLost,tested.robotscs.EnvAttack"; + } + + @Override + protected int getExpectedErrors() { + return 1; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("System.Security.Permissions.EnvironmentPermission")) { + messagedAttack = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedAttack); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestEventPriorityFilter.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestEventPriorityFilter.java new file mode 100644 index 0000000..578eb12 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestEventPriorityFilter.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Pavel Savara (original) + */ +public class TestEventPriorityFilter extends RobocodeTestBed { + boolean messagedScanned; + + @Test + public void run() { + super.run(); + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("Scanned!!!")) { + messagedScanned = true; + } + } + + @Override + public String getRobotNames() { + return "tested.robotscs.EventPriorityFilter,tested.robotscs.EventPriorityFilter"; + } + + @Override + protected void runTeardown() { + Assert.assertFalse(messagedScanned); + } +} + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileAttack.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileAttack.java new file mode 100644 index 0000000..5f45c26 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileAttack.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + +import java.io.File; + + +/** + * @author Pavel Savara (original) + */ +public class TestFileAttack extends RobocodeTestBed { + boolean messaged; + + @Test + public void run() { + super.run(); + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("System.Security.SecurityException")) { + messaged = true; + } + } + + @Override + public String getRobotNames() { + return "SampleCs.Fire,tested.robotscs.FileAttack"; + } + + @Override + protected void runSetup() { + File attack = new File("C:\\Robocode.attack"); + + if (attack.exists()) { + Assert.assertTrue(attack.delete()); + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Didn't seen preventing read", messaged); + Assert.assertFalse("Found attack file", new File("C:\\Robocode.attack").exists()); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileWrite.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileWrite.java new file mode 100644 index 0000000..27293d6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileWrite.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; + + +/** + * @author Pavel Savara (original) + */ +public class TestFileWrite extends RobocodeTestBed { + + @Test + public void run() { + super.run(); + } + File file; + + public String getRobotNames() { + return "SampleCs.Walls,SampleCs.SittingDuck"; + } + + @Override + protected void runSetup() { + file = new File("../../../robocode.tests.robots/target/classes/.data/SampleCs/count.dat"); + if (file.exists()) { + if (!file.delete()) { + Logger.logError("Can't delete" + file); + } + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue(file.exists()); + if (!file.delete()) { + Logger.logError("Can't delete" + file); + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileWriteSize.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileWriteSize.java new file mode 100644 index 0000000..a47500f --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFileWriteSize.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + +import java.io.File; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestFileWriteSize extends RobocodeTestBed { + + boolean messagedDataQuota; + boolean messagedDataDirectory; + boolean messageQuotaReached; + boolean robotTerminated; + + @Test + public void run() { + super.run(); + } + + @Override + public String getRobotNames() { + return "tested.robotscs.FileWriteSize,SampleCs.Target"; + } + + File file; + @Override + protected void runSetup() { + file = new File(robotsPath + "\\target\\classes\\.data\\tested\\robotscs\\test.txt"); + if (file.exists()) { + if (!file.delete()) { + Logger.logError("Can't delete" + file); + } + } + } + + @Override + protected int getExpectedErrors() { + return 1; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("Data quota: 200000\r\n")) { + messagedDataQuota = true; + } + + if (out.contains("Data directory: " + robotsPath + "\\target\\classes\\.data\\tested\\robotscs")) { + messagedDataDirectory = true; + } + + if (out.contains("You have reached your filesystem quota: 200000 bytes per robot")) { + messageQuotaReached = true; + } + + if (event.getTurnSnapshot().getRobots()[0].getEnergy() == 0) { + robotTerminated = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Data quota must be 200000", messagedDataQuota); + Assert.assertTrue("Data directory path is wrong", messagedDataDirectory); + Assert.assertTrue("Error must be output that file quota has been exceeded", messageQuotaReached); + Assert.assertTrue("Game must terminate the robot", robotTerminated); + Assert.assertTrue(file.exists()); + if (!file.delete()) { + Logger.logError("Can't delete" + file); + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFormsAttack.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFormsAttack.java new file mode 100644 index 0000000..58cb00c --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestFormsAttack.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Pavel Savara (original) + */ +public class TestFormsAttack extends RobocodeTestBed { + // in case: boolean messagedAttack; + boolean messagedViolation; + + @Test + public void run() { + super.run(); + } + + @Override + public String getRobotNames() { + return "tested.robotscs.BattleLost,tested.robotscs.FormsAttack"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("System.Security.Permissions.UIPermission")) { + messagedViolation = true; + } + } + + @Override + protected int getExpectedErrors() { + return 2; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedViolation); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestHttpAttack.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestHttpAttack.java new file mode 100644 index 0000000..5b4e7f8 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestHttpAttack.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestHttpAttack extends RobocodeTestBed { + + private boolean messagedAccessDenied; + + @Override + public String getRobotNames() { + return "tested.robotscs.HttpAttack,SampleCs.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("System.Net.WebPermission")) { + messagedAccessDenied = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("HTTP connection is not allowed", messagedAccessDenied); + } + + @Override + protected int getExpectedErrors() { + return 1; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestInteruptibleEvent.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestInteruptibleEvent.java new file mode 100644 index 0000000..6527e63 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestInteruptibleEvent.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + + +/** + * Test if onScannedRobot() is called when the radar is turned from within a onHitWall() event. + * + * @author Flemming N. Larsen (original) + */ +public class TestInteruptibleEvent extends RobocodeTestBed { + boolean messagedScanned; + + @Test + public void run() { + super.run(); + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("Scanned!!!")) { + messagedScanned = true; + } + } + + @Override + public String getRobotNames() { + return "tested.robotscs.InteruptibleEvent,tested.robotscs.InteruptibleEvent"; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedScanned); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestJunior.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestJunior.java new file mode 100644 index 0000000..ff12857 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestJunior.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import org.junit.Assert; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestJunior extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "tested.robotscs.JuniorEvents,SampleCs.SittingDuck"; + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[0]; + + if (event.getTurnSnapshot().getTurn() == 590) { + String out = robot.getOutputStreamSnapshot(); + + test(out, "Robocode.BulletMissedEvent 5"); + test(out, "Robocode.ScannedRobotEvent 100"); + test(out, "Robocode.BulletHitEvent 24"); + test(out, "Robocode.StatusEvent 590"); + test(out, "Robocode.WinEvent 1"); + test(out, "last bullet heading 6.06794"); + } + } + + private void test(String out, String in) { + Assert.assertTrue(in, out.contains(in)); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestLost.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestLost.java new file mode 100644 index 0000000..557425a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestLost.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestLost extends RobocodeTestBed { + private int lost = 0; + private int end = 0; + + @Test + public void run() { + super.run(); + } + + @Override + public int getNumRounds() { + return 5; + } + + @Override + public String getRobotNames() { + return "SampleCs.Fire,tested.robotscs.BattleLost"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[1]; + final String streamSnapshot = robot.getOutputStreamSnapshot(); + + if (streamSnapshot.contains("Death!")) { + lost++; + } + if (streamSnapshot.contains("BattleEnded!")) { + end++; + } + } + + @Override + protected void runTeardown() { + Assert.assertThat("always should loose", lost, is(getNumRounds())); + Assert.assertThat("should get BattleEnded event", end, is(1)); + } + +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxVelocity.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxVelocity.java new file mode 100644 index 0000000..c888f57 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestMaxVelocity.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; +import robocode.util.Utils; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestMaxVelocity extends RobocodeTestBed { + + @Override + public String getRobotNames() { + return "tested.robotscs.MaxVelocity,SampleCs.Target"; + } + + @Override + public String getInitialPositions() { + return "(50,50,0), (600,50,0)"; // Make sure the robots do not collide! + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final int time = (int) event.getTurnSnapshot().getTurn(); + final double velocity = event.getTurnSnapshot().getRobots()[0].getVelocity(); + + switch (time) { + case 10: + case 20: + case 100: + Assert.assertTrue(Utils.isNear(velocity, 8)); + break; + + case 32: + case 40: + case 120: + Assert.assertTrue(Utils.isNear(velocity, -8)); + break; + + case 50: + case 60: + Assert.assertTrue(Utils.isNear(velocity, 4.2)); + break; + + case 70: + case 80: + Assert.assertTrue(Utils.isNear(velocity, -4.2)); + break; + + case 130: + case 140: + Assert.assertTrue(Utils.isNear(velocity, 2)); + break; + + case 150: + case 160: + Assert.assertTrue(Utils.isNear(velocity, -2)); + break; + + case 170: + case 180: + case 190: + case 199: + Assert.assertTrue(Utils.isNear(velocity, 0)); + break; + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestNames.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestNames.java new file mode 100644 index 0000000..90978c6 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestNames.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; + + +/** + * @author Pavel Savara (original) + */ +public class TestNames extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + @Override + protected int getExpectedErrors() { + return 4; + } + + @Override + public int getExpectedRobotCount(String list) { + return 2; + } + + @Override + public String getRobotNames() { + return "SampleCs.Fire,robocode.BadNamespace,tested.robotscs.TooLongNameThisIsReallyTooLongName,tooLongNamespaceThisIsReallyTooLongNamespace.TooLongNamespace,NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLonger,NoPackageShortName"; + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestPosition.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestPosition.java new file mode 100644 index 0000000..8cd2571 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestPosition.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.RoundStartedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * Repeatable robot possition test + * + * @author Pavel Savara (original) + */ +public class TestPosition extends RobocodeTestBed { + int lastTurn; + + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "SampleCs.Crazy,SampleCs.Target"; + } + + @Override + public void onRoundStarted(final RoundStartedEvent event) { + super.onRoundStarted(event); + if (event.getRound() == 0) { + IRobotSnapshot crazy = event.getStartSnapshot().getRobots()[0]; + IRobotSnapshot target = event.getStartSnapshot().getRobots()[1]; + + Assert.assertNear(568.1445492, crazy.getX()); + Assert.assertNear(163.0032275, crazy.getY()); + Assert.assertNear(436.7181397, target.getX()); + Assert.assertNear(351.5039067, target.getY()); + } + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + lastTurn = event.getTurnSnapshot().getTurn(); + + IRobotSnapshot crazy = event.getTurnSnapshot().getRobots()[0]; + IRobotSnapshot target = event.getTurnSnapshot().getRobots()[1]; + + if (lastTurn == 1) { + Assert.assertNear(567.2831835, crazy.getX()); + Assert.assertNear(162.4952421, crazy.getY()); + Assert.assertNear(436.7181397, target.getX()); + Assert.assertNear(351.5039067, target.getY()); + } + + if (lastTurn == 1700) { + Assert.assertNear(373.9958377, crazy.getX()); + Assert.assertNear(196.1380677, crazy.getY()); + Assert.assertNear(340.3212984, target.getX()); + Assert.assertNear(456.5502002, target.getY()); + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue(lastTurn == 2080 || lastTurn == 2296); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestPrivateConstructor.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestPrivateConstructor.java new file mode 100644 index 0000000..2f37039 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestPrivateConstructor.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestPrivateConstructor extends RobocodeTestBed { + boolean messaged; + + @Test + public void run() { + super.run(); + } + + public void onTurnEnded(final TurnEndedEvent event) { + super.onTurnEnded(event); + final IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[1]; + + if (robot.getOutputStreamSnapshot().contains( + "tested.robotscs.PrivateConstructor No parameterless constructor defined for this object.")) { + messaged = true; + } + Assert.assertNear(0, robot.getEnergy()); + } + + @Override + public String getRobotNames() { + return "SampleCs.Fire,tested.robotscs.PrivateConstructor"; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messaged); + } + + @Override + protected int getExpectedErrors() { + return 1; // Security error must be reported as an error + } +} + diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestRandom.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestRandom.java new file mode 100644 index 0000000..eb22120 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestRandom.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * Repeatable random test + * + * @author Pavel Savara (original) + */ +public class TestRandom extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "SampleCs.Fire,tested.robotscs.Random"; + } + + @Override + public boolean isCheckOnBattleStart() { + return true; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + Assert.assertTrue(event.getTurnSnapshot().getTurn() <= 1407); + IRobotSnapshot fire = event.getTurnSnapshot().getRobots()[0]; + IRobotSnapshot random = event.getTurnSnapshot().getRobots()[1]; + + if (event.getTurnSnapshot().getTurn() == 1241) { + Assert.assertNear(213.18621928, fire.getX()); + Assert.assertNear(371.45706118, fire.getY()); + Assert.assertNear(782.0, random.getX()); + Assert.assertNear(230.95479253, random.getY()); + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestReflectionAttack.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestReflectionAttack.java new file mode 100644 index 0000000..06f50e7 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestReflectionAttack.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestReflectionAttack extends RobocodeTestBed { + + private boolean securityException; + private boolean fieldAccessException; + + @Override + public String getRobotNames() { + return "tested.robotscs.ReflectionAttack,SampleCs.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("System.Security.SecurityException")) { + securityException = true; + } else if (out.contains("System.FieldAccessException")) { + fieldAccessException = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Reflection is not allowed", securityException || fieldAccessException); + } + + @Override + protected int getExpectedErrors() { + return securityException ? 1 : 0; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestRobotDeathEvents.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestRobotDeathEvents.java new file mode 100644 index 0000000..d8bb60e --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestRobotDeathEvents.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestRobotDeathEvents extends RobocodeTestBed { + + @Override + public String getRobotNames() { + return "tested.robotscs.RobotDeathEvents,SampleCs.Crazy,SampleCs.Target,SampleCs.Target,SampleCs.Target"; + } + + @Override + public int getNumRounds() { + return 5; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("enemyCount != getOthers()")) { + Assert.fail("Robot is missing RobotDeathEvent"); + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestScoring.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestScoring.java new file mode 100644 index 0000000..f269e0a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestScoring.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.RoundEndedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IScoreSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + + +/** + * This test is used for testing if the current scores and total scores are + * calculated correctly. Current scores are tested at each turn, and the total + * scores are tested per round and per battle. + * + * @author Flemming N. Larsen (original) + */ +public class TestScoring extends RobocodeTestBed { + + ITurnSnapshot lastTurnSnapshot; + + @Override + public String getRobotNames() { + return "SampleCs.Corners,SampleCs.Crazy,SampleCs.Fire,SampleCs.RamFire,SampleCs.SittingDuck,SampleCs.SpinBot,SampleCs.Tracker,SampleCs.TrackFire,SampleCs.Walls"; + } + + @Override + public int getNumRounds() { + return 10; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + lastTurnSnapshot = event.getTurnSnapshot(); + + for (IScoreSnapshot score : lastTurnSnapshot.getSortedTeamScores()) { + // Notice that the is no such thing as a 'current total last + // survivor bonus' + int currentScore = (int) (0.5 + score.getCurrentSurvivalScore() + score.getCurrentBulletDamageScore() + + score.getCurrentBulletKillBonus() + score.getCurrentRammingDamageScore() + + score.getCurrentRammingKillBonus() + score.getCurrentSurvivalBonus()); + + Assert.assertThat(score.getName(), currentScore, is((int) (0.5 + score.getCurrentScore()))); + } + } + + @Override + public void onRoundEnded(RoundEndedEvent event) { + super.onRoundEnded(event); + + for (IScoreSnapshot score : lastTurnSnapshot.getSortedTeamScores()) { + + int totalScore = (int) (0.5 + score.getTotalSurvivalScore() + score.getTotalLastSurvivorBonus() + + score.getTotalBulletDamageScore() + score.getTotalBulletKillBonus() + score.getTotalRammingDamageScore() + + score.getTotalRammingKillBonus()); + + Assert.assertThat(score.getName(), totalScore, is((int) (0.5 + score.getTotalScore()))); + } + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + for (IScoreSnapshot score : lastTurnSnapshot.getSortedTeamScores()) { + + int totalScore = (int) (0.5 + score.getTotalSurvivalScore() + score.getTotalLastSurvivorBonus() + + score.getTotalBulletDamageScore() + score.getTotalBulletKillBonus() + score.getTotalRammingDamageScore() + + score.getTotalRammingKillBonus()); + + Assert.assertThat(totalScore, is((int) (0.5 + score.getTotalScore()))); + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestSkippedTurns.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestSkippedTurns.java new file mode 100644 index 0000000..c119173 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestSkippedTurns.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import org.junit.Ignore; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Pavel Savara (original) + */ +@Ignore("is very timing sensitive test, so it usually fails on different machines, please run explicitly if you did something to security or timing") +public class TestSkippedTurns extends RobocodeTestBed { + boolean messagedBattle; + boolean messagedEvent; + + @Test + public void run() { + super.run(); + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("Skipped!!!")) { + messagedEvent = true; + } + if (out.contains("not performed any actions in a reasonable")) { + messagedBattle = true; + } + } + + @Override + public String getRobotNames() { + return "SampleCs.TrackFire,tested.robotscs.SkipTurns"; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedEvent); + Assert.assertTrue(messagedBattle); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestThreadAttack.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestThreadAttack.java new file mode 100644 index 0000000..80a4368 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestThreadAttack.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Pavel Savara (original) + */ +public class TestThreadAttack extends RobocodeTestBed { + boolean messagedMax; + + @Override + public String getRobotNames() { + return "tested.robotscs.ThreadAttack,SampleCs.SittingDuck"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("You may only create 5 threads")) { + messagedMax = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedMax); + } + + @Override + protected int getExpectedErrors() { + return 1; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestUndeadThread.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestUndeadThread.java new file mode 100644 index 0000000..4338c2a --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestUndeadThread.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.BattleErrorEvent; + + +/** + * @author Pavel Savara (original) + */ +public class TestUndeadThread extends RobocodeTestBed { + boolean messagedStop; + + @Test + public void run() { + super.run(); + } + + public void onBattleError(BattleErrorEvent event) { + super.onBattleError(event); + final String error = event.getError(); + + if (error.contains("Unable to stop thread")) { + messagedStop = true; + } + } + + @Override + protected int getExpectedErrors() { + return 1; + } + + @Override + public String getRobotNames() { + return "SampleCs.SittingDuck,tested.robotscs.UndeadThread"; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedStop); + } + +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestWatchBullet.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestWatchBullet.java new file mode 100644 index 0000000..f404095 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestWatchBullet.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import org.junit.Assert; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestWatchBullet extends RobocodeTestBed { + boolean messagedIdentity; + + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "tested.robotscs.WatchBullets,SampleCs.SittingDuck"; + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[0]; + + final String out = robot.getOutputStreamSnapshot(); + final int time = event.getTurnSnapshot().getTurn(); + + test(out, time, 33, "33 487.43878 119.51132 347.66745 True"); + test(out, time, 45, "45 459.24551 248.46534 347.66745 True"); + test(out, time, 52, "52 442.79943 323.68851 347.66745 True"); + test(out, time, 53, "53 440.44999 334.43468 347.66745 False"); + + if (out.contains("Failed bullet identity")) { + messagedIdentity = true; + } + } + + @Override + protected void runTeardown() { + net.sf.robocode.test.helpers.Assert.assertFalse(messagedIdentity); + } + + private void test(String out, int timecurr, int timeWatch, String in) { + if (timecurr == timeWatch) { + Assert.assertTrue("got: " + out + ", expected: " + in, out.contains(in)); + } + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestWin.java b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestWin.java new file mode 100644 index 0000000..c736838 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/java/net/sf/robocode/test/robotscs/TestWin.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robotscs; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import org.junit.Test; +import robocode.BattleResults; +import robocode.control.events.BattleCompletedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestWin extends RobocodeTestBed { + private int win = 0; + private int end = 0; + private int rend = 0; + private BattleResults[] results; + + @Test + public void run() { + super.run(); + } + + @Override + public int getNumRounds() { + return 5; + } + + @Override + public String getRobotNames() { + return "SampleCs.Target,tested.robotscs.BattleWin"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[1]; + final String streamSnapshot = robot.getOutputStreamSnapshot(); + + if (streamSnapshot.contains("Win!")) { + win++; + } + if (streamSnapshot.contains("BattleEnded!")) { + end++; + } + if (streamSnapshot.contains("RoundEnded!")) { + rend++; + } + } + + public void onBattleCompleted(BattleCompletedEvent event) { + results = event.getSortedResults(); + } + + @Override + protected void runTeardown() { + Assert.assertThat("always should win", win, is(getNumRounds())); + Assert.assertThat("should get BattleEnded event", end, is(1)); + Assert.assertThat("should get RoundEnded event", rend, is(5)); + Assert.assertThat("always should be FIRST", results[0].getTeamLeaderName(), is("tested.robotscs.BattleWin")); + Assert.assertThat("always should get score", results[0].getScore(), is(900)); + } +} diff --git a/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/resources/config/robocode.properties b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/resources/config/robocode.properties new file mode 100644 index 0000000..35ec106 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/robocode.dotnet.tests/src/test/resources/config/robocode.properties @@ -0,0 +1,4 @@ +#Robocode Properties +#Fri Jan 02 00:50:04 CET 2009 +robocode.options.development.path=../../../robocode.samples/target/classes;../robocode.dotnet.samples/target;../robocode.dotnet.robotscs/target +robocode.versionchecked=01/04/2109 23\:46\:20 diff --git a/代码/workspace_robo4/plugins/dotnet/tools/.gitignore b/代码/workspace_robo4/plugins/dotnet/tools/.gitignore new file mode 100644 index 0000000..a65b417 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/tools/.gitignore @@ -0,0 +1 @@ +lib diff --git a/代码/workspace_robo4/plugins/dotnet/tools/keys/.gitignore b/代码/workspace_robo4/plugins/dotnet/tools/keys/.gitignore new file mode 100644 index 0000000..4bcc837 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/tools/keys/.gitignore @@ -0,0 +1 @@ +robocode.snk diff --git a/代码/workspace_robo4/plugins/dotnet/tools/keys/gennetkey.cmd b/代码/workspace_robo4/plugins/dotnet/tools/keys/gennetkey.cmd new file mode 100644 index 0000000..49c0d6b --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/tools/keys/gennetkey.cmd @@ -0,0 +1,9 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\sn.exe" -k robocode.snk \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/dotnet/tools/loadTools.cmd b/代码/workspace_robo4/plugins/dotnet/tools/loadTools.cmd new file mode 100644 index 0000000..c6e3cce --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/tools/loadTools.cmd @@ -0,0 +1,23 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off + +if not exist "%~dp0/lib/" ( + mkdir "%~dp0/lib/" +) + +java -cp "%~dp0/../../../tools/loader" Loader http://robocode.sourceforge.net/mvnrepo/net/sf/jni4net/jni4net.n/0.8.7.0/ "%~dp0/lib/" jni4net.n-0.8.7.0.dll +java -cp "%~dp0/../../../tools/loader" Loader http://robocode.sourceforge.net/mvnrepo/net/sf/jni4net/jni4net.n.w32.v20/0.8.7.0/ "%~dp0/lib/" jni4net.n.w32.v20-0.8.7.0.dll +java -cp "%~dp0/../../../tools/loader" Loader http://robocode.sourceforge.net/mvnrepo/net/sf/jni4net/jni4net.n.w64.v20/0.8.7.0/ "%~dp0/lib/" jni4net.n.w64.v20-0.8.7.0.dll +java -cp "%~dp0/../../../tools/loader" Loader http://robocode.sourceforge.net/mvnrepo/net/sf/jni4net/jni4net.n.w32.v40/0.8.7.0/ "%~dp0/lib/" jni4net.n.w32.v40-0.8.7.0.dll +java -cp "%~dp0/../../../tools/loader" Loader http://robocode.sourceforge.net/mvnrepo/net/sf/jni4net/jni4net.n.w64.v40/0.8.7.0/ "%~dp0/lib/" jni4net.n.w64.v40-0.8.7.0.dll +java -cp "%~dp0/../../../tools/loader" Loader http://robocode.sourceforge.net/mvnrepo/net/sf/jni4net/jni4net.j/0.8.7.0/ "%~dp0/lib/" jni4net.j-0.8.7.0.jar +java -cp "%~dp0/../../../tools/loader" Loader http://robocode.sourceforge.net/mvnrepo/net/sf/jni4net/proxygen/0.8.7.0/ "%~dp0/lib/" proxygen.exe +java -cp "%~dp0/../../../tools/loader" Loader http://jni4net.googlecode.com/svn/mvnrepo/org/nunit/nunit.framework/2.4.3.0/ "%~dp0/lib/" nunit.framework-2.4.3.0.dll + diff --git a/代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.control.proxygen.xml b/代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.control.proxygen.xml new file mode 100644 index 0000000..f288fcd --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.control.proxygen.xml @@ -0,0 +1,56 @@ + + + + robocode.dotnet.host/src/main/java + robocode.dotnet.control.api/src/generated + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.proxygen.net.xml b/代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.proxygen.net.xml new file mode 100644 index 0000000..dbdda05 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.proxygen.net.xml @@ -0,0 +1,28 @@ + + + + + robocode.dotnet.host/src/main/java + robocode.dotnet.nhost/src/generated + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.proxygen.xml b/代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.proxygen.xml new file mode 100644 index 0000000..db99900 --- /dev/null +++ b/代码/workspace_robo4/plugins/dotnet/tools/proxygen/robocode.proxygen.xml @@ -0,0 +1,45 @@ + + + + + robocode.dotnet.host/src/main/java + robocode.dotnet.nhost/src/generated + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/.gitignore b/代码/workspace_robo4/plugins/testing/.gitignore new file mode 100644 index 0000000..ef1aab0 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/.gitignore @@ -0,0 +1 @@ +tools diff --git a/代码/workspace_robo4/plugins/testing/mvn.cmd b/代码/workspace_robo4/plugins/testing/mvn.cmd new file mode 100644 index 0000000..0e56a2d --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/mvn.cmd @@ -0,0 +1,19 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off + +if not exist "%~dp0\tools\lib" ( + mkdir "%~dp0\tools\lib" +) + +if not exist "%~dp0\..\..\tools\lib\maven-*-uber.jar" ( + call "%~dp0\..\..\tools\loadTools.cmd" +) + +call "%~dp0\..\..\mvn" %* \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/mvn.sh b/代码/workspace_robo4/plugins/testing/mvn.sh new file mode 100644 index 0000000..7a6b177 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/mvn.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +dp0=${0%/*} + +if [ ! -d "$dp0/tools/lib" ]; then + mkdir $dp0/tools/lib +fi + +if [ ! -f $dp0/../../tools/lib/maven-*-uber.jar ]; then + $dp0/../../tools/loadTools.sh +fi + +$dp0/../../mvn.sh $* \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/mvnassembly.cmd b/代码/workspace_robo4/plugins/testing/mvnassembly.cmd new file mode 100644 index 0000000..fb10c4c --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/mvnassembly.cmd @@ -0,0 +1,12 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off + +mvn clean install ant:ant -DskipTests=false %* +rem mvn eclipse:eclipse \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/mvnassembly.sh b/代码/workspace_robo4/plugins/testing/mvnassembly.sh new file mode 100644 index 0000000..a498a71 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/mvnassembly.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +./mvn.sh clean install ant:ant -DskipTests=false $* +#./mvn.sh eclipse:eclipse \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/pom.xml b/代码/workspace_robo4/plugins/testing/pom.xml new file mode 100644 index 0000000..6e5adcc --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + robocode.testing + Robot Testing Framework + pom + + net.sf.robocode + robocode + ${robocode.version} + ../.. + + + robocode.testing.api + robocode.testing.content + robocode.testing.distribution + robocode.testing.installer + robocode.testing.samples + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.api/.classpath b/代码/workspace_robo4/plugins/testing/robocode.testing.api/.classpath new file mode 100644 index 0000000..776135b --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.api/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.api/.project b/代码/workspace_robo4/plugins/testing/robocode.testing.api/.project new file mode 100644 index 0000000..6cac192 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.api/.project @@ -0,0 +1,14 @@ + + + robocode.testing.api + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.api/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/testing/robocode.testing.api/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..ee629d3 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.api/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:14:19 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.api/pom.xml b/代码/workspace_robo4/plugins/testing/robocode.testing.api/pom.xml new file mode 100644 index 0000000..89cf1b6 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.api/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + robocode.testing.api + Robot Testing Framework API + + net.sf.robocode + robocode.testing + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + junit + junit + 4.11 + + + + + + org.apache.maven.plugins + maven-jar-plugin + + robocode.testing + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + package + + javadoc + + + + + Robocode Testing Framework ${project.version} + true + + Robocode Testing Framework ${project.version}]]> + + + http://docs.oracle.com/javase/6/docs/api/ + http://junit.sourceforge.net/javadoc + http://robocode.sourceforge.net/docs/robocode + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.api/robocode.testing.api.iml b/代码/workspace_robo4/plugins/testing/robocode.testing.api/robocode.testing.api.iml new file mode 100644 index 0000000..774c095 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.api/robocode.testing.api.iml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/RobotTestBed.java b/代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/RobotTestBed.java new file mode 100644 index 0000000..b88e90a --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/RobotTestBed.java @@ -0,0 +1,329 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.testing; + + +import robocode.control.BattleSpecification; +import robocode.control.BattlefieldSpecification; +import robocode.control.IRobocodeEngine; +import robocode.control.RandomFactory; +import robocode.control.RobocodeEngine; +import robocode.control.RobotSpecification; +import robocode.control.events.BattleAdaptor; +import robocode.control.events.BattleErrorEvent; +import robocode.control.events.BattleMessageEvent; +import robocode.control.events.TurnEndedEvent; +import net.sf.robocode.io.Logger; +import static org.hamcrest.CoreMatchers.is; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import robocode.control.snapshot.IRobotSnapshot; + +import java.io.File; + + +/** + * RobotTestBed provides a superclass that can be extended in order to implement JUnit tests + * for Robocode robots. + *

+ * The user must set the system property robocode.home to the location of the robocode installation, + * otherwise we cannot set up the Robocode engine. If robocode.home is not a system property, + * we throw a RuntimeException. + * + * @author Philip Johnson (original) + * @author Pavel Savara (contributor) + */ +public abstract class RobotTestBed extends BattleAdaptor { + + /** + * The Robocode game engine instance used for this test. + */ + protected final IRobocodeEngine engine; + + /** + * The battlefield specification, which is the default. + */ + protected final BattlefieldSpecification battleFieldSpec = new BattlefieldSpecification(); + + /** + * The number of errors generated during this battle so far. + */ + protected int errors = 0; + + /** + * The number of messages generated during this battle so far. + */ + protected int messages = 0; + + /** + * The height of the battle field, initialized at the beginning of the battle. + */ + protected int height = 0; + + /** + * The width of the battle field, initialized at the beginning of the battle. + */ + protected int width = 0; + + /** + * True to specify that the position during each turn should be printed out. + */ + protected boolean isDumpingPositions = false; + + /** + * True to specify that each turn should be printed out. + */ + protected boolean isDumpingTurns = false; + + /** + * True to specify that Robot output should be printed out. + */ + protected boolean isDumpingOutput = false; + + /** + * True to specify that error messages should be printed out. + */ + protected boolean isDumpingErrors = true; + + /** + * True to specify that Robot messages should be printed out. + */ + protected boolean isDumpingMessages = true; + + /** + * Create an instance of RobotTestBed which provides default implementations for some (not all) + * of the IBattleListener methods. Your subclass can provide overridden methods for more + * of the IBattleListener methods, or override any of the methods in this class, in order to + * check for the desired behavior by your robot. + *

+ * Also instantiates a Robocode engine for running the test battle. This requires a system + * property called robocode.home to be defined and to provide the path to a Robocode installation + * containing the robots under test. + * + * @throws RuntimeException If robocode.home is not defined or does not point to a robocode + * installation. + */ + public RobotTestBed() { + // Set some system properties for use by the robocode engine. + System.setProperty("EXPERIMENTAL", "true"); + System.setProperty("TESTING", "true"); + + // Check that robocode.home is defined and points to a robocode installation. + String robocodeHome = System.getProperty("robocode.home"); + + if (robocodeHome == null) { + throw new RuntimeException("System property robocode.home is not set."); + } + + File robocodeJar = new File(new File(robocodeHome), "libs/robocode.jar"); + + if (!robocodeJar.exists()) { + throw new RuntimeException("robocode.jar not found. robocode.home: " + robocodeHome); + } + + // Now create the robocode engine. + engine = new RobocodeEngine(new File(robocodeHome)); + } + + /** + * Called after each turn, and implements basic logging information about the turn number and + * the position of each robot. + *

+ * Override this method to perform testing at the end of each turn. + * + * @param event The TurnEndedEvent. + */ + public void onTurnEnded(TurnEndedEvent event) { + if (isDumpingTurns) { + Logger.realOut.println("turn " + event.getTurnSnapshot().getTurn()); + } + for (IRobotSnapshot robot : event.getTurnSnapshot().getRobots()) { + if (isDumpingPositions) { + Logger.realOut.print(robot.getVeryShortName()); + Logger.realOut.print(" X:"); + Logger.realOut.print(robot.getX()); + Logger.realOut.print(" Y:"); + Logger.realOut.print(robot.getY()); + Logger.realOut.print(" V:"); + Logger.realOut.print(robot.getVelocity()); + Logger.realOut.println(); + } + if (isDumpingOutput) { + Logger.realOut.print(robot.getOutputStreamSnapshot()); + } + } + } + + /** + * Must return a comma-separated list of fully qualified robot names to be in this battle. + *

+ * You must override this event to specify the robots to battle in this test case. + * + * @return The list of robots. + */ + public abstract String getRobotNames(); + + /** + * Provides the number of rounds in this battle. Defaults to 1. + * Override this to change the number of rounds. + * + * @return The number of rounds. + */ + public int getNumRounds() { + return 1; + } + + /** + * Returns a comma or space separated list like: x1,y1,heading1, x2,y2,heading2, which are the + * coordinates and heading of robot #1 and #2. So "0,0,180, 50,80,270" means that robot #1 + * has position (0,0) and heading 180, and robot #2 has position (50,80) and heading 270. + *

+ * Override this method to explicitly specify the initial positions. + *

+ * Defaults to null, which means that the initial positions are determined randomly. Since + * battles are deterministic by default, the initial positions are randomly chosen but will + * always be the same each time you run the test case. + * + * @return The list of initial positions. + */ + public String getInitialPositions() { + return null; + } + + /** + * Provides the number of robots in this battle. + * + * @param robotList The list of robots. + * @return The number of robots in this battle. + */ + private int getExpectedRobotCount(String robotList) { + return robotList.split("[\\s,;]+").length; + } + + /** + * Defaults to true, indicating that the battle is deterministic and robots will always start + * in the same position each time. + *

+ * Override to support random initialization. + * + * @return True if the battle will be deterministic. + */ + public boolean isDeterministic() { + return true; + } + + /** + * The setup method run before each test, which sets up the listener on the engine for testing. + * Don't override this method; instead, override runSetup to add behavior before the test + * battle starts. + */ + @Before + public void setup() { + engine.addBattleListener(this); + if (isDeterministic()) { + RandomFactory.resetDeterministic(0); + } + this.height = battleFieldSpec.getHeight(); + this.width = battleFieldSpec.getWidth(); + errors = 0; + messages = 0; + } + + /** + * After each test is run, the listener is removed. + * Don't override this method; instead, override runTearDown to add behavior after the test + * battle ends. + */ + @After + public void tearDown() { + engine.removeBattleListener(this); + } + + /** + * Runs a test, invoking the runSetup method before the battle starts and the + * runTearDown method after the battle ends. + * Asserts that the expected number of errors for this battle were obtained. + */ + @Test + public void run() { + runSetup(); + runBattle(getRobotNames(), getNumRounds(), getInitialPositions()); + runTeardown(); + RobotTestBedAssert.assertThat(errors, is(getExpectedErrors())); + } + + /** + * Specifies how many errors you expect this battle to generate. + * Defaults to 0. Override this method to change the number of expected errors. + * + * @return The expected number of errors. + */ + protected int getExpectedErrors() { + return 0; + } + + /** + * Invoked before the test battle begins. + * Default behavior is to do nothing. + * Override this method in your test case to add behavior before the battle starts. + */ + protected void runSetup() {// Default does nothing. + } + + /** + * Invoked after the test battle ends. + * Default behavior is to do nothing. + * Override this method in your test case to add behavior after the battle ends. + */ + protected void runTeardown() {// Default does nothing. + } + + /** + * Runs the test battle. + * + * @param robotList The list of robots. + * @param numRounds The number of rounds. + * @param initialPositions The initial positions for the robots. + */ + private void runBattle(String robotList, int numRounds, String initialPositions) { + final RobotSpecification[] robotSpecifications = engine.getLocalRepository(robotList); + + if (getExpectedRobotCount(robotList) > 0) { + RobotTestBedAssert.assertNotNull("Robot not loaded", robotSpecifications); + RobotTestBedAssert.assertEquals("Robot not loaded", getExpectedRobotCount(robotList), + robotSpecifications.length); + engine.runBattle(new BattleSpecification(numRounds, battleFieldSpec, robotSpecifications), initialPositions, + true); + } + } + + /** + * Keep track of the number of messages. Print them if desired. + * + * @param event The BattleMessageEvent. + */ + public void onBattleMessage(BattleMessageEvent event) { + if (isDumpingMessages) { + Logger.realOut.println(event.getMessage()); + } + messages++; + } + + /** + * Keep track of the number of errors. Print them if desired. + * + * @param event The BattleErrorEvent. + */ + public void onBattleError(BattleErrorEvent event) { + if (isDumpingErrors) { + Logger.realErr.println(event.getError()); + } + errors++; + } +} diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/RobotTestBedAssert.java b/代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/RobotTestBedAssert.java new file mode 100644 index 0000000..efb7fe8 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/RobotTestBedAssert.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.testing; + + +import robocode.util.Utils; + + +/** + * Provides some additional Assert methods for use in Robocode. + * + * @author Philip Johnson (original) + * @author Pavel Savara (contributor) + */ +public class RobotTestBedAssert extends org.junit.Assert { + + /** + * Asserts that the two values are "sufficiently close". + * Define sufficiently close using Utils.NEAR_DELTA. + * + * @param value1 First value. + * @param value2 Second value. + */ + public static void assertNear(double value1, double value2) { + org.junit.Assert.assertEquals(value1, value2, Utils.NEAR_DELTA); + } +} diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/package.html b/代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/package.html new file mode 100644 index 0000000..b0fe82d --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.api/src/main/java/robocode/control/testing/package.html @@ -0,0 +1,12 @@ + + +Provides a harness for JUnit testing. + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.content/.classpath b/代码/workspace_robo4/plugins/testing/robocode.testing.content/.classpath new file mode 100644 index 0000000..31eaf22 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.content/.classpath @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.content/.project b/代码/workspace_robo4/plugins/testing/robocode.testing.content/.project new file mode 100644 index 0000000..a5b7468 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.content/.project @@ -0,0 +1,16 @@ + + + robocode.testing.content + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.testing.samples + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.content/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/testing/robocode.testing.content/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..7040061 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.content/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:14:20 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.content/pom.xml b/代码/workspace_robo4/plugins/testing/robocode.testing.content/pom.xml new file mode 100644 index 0000000..11e7063 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.content/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + robocode.testing.content + Robot Testing Framework Static Content + + net.sf.robocode + robocode.testing + ${robocode.version} + + + + net.sf.robocode + robocode.testing.samples + ${project.version} + + + net.sf.robocode + robocode.testing.api + + + net.sf.robocode + robocode.api + + + junit + junit + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.content/robocode.testing.content.iml b/代码/workspace_robo4/plugins/testing/robocode.testing.content/robocode.testing.content.iml new file mode 100644 index 0000000..4203486 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.content/robocode.testing.content.iml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/Read.Me.txt b/代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/Read.Me.txt new file mode 100644 index 0000000..f856f5f --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/Read.Me.txt @@ -0,0 +1,33 @@ +==== + Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://robocode.sourceforge.net/license/epl-v10.html +==== + +This is way how to test your robots with JUnit and Robocode. + +1) Look at robocode/testing/sample/TestWallBehavior.java + - it's behavioral integration test, to proove that samples.Wall robot will visit all 4 corners of battlefield + - it's inherited from robocode.control.testing.RobotTestBed, which is part of robocode.testing extension + +2) RobotTestBed - base class for tests + - provides setup of Robocode engine itself + - expects you to set Java system property robocode.home to path to your robocode installation. For example C:\Robocode + - supports setup of battle by overriding various virtual methods, among others + - getRobotNames() - allows you to specify coma separated list of robos for battle + - getNumRounds() - allows you to specify number of rounds for the battle + - for more see robocode/testing/javadoc/index.html + - implements IBattleListener interface of robocode and it's notified about battle events + - override onTurnEnded() method to be invoked after each turn, with snapshot of current battlefield + - override onBattleCompleted() method to be invoked after battle, with battle resutls and scores + - for more see robocode/testing/javadoc/index.html and robocode/javadoc/index.html + +3) Build the unit test by starting robocode\testing\compile.cmd or do it in your IDE + +4) Run the test with JUnit by starting robocode\testing\test.cmd or do it in your IDE + - note that we pass -Drobocode.home Java property + +5) watch the test result + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/compile.cmd b/代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/compile.cmd new file mode 100644 index 0000000..b877710 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/compile.cmd @@ -0,0 +1,10 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off +javac -cp ../libs/junit-4.5.jar;../libs/robocode.jar;../libs/robocode.testing.jar sample/TestWallBehavior.java \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/test.cmd b/代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/test.cmd new file mode 100644 index 0000000..3f14b58 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.content/src/main/resources/testing/test.cmd @@ -0,0 +1,10 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off +java -Drobocode.home=.. -cp ../libs/junit-4.5.jar;../libs/robocode.jar;../libs/robocode.testing.jar;.; org.junit.runner.JUnitCore sample.TestWallBehavior diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.classpath b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.classpath new file mode 100644 index 0000000..9e54ea0 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.project b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.project new file mode 100644 index 0000000..716aee0 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.project @@ -0,0 +1,19 @@ + + + robocode.testing.distribution + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.testing.api + robocode.testing.content + robocode.testing.samples + robocode.testing.installer + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..7040061 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:14:20 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/pom.xml b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/pom.xml new file mode 100644 index 0000000..93569f0 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + robocode.testing.distribution + Robot Testing Framework Distribution + + net.sf.robocode + robocode.testing + ${robocode.version} + + + + net.sf.robocode + robocode.testing.api + ${project.version} + jar + + + net.sf.robocode + robocode.testing.content + ${project.version} + jar + + + net.sf.robocode + robocode.testing.installer + ${project.version} + jar + + + net.sf.robocode + robocode.testing.samples + ${project.version} + jar + + + junit + junit + 4.11 + jar + + + + + + maven-assembly-plugin + + ${project.parent.artifactId}-${project.version} + true + + testing-setup.asm.xml + + + + net.sf.robocode.installer.AutoExtract + + + + + + make-assembly + package + + single + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/robocode.testing.distribution.iml b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/robocode.testing.distribution.iml new file mode 100644 index 0000000..60e4af3 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/robocode.testing.distribution.iml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/testing-setup.asm.xml b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/testing-setup.asm.xml new file mode 100644 index 0000000..54b0fc4 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.distribution/testing-setup.asm.xml @@ -0,0 +1,79 @@ + + + setup + + dir + jar + + false + + + + + junit:junit + + libs + false + + + + + net.sf.robocode:robocode.testing.api + + libs + false + robocode.testing.${artifact.extension} + + + + net.sf.robocode:robocode.testing.api:javadoc + + testing/javadoc + true + + + + + net.sf.robocode:robocode.testing.samples + + testing + true + + + **/META-INF/** + **/*.class + + + + + + + net.sf.robocode:robocode.testing.installer + net.sf.robocode:robocode.testing.content + + true + + + **/META-INF/** + + + + + + + ../robocode.testing.api/target/site/apidocs + /testing/javadoc + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.iml b/代码/workspace_robo4/plugins/testing/robocode.testing.iml new file mode 100644 index 0000000..c163c5f --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.iml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.installer/.classpath b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/.classpath new file mode 100644 index 0000000..faff71b --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/.classpath @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.installer/.project b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/.project new file mode 100644 index 0000000..dc2dd6e --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/.project @@ -0,0 +1,14 @@ + + + robocode.testing.installer + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.installer/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..7040061 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:14:20 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.installer/pom.xml b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/pom.xml new file mode 100644 index 0000000..5336a18 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + robocode.testing.installer + Robot Testing Framework Installer + + net.sf.robocode + robocode.testing + ${robocode.version} + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + net.sf.robocode.installer.AutoExtract + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.installer/robocode.testing.installer.iml b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/robocode.testing.installer.iml new file mode 100644 index 0000000..93c108a --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.installer/robocode.testing.installer.iml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.ipr b/代码/workspace_robo4/plugins/testing/robocode.testing.ipr new file mode 100644 index 0000000..55ed2f3 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.ipr @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.iws b/代码/workspace_robo4/plugins/testing/robocode.testing.iws new file mode 100644 index 0000000..03c854e --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.iws @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.samples/.classpath b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/.classpath new file mode 100644 index 0000000..88b5f19 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.samples/.project b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/.project new file mode 100644 index 0000000..8fa0726 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/.project @@ -0,0 +1,16 @@ + + + robocode.testing.samples + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.testing.api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.samples/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..ee629d3 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:14:19 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.samples/pom.xml b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/pom.xml new file mode 100644 index 0000000..c237b80 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + robocode.testing.samples + Robot Testing Framework Samples + + net.sf.robocode + robocode.testing + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + net.sf.robocode + robocode.testing.api + ${project.version} + + + net.sf.robocode + robocode.tests + ${project.version} + test + + + junit + junit + 4.11 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + + robocode.home + ${project.build.directory}/../../../../robocode.tests/target/classes + + + + + + + + src/main/java + false + + **/*.java + + + + src/main/resources + false + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.samples/robocode.testing.samples.iml b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/robocode.testing.samples.iml new file mode 100644 index 0000000..fc33155 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/robocode.testing.samples.iml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/plugins/testing/robocode.testing.samples/src/main/java/sample/TestWallBehavior.java b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/src/main/java/sample/TestWallBehavior.java new file mode 100644 index 0000000..1a8bf38 --- /dev/null +++ b/代码/workspace_robo4/plugins/testing/robocode.testing.samples/src/main/java/sample/TestWallBehavior.java @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import static org.junit.Assert.assertTrue; +import robocode.control.events.BattleCompletedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.testing.RobotTestBed; + + +/** + * Tests that sample.Walls moves to all four corners. + * + * @author Philip Johnson (original) + * @author Pavel Savara (contributor) + */ +public class TestWallBehavior extends RobotTestBed { + + /** + * True if the robot visited this corner during the test case. + */ + boolean visitedUpperLeft = false; + + /** + * True if the robot visited this corner during the test case. + */ + boolean visitedUpperRight = false; + + /** + * True if the robot visited this corner during the test case. + */ + boolean visitedLowerLeft = false; + + /** + * True if the robot visited this corner during the test case. + */ + boolean visitedLowerRight = false; + + /** + * Specifies that SittingDuck and DaCruzer are to be matched up in this test case. + * + * @return The comma-delimited list of robots in this match. + */ + @Override + public String getRobotNames() { + return "sample.SittingDuck,sample.Walls"; + } + + /** + * This test runs for 1 round. + * + * @return The number of rounds. + */ + @Override + public int getNumRounds() { + return 1; + } + + /** + * After each turn, check to see if we're at a corner. If so, set the corresponding flag. + * + * @param event Info about the current state of the battle. + */ + @Override + public void onTurnEnded(TurnEndedEvent event) { + IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[1]; + double xPos = robot.getX(); + double yPos = robot.getY(); + + if ((xPos < 40) && (yPos < 40)) { + visitedUpperLeft = true; + } + if ((xPos < 40 && (yPos > (height - 40)))) { + visitedLowerLeft = true; + } + if ((xPos > (width - 40)) && (yPos < 40)) { + visitedUpperRight = true; + } + if ((xPos > (width - 40) && (yPos > (height - 40)))) { + visitedLowerRight = true; + } + } + + /** + * After the battle, check to see that we've visited the corners. + * + * @param event Details about the completed battle. + */ + @Override + public void onBattleCompleted(BattleCompletedEvent + event) { + assertTrue("Check UpperLeft", visitedUpperLeft); + assertTrue("Check LowerLeft", visitedLowerLeft); + assertTrue("Check UpperRight", visitedUpperRight); + assertTrue("Check LowerRight", visitedLowerRight); + } +} diff --git a/代码/workspace_robo4/pom.xml b/代码/workspace_robo4/pom.xml new file mode 100644 index 0000000..c880dfc --- /dev/null +++ b/代码/workspace_robo4/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + robocode + Robocode + pom + + super-pom + net.sf.robocode + ${robocode.version} + super-pom + + + robocode.api + robocode.core + robocode.battle + robocode.host + robocode.ui + robocode.ui.editor + robocode.sound + robocode.samples + robocode.roborumble + robocode.tests.robots + robocode.tests + robocode.installer + robocode.repository + robocode.content + robocode.distribution + + + + + com.mycila + license-maven-plugin + 2.6 + +

super-pom/robocode-license-header.txt
+ + **/*.properties + **/ReadMe.* + tools/bin/** + tools/licenses/** + LICENSE.txt + **/license/** + **/CILReader.cs + **/roborumble/*.txt + **/pom.xml + + + + + + format + + + + + + + diff --git a/代码/workspace_robo4/robocode.api/.classpath b/代码/workspace_robo4/robocode.api/.classpath new file mode 100644 index 0000000..faff71b --- /dev/null +++ b/代码/workspace_robo4/robocode.api/.classpath @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.api/.externalToolBuilders/Launch Dir Builder.launch b/代码/workspace_robo4/robocode.api/.externalToolBuilders/Launch Dir Builder.launch new file mode 100644 index 0000000..1f54b39 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/.externalToolBuilders/Launch Dir Builder.launch @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.api/.gitignore b/代码/workspace_robo4/robocode.api/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/.gitignore @@ -0,0 +1 @@ +target diff --git a/代码/workspace_robo4/robocode.api/.project b/代码/workspace_robo4/robocode.api/.project new file mode 100644 index 0000000..3f3e191 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/.project @@ -0,0 +1,26 @@ + + + robocode.api + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.ui.externaltools.ExternalToolBuilder + + + LaunchConfigHandle + <project>/.externalToolBuilders/Launch Dir Builder.launch + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/代码/workspace_robo4/robocode.api/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.api/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..65f3846 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:08 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.api/Robocode.launch b/代码/workspace_robo4/robocode.api/Robocode.launch new file mode 100644 index 0000000..c7fb7fe --- /dev/null +++ b/代码/workspace_robo4/robocode.api/Robocode.launch @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.api/pom.xml b/代码/workspace_robo4/robocode.api/pom.xml new file mode 100644 index 0000000..f26680a --- /dev/null +++ b/代码/workspace_robo4/robocode.api/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + robocode.api + Robocode API + + net.sf.robocode + robocode + ${robocode.version} + + + + + org.apache.maven.plugins + maven-jar-plugin + + robocode + + + robocode.Robocode + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + package + + javadoc + + + + + Robocode ${project.version} API + true + + Robocode ${project.version} API]]> + + + http://docs.oracle.com/javase/6/docs/api/ + + false + robocode.exception:net.sf.robocode:gl4java:robocode.robocodeGL + ${javadoc.additionalparam} + + + + org.apache.maven.plugins + maven-deploy-plugin + + false + + + + + diff --git a/代码/workspace_robo4/robocode.api/robocode.api.iml b/代码/workspace_robo4/robocode.api/robocode.api.iml new file mode 100644 index 0000000..613ddb1 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/robocode.api.iml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.api/src/main/java/gl4java/GLFont.java b/代码/workspace_robo4/robocode.api/src/main/java/gl4java/GLFont.java new file mode 100644 index 0000000..5ed7f60 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/gl4java/GLFont.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package gl4java; + + +/** + * Dummy class that stub out RobocodeGL 0.1.4 functionality. + * + * Original author is David Alves for RobocodeGL. + */ +public class GLFont {} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/gl4java/GLFunc.java b/代码/workspace_robo4/robocode.api/src/main/java/gl4java/GLFunc.java new file mode 100644 index 0000000..6f8bc58 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/gl4java/GLFunc.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package gl4java; + + +/** + * Dummy class that stub out RobocodeGL 0.1.4 functionality. + * + * Original author is David Alves for RobocodeGL. + */ +public class GLFunc {} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/api/Module.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/api/Module.java new file mode 100644 index 0000000..0936dd9 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/api/Module.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.api; + + +import net.sf.robocode.core.IModule; +import net.sf.robocode.serialization.RbSerializer; +import robocode.*; + +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public class Module implements IModule { + public void afterLoaded(List allModules) { + RbSerializer.register(RobotStatus.class, RbSerializer.RobotStatus_TYPE); + RbSerializer.register(BattleResults.class, RbSerializer.BattleResults_TYPE); + RbSerializer.register(Bullet.class, RbSerializer.Bullet_TYPE); + + // events + RbSerializer.register(RoundEndedEvent.class, RbSerializer.RoundEndedEvent_TYPE); + RbSerializer.register(BattleEndedEvent.class, RbSerializer.BattleEndedEvent_TYPE); + RbSerializer.register(BulletHitBulletEvent.class, RbSerializer.BulletHitBulletEvent_TYPE); + RbSerializer.register(BulletHitEvent.class, RbSerializer.BulletHitEvent_TYPE); + RbSerializer.register(BulletMissedEvent.class, RbSerializer.BulletMissedEvent_TYPE); + RbSerializer.register(DeathEvent.class, RbSerializer.DeathEvent_TYPE); + + RbSerializer.register(WinEvent.class, RbSerializer.WinEvent_TYPE); + RbSerializer.register(HitWallEvent.class, RbSerializer.HitWallEvent_TYPE); + RbSerializer.register(RobotDeathEvent.class, RbSerializer.RobotDeathEvent_TYPE); + RbSerializer.register(SkippedTurnEvent.class, RbSerializer.SkippedTurnEvent_TYPE); + RbSerializer.register(ScannedRobotEvent.class, RbSerializer.ScannedRobotEvent_TYPE); + RbSerializer.register(HitByBulletEvent.class, RbSerializer.HitByBulletEvent_TYPE); + RbSerializer.register(HitRobotEvent.class, RbSerializer.HitRobotEvent_TYPE); + RbSerializer.register(KeyPressedEvent.class, RbSerializer.KeyPressedEvent_TYPE); + RbSerializer.register(KeyReleasedEvent.class, RbSerializer.KeyReleasedEvent_TYPE); + RbSerializer.register(KeyTypedEvent.class, RbSerializer.KeyTypedEvent_TYPE); + RbSerializer.register(MouseClickedEvent.class, RbSerializer.MouseClickedEvent_TYPE); + RbSerializer.register(MouseDraggedEvent.class, RbSerializer.MouseDraggedEvent_TYPE); + RbSerializer.register(MouseEnteredEvent.class, RbSerializer.MouseEnteredEvent_TYPE); + RbSerializer.register(MouseExitedEvent.class, RbSerializer.MouseExitedEvent_TYPE); + RbSerializer.register(MouseMovedEvent.class, RbSerializer.MouseMovedEvent_TYPE); + RbSerializer.register(MousePressedEvent.class, RbSerializer.MousePressedEvent_TYPE); + RbSerializer.register(MouseReleasedEvent.class, RbSerializer.MouseReleasedEvent_TYPE); + RbSerializer.register(MouseWheelMovedEvent.class, RbSerializer.MouseWheelMovedEvent_TYPE); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/battle/IBattleManagerBase.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/battle/IBattleManagerBase.java new file mode 100644 index 0000000..f32f146 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/battle/IBattleManagerBase.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +import robocode.control.BattleSpecification; +import robocode.control.events.IBattleListener; + + +/** + * @author Pavel Savara (original) + */ +public interface IBattleManagerBase { + void addListener(IBattleListener listener); + + void removeListener(IBattleListener listener); + + void waitTillOver(); + + void stop(boolean waitTillEnd); + + void startNewBattle(BattleSpecification spec, String initialPositions, boolean waitTillOver, boolean enableCLIRecording); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/core/ContainerBase.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/core/ContainerBase.java new file mode 100644 index 0000000..341c6a8 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/core/ContainerBase.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.core; + + +/** + * @author Pavel Savara (original) + */ +public abstract class ContainerBase { + public static ContainerBase instance; + + protected abstract T getBaseComponent(java.lang.Class tClass); + + public static T getComponent(java.lang.Class tClass) { + return instance == null ? null : instance.getBaseComponent(tClass); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/core/IModule.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/core/IModule.java new file mode 100644 index 0000000..177717e --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/core/IModule.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.core; + + +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public interface IModule { + void afterLoaded(List allModules); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/gui/IWindowManagerBase.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/gui/IWindowManagerBase.java new file mode 100644 index 0000000..815715b --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/gui/IWindowManagerBase.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.gui; + + +/** + * @author Pavel Savara (original) + */ +public interface IWindowManagerBase { + void setVisibleForRobotEngine(boolean visible); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/FileUtil.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/FileUtil.java new file mode 100644 index 0000000..c9994b3 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/FileUtil.java @@ -0,0 +1,352 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.io; + + +import static net.sf.robocode.io.Logger.logError; + +import java.io.*; + + +/** + * This is a class for file utilization. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class FileUtil { + + // Current working directory + private static File cwd; + + // Initializes the current working directory + static { + try { + final String wd = System.getProperty("WORKINGDIRECTORY", ""); + + FileUtil.setCwd(new File(wd)); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Returns the current working directory. + * + * @return a File for the current working directory + */ + public static File getCwd() { + return cwd; + } + + /** + * Changes the current working directory. + * + * @param cwd a File that is the new working directory + * @throws IOException if an I/O exception occurs + */ + public static void setCwd(File cwd) throws IOException { + FileUtil.cwd = cwd.getCanonicalFile(); + } + + /** + * Returns the file type of a file, i.e. it's extension. + * + * @param file the file + * @return the file type of the file, e.g. ".class", ".jar" or "" if the + * file name does not contain an extension. + */ + public static String getFileType(File file) { + return getFileType(file.getName()); + } + + /** + * Returns the file type of a file name, i.e. it's extension. + * + * @param fileName the file name + * @return the file type of the file name, e.g. ".class", ".jar" or "" if + * the file name does not contain an extension. + */ + public static String getFileType(String fileName) { + int lastdot = fileName.lastIndexOf('.'); + + return (lastdot < 0) ? "" : fileName.substring(lastdot); + } + + /** + * Quotes a file name if it contains white spaces and has not already been + * quoted. + * + * @param filename the file to quote + * @return a quoted version of the specified filename + */ + public static String quoteFileName(String filename) { + if (filename.startsWith("\"") && filename.endsWith("\"")) { + return filename; + } + if (System.getProperty("os.name").toLowerCase().startsWith("windows") && filename.startsWith("file://")) { + filename = filename.substring(7); + } + if (filename.matches(".*\\s+?.*")) { + return '"' + filename + '"'; + } + return filename; + } + + /** + * Copies a file into another file. + * + * @param srcFile the input file to copy + * @param destFile the output file to copy to + * @throws IOException if an I/O exception occurs + */ + public static void copy(File srcFile, File destFile) throws IOException { + if (srcFile.equals(destFile)) { + throw new IOException("You cannot copy a file onto itself"); + } + + byte buf[] = new byte[4096]; + + FileInputStream in = null; + FileOutputStream out = null; + + try { + in = new FileInputStream(srcFile); + out = new FileOutputStream(destFile); + + while (in.available() > 0) { + out.write(buf, 0, in.read(buf, 0, buf.length)); + } + } finally { + if (in != null) { + in.close(); + } + if (out != null) { + out.close(); + } + } + } + + /** + * Deletes a directory. + * + * @param dir the file for the directory to delete + * @return true if success + */ + public static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + for (File file : dir.listFiles()) { + if (file.isDirectory()) { + try { + // Test for symlink and ignore. + // Robocode won't create one, but just in case a user does... + if (file.getCanonicalFile().getParentFile().equals(dir.getCanonicalFile())) { + deleteDir(file); + if (file.exists() && !file.delete()) { + Logger.logError("Cannot delete: " + file); + } + } else { + Logger.logWarning(file + " may be a symlink. Ignoring."); + } + } catch (IOException e) { + Logger.logWarning("Cannot determine canonical file for " + file + ". Ignoring."); + } + } else { + if (file.exists() && !file.delete()) { + Logger.logError("Cannot delete: " + file); + } + } + } + return dir.delete(); + } + return false; + } + + /** + * Creates a directory if it does not exist already + * + * @param dir the File that represents the new directory to create. + * @return the created directory + */ + public static File createDir(File dir) { + if (dir != null && !dir.exists()) { + if (!dir.mkdir()) { + Logger.logError("Cannot create dir: " + dir); + } + } + return dir; + } + + /** + * Returns the class name of the specified filename. + * + * @param fileName the filename to extract the class name from + * @return the class name of the specified filename + */ + public static String getClassName(String fileName) { + int lastdot = fileName.lastIndexOf('.'); + + if (lastdot < 0) { + return fileName; + } + if (fileName.length() - 1 == lastdot) { + return fileName.substring(0, fileName.length() - 1); + } + return fileName.substring(0, lastdot); + } + + /** + * Returns the directory containing the robots. + * + * @return a File that is the directory containing the robots + */ + public static File getRobotsDir() { + String robotPath = System.getProperty("ROBOTPATH"); + File file; + + if (robotPath != null) { + file = new File(robotPath); + } else { + file = new File(cwd, "/robots"); + } + return createDir(file); + } + + /** + * Returns the robot database file. + * + * @return a File that is the directory containing the robot cache. + */ + public static File getRobotDatabaseFile() { + return new File(getRobotsDir(), "/robot.database"); + } + + /** + * Returns the directory containing data files of robots. + * + * @return a File that is the directory containing the robot data. + */ + public static File getRobotsDataDir() { + return createDir(new File(getRobotsDir(), "/.data/")); + } + + /** + * Returns the directory containing the battle files. + * + * @return a File that is the directory containing the battle files + */ + public static File getBattlesDir() { + return createDir(new File(cwd, "/battles")); + } + + /** + * Returns the directory containing the configuration files. + * If the directory does not exist, it will be created automatically. + * + * @return a File that is the directory containing configuration files + */ + public static File getConfigDir() { + return createDir(new File(cwd, "/config")); + } + + /** + * Returns the directory containing the screen shot files. + * If the directory does not exist, it will be created automatically. + * + * @return a File that is the directory containing screen shot files + */ + public static File getScreenshotsDir() { + return createDir(new File(cwd, "/screenshots")); + } + + /** + * Returns the Robocode configuration file. + * + * @return a File that is the Robocode configuration file. + */ + public static File getRobocodeConfigFile() { + return new File(getConfigDir(), "robocode.properties"); + } + + /** + * Returns the window configuration file. + * + * @return a File that is the window configuration file. + */ + public static File getWindowConfigFile() { + return new File(getConfigDir(), "window.properties"); + } + + /** + * Returns the compiler configuration file. + * + * @return a File that is the compiler configuration file. + */ + public static File getCompilerConfigFile() { + return new File(getConfigDir(), "compiler.properties"); + } + + /** + * Returns the source code editor configuration file. + * + * @return a File that is the editor configuration file. + */ + public static File getEditorConfigFile() { + return new File(getConfigDir(), "editor.properties"); + } + + /** + * Returns the editor theme directory. + * + * @return a File that is the directory containing the editor theme files. + */ + public static File getEditorThemeConfigDir() { + return createDir(new File(cwd, "/theme/editor")); + } + + /** + * Cleans up a stream by flushing it and closing it if it is not null. + * + * @param stream the stream to clean up. + */ + public static void cleanupStream(Object stream) { + if (stream == null) { + return; + } + if (stream instanceof Flushable) { + try { + ((Flushable) stream).flush(); + } catch (IOException e) { + logError(e); + } + } + if (stream instanceof Closeable) { + try { + ((Closeable) stream).close(); + } catch (IOException e) { + logError(e); + } + } + } + + /** + * Checks if a filename is valid. + * + * @param file the filename to check. + * @return true if the filename is valid; false otherwise. + */ + public static boolean isFilenameValid(String file) { + File f = new File(file); + try { + f.getCanonicalPath(); + return true; + } catch (IOException e) { + return false; + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/Logger.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/Logger.java new file mode 100644 index 0000000..a903fd8 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/Logger.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.io; + + +import net.sf.robocode.security.HiddenAccess; +import net.sf.robocode.util.StringUtil; +import robocode.control.events.BattleErrorEvent; +import robocode.control.events.BattleMessageEvent; +import robocode.control.events.IBattleListener; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + + +/** + * This is a class used for logging. + * + * @author Flemming N. Larsen (original) + * @author Mathew A. Nelson (original) + */ +public class Logger { + public static final PrintStream realOut = System.out; + public static final PrintStream realErr = System.err; + + private static IBattleListener logListener; + + private final static StringBuffer logBuffer = new StringBuffer(); + + public static void setLogListener(IBattleListener logListener) { + Logger.logListener = logListener; + } + + public static void logMessage(String s) { + logMessage(s, true); + } + + public static void logMessage(String s, boolean newline) { + if (logListener == null) { + if (System.getProperty("logMessages", "true").equalsIgnoreCase("true")) { + s = StringUtil.toBasicLatin(s); + if (newline) { + realOut.println(s); + } else { + realOut.print(s); + realOut.flush(); + } + } + } else { + synchronized (logBuffer) { + if (!HiddenAccess.isSafeThread()) { + // we just queue it, to not let unsafe thread travel thru system + logBuffer.append(s); + logBuffer.append("\n"); + } else if (newline) { + logListener.onBattleMessage(new BattleMessageEvent(logBuffer + s)); + logBuffer.setLength(0); + } else { + logBuffer.append(s); + } + } + } + } + + public static void logWarning(String s) { + logMessage("Warning: " + s, true); + } + + public static void logError(String message, Throwable t) { + logError(message + ":\n" + toStackTraceString(t)); + } + + public static void logError(Throwable t) { + logError(toStackTraceString(t)); + } + + public static void logError(String s) { + if (logListener == null) { + if (System.getProperty("logErrors", "true").equalsIgnoreCase("true")) { + s = StringUtil.toBasicLatin(s); + realErr.println(s); + } + } else { + logListener.onBattleError(new BattleErrorEvent(s)); + } + } + + private static String toStackTraceString(Throwable t) { + if (t == null) { + return ""; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(baos); + + t.printStackTrace(ps); + ps.close(); + return baos.toString(); + } + + public static void printlnToRobotsConsole(String s) { + // this will get redirected to robot's console + System.out.println(s); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/RobocodeProperties.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/RobocodeProperties.java new file mode 100644 index 0000000..d39924f --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/io/RobocodeProperties.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.io; + + +/** + * Utility class for convenient access to Robocode system wide properties. + * + * @author Flemming N. Larsen (original) + */ +public final class RobocodeProperties { + + // These properties can only be set at startup + private static final boolean NO_SECURITY = System.getProperty("NOSECURITY", "false").equals("true"); + private static final boolean DEBUG = System.getProperty("debug", "false").equals("true"); + + private RobocodeProperties() {} + + /** + * Checks if security is off, i.e. that the NOSECURITY property has been set to true. + * @return true if security is disabled; false if security is enabled. + */ + public static boolean isSecurityOff() { + return NO_SECURITY; + } + + /** + * Checks if security is on, i.e. that the NOSECURITY property has been set to false or not defined at all. + * @return true if security is enabled; false if security is disabled. + */ + public static boolean isSecurityOn() { + return !NO_SECURITY; + } + + /** + * Checks if debugging is disabled. + * @return true if debugging is disabled; false is debugging is enabled. + */ + public static boolean isDebuggingOff() { + return !DEBUG; + } + + /** + * Checks if debugging is enabled. + * @return true if debugging is enabled; false is debugging is disabled. + */ + public static boolean isDebuggingOn() { + return DEBUG; + } + + /** + * Sets the testing flag. + * @param enabled true if testing is being enabled; false if testing is being disabled. + */ + public static void setTesting(boolean enabled) { + System.setProperty("TESTING", "" + enabled); + } + + /** + * Checks if testing is disabled. + * @return true if testing is disabled; false is testing is enabled. + */ + public static boolean isTestingOff() { + return !isTestingOn(); + } + + /** + * Checks if testing is enabled. + * @return true if testing is enabled; false is testing is disabled. + */ + public static boolean isTestingOn() { + return System.getProperty("TESTING", "false").equals("true"); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/manager/IVersionManagerBase.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/manager/IVersionManagerBase.java new file mode 100644 index 0000000..f679071 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/manager/IVersionManagerBase.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.manager; + + +/** + * @author Pavel Savara (original) + */ +public interface IVersionManagerBase { + String getVersion(); + String getVersionN(); + int getVersionAsInt(); + boolean isLastRunVersionChanged(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/peer/IRobotStatics.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/peer/IRobotStatics.java new file mode 100644 index 0000000..3a1646c --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/peer/IRobotStatics.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.peer; + + +/** + * @author Pavel Savara (original) + */ +public interface IRobotStatics { + boolean isInteractiveRobot(); + + boolean isPaintRobot(); + + boolean isAdvancedRobot(); + + boolean isTeamRobot(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/repository/CodeSizeCalculator.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/repository/CodeSizeCalculator.java new file mode 100644 index 0000000..b1bbdb4 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/repository/CodeSizeCalculator.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + + +/** + * Tool used for calculating the code size of a directory or jar file. + * + * @author Flemming N. Larsen (original) + */ +public final class CodeSizeCalculator { + + public static Integer getDirectoryCodeSize(File dir) { + return getCodeSize("processDirectory", dir); + } + + public static Integer getJarFileCodeSize(File jarFile) { + return getCodeSize("processZipFile", jarFile); + } + + private static Integer getCodeSize(String invokeMethod, File jarFile) { + Integer codesize; + try { + // Call the code size utility using reflection + Class classType = Class.forName("codesize.Codesize"); + + Method method = classType.getMethod(invokeMethod, new Class[] { File.class }); + Object item = method.invoke(null/* static method */, jarFile); + + // Calls Codesize.Item.getCodeSize() + method = item.getClass().getMethod("getCodeSize", (Class[]) null); + codesize = (Integer) method.invoke(item, (Object[]) null); + + } catch (IllegalAccessException e) { + codesize = null; + } catch (InvocationTargetException e) { + codesize = null; + } catch (NoSuchMethodException e) { + codesize = null; + } catch (ClassNotFoundException e) { + codesize = null; + } + return codesize; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/repository/IRepositoryManagerBase.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/repository/IRepositoryManagerBase.java new file mode 100644 index 0000000..5873b6c --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/repository/IRepositoryManagerBase.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import robocode.control.RobotSpecification; + + +/** + * @author Pavel Savara (original) + */ +public interface IRepositoryManagerBase { + boolean refresh(); + RobotSpecification[] getSpecifications(); + RobotSpecification[] loadSelectedRobots(String selectedRobots); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenBulletHelper.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenBulletHelper.java new file mode 100644 index 0000000..08b8b67 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenBulletHelper.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.security; + + +import robocode.Bullet; + + +/** + * @author Pavel Savara (original) + */ +public interface IHiddenBulletHelper { + void update(Bullet bullet, double x, double y, String victimName, boolean isActive); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenEventHelper.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenEventHelper.java new file mode 100644 index 0000000..8c6d2e0 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenEventHelper.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.security; + + +import net.sf.robocode.peer.IRobotStatics; +import robocode.Event; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; + + +/** + * @author Pavel Savara (original) + */ +public interface IHiddenEventHelper { + void setDefaultPriority(Event event); + void setPriority(Event event, int newPriority); + void setTime(Event event, long newTime); + boolean isCriticalEvent(Event event); + void dispatch(Event event, IBasicRobot robot, IRobotStatics statics, Graphics2D graphics); + byte getSerializationType(Event event); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenRulesHelper.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenRulesHelper.java new file mode 100644 index 0000000..85dec02 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenRulesHelper.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.security; + + +import robocode.BattleRules; + + +/** + * @author Pavel Savara (original) + */ +public interface IHiddenRulesHelper { + BattleRules createRules(int battlefieldWidth, int battlefieldHeight, int numRounds, double gunCoolingRate, long inactivityTime, boolean hideEnemyNames, int sentryBorderSizes); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenSpecificationHelper.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenSpecificationHelper.java new file mode 100644 index 0000000..05bc943 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenSpecificationHelper.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.security; + + +import robocode.control.RobotSpecification; + + +/** + * @author Pavel Savara (original) + */ +public interface IHiddenSpecificationHelper { + + RobotSpecification createSpecification(Object specification, String name, String author, String webpage, String version, String robocodeVersion, String jarFile, String fullClassName, String description); + Object getFileSpecification(RobotSpecification specification); + void setTeamName(RobotSpecification specification, String teamName); + String getTeamName(RobotSpecification specification); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenStatusHelper.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenStatusHelper.java new file mode 100644 index 0000000..8bff082 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IHiddenStatusHelper.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.security; + + +import robocode.RobotStatus; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public interface IHiddenStatusHelper { + RobotStatus createStatus(double energy, double x, double y, double bodyHeading, double gunHeading, double radarHeading, + double velocity, double bodyTurnRemaining, double radarTurnRemaining, double gunTurnRemaining, + double distanceRemaining, double gunHeat, int others, int numSentries, int roundNum, int numRounds, long time); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IThreadManagerBase.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IThreadManagerBase.java new file mode 100644 index 0000000..b69d1cd --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/IThreadManagerBase.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.security; + + +import java.io.FileOutputStream; +import java.io.IOException; + + +/** + * @author Pavel Savara (original) + */ +public interface IThreadManagerBase { + boolean isSafeThread(); + FileOutputStream createRobotFileStream(String fileName, boolean append) throws IOException; +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/SafeComponent.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/SafeComponent.java new file mode 100644 index 0000000..74d96a9 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/security/SafeComponent.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.security; + + +import java.awt.*; + + +/** + * @author Pavel Savara (original) + */ +@SuppressWarnings("serial") +public class SafeComponent extends Component { + // Dummy component used to preventing robots in accessing the real source component + private static Component safeEventComponent; + + public static Component getSafeEventComponent() { + if (safeEventComponent == null) { + safeEventComponent = new SafeComponent(); + } + return safeEventComponent; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/serialization/ISerializableHelper.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/serialization/ISerializableHelper.java new file mode 100644 index 0000000..97ef510 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/serialization/ISerializableHelper.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.serialization; + + +import java.nio.ByteBuffer; + + +/** + * @author Pavel Savara (original) + */ +public interface ISerializableHelper { + int sizeOf(RbSerializer serializer, Object object); + void serialize(RbSerializer serializer, ByteBuffer buffer, Object object); + Object deserialize(RbSerializer serializer, ByteBuffer buffer); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/serialization/RbSerializer.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/serialization/RbSerializer.java new file mode 100644 index 0000000..3a01c8e --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/serialization/RbSerializer.java @@ -0,0 +1,539 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.serialization; + + +import net.sf.robocode.core.ContainerBase; +import net.sf.robocode.io.Logger; +import net.sf.robocode.manager.IVersionManagerBase; +import net.sf.robocode.security.HiddenAccess; +import robocode.Event; + +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.*; +import java.util.HashMap; +import java.util.Map; + + +/** + * @author Pavel Savara (original) + */ +public final class RbSerializer { + public final static int SIZEOF_TYPEINFO = 1; + public final static int SIZEOF_BYTE = 1; + public final static int SIZEOF_BOOL = 1; + public final static int SIZEOF_CHAR = 2; + public final static int SIZEOF_INT = 4; + public final static int SIZEOF_LONG = 8; + public final static int SIZEOF_DOUBLE = 8; + + public final static byte TERMINATOR_TYPE = -1; + public final static byte ExecCommands_TYPE = 1; + public final static byte BulletCommand_TYPE = 2; + public final static byte TeamMessage_TYPE = 3; + public final static byte DebugProperty_TYPE = 4; + public final static byte ExecResults_TYPE = 5; + public final static byte RobotStatus_TYPE = 6; + public final static byte BulletStatus_TYPE = 7; + public final static byte BattleResults_TYPE = 8; + public final static byte Bullet_TYPE = 9; + public final static byte RobotStatics_TYPE = 10; + + public final static byte BattleEndedEvent_TYPE = 32; + public final static byte BulletHitBulletEvent_TYPE = 33; + public final static byte BulletHitEvent_TYPE = 34; + public final static byte BulletMissedEvent_TYPE = 35; + public final static byte DeathEvent_TYPE = 36; + public final static byte WinEvent_TYPE = 37; + public final static byte HitWallEvent_TYPE = 38; + public final static byte RobotDeathEvent_TYPE = 39; + public final static byte SkippedTurnEvent_TYPE = 40; + public final static byte ScannedRobotEvent_TYPE = 41; + public final static byte HitByBulletEvent_TYPE = 42; + public final static byte HitRobotEvent_TYPE = 43; + public final static byte KeyPressedEvent_TYPE = 44; + public final static byte KeyReleasedEvent_TYPE = 45; + public final static byte KeyTypedEvent_TYPE = 46; + public final static byte MouseClickedEvent_TYPE = 47; + public final static byte MouseDraggedEvent_TYPE = 48; + public final static byte MouseEnteredEvent_TYPE = 49; + public final static byte MouseExitedEvent_TYPE = 50; + public final static byte MouseMovedEvent_TYPE = 51; + public final static byte MousePressedEvent_TYPE = 52; + public final static byte MouseReleasedEvent_TYPE = 53; + public final static byte MouseWheelMovedEvent_TYPE = 54; + public final static byte RoundEndedEvent_TYPE = 55; + + private final static ISerializableHelper[] typeToHelper = new ISerializableHelper[256]; + private static Map, Byte> classToType = new HashMap, Byte>(); + private final static Charset charset; + private final CharsetEncoder encoder; + private final CharsetDecoder decoder; + + private static final int BYTE_ORDER = 0xC0DEDEA1; + private final int currentVersion; + + static { + charset = Charset.forName("UTF8"); // we will use it as UCS-2 + register(null, TERMINATOR_TYPE); // reserved for end of (list) element + } + + public RbSerializer() { + this.currentVersion = ContainerBase.getComponent(IVersionManagerBase.class).getVersionAsInt(); + encoder = charset.newEncoder(); + encoder.onMalformedInput(CodingErrorAction.REPORT); + encoder.onUnmappableCharacter(CodingErrorAction.REPLACE); + // throw away forst bom + ByteBuffer buffer = ByteBuffer.allocate(8); + + encoder.encode(CharBuffer.wrap("BOM"), buffer, false); + + decoder = charset.newDecoder(); + decoder.onMalformedInput(CodingErrorAction.REPORT); + decoder.onUnmappableCharacter(CodingErrorAction.REPLACE); + } + + public void serialize(OutputStream target, byte type, Object object) throws IOException { + int length = sizeOf(type, object); + + // header + ByteBuffer buffer = ByteBuffer.allocate(SIZEOF_INT + SIZEOF_INT + SIZEOF_INT); + + buffer.putInt(BYTE_ORDER); + buffer.putInt(currentVersion); + buffer.putInt(length); + target.write(buffer.array()); + + // body + buffer = ByteBuffer.allocate(length); + serialize(buffer, type, object); + if (buffer.remaining() != 0) { + throw new IOException("Serialization failed: bad size"); + } + target.write(buffer.array()); + } + + public ByteBuffer serialize(byte type, Object object) throws IOException { + int length = sizeOf(type, object); + + // header + ByteBuffer buffer = ByteBuffer.allocateDirect(SIZEOF_INT + SIZEOF_INT + SIZEOF_INT + length); + + buffer.putInt(BYTE_ORDER); + buffer.putInt(currentVersion); + buffer.putInt(length); + + // body + serialize(buffer, type, object); + if (buffer.remaining() != 0) { + throw new IOException("Serialization failed: bad size"); + } + return buffer; + } + + public ByteBuffer serializeToBuffer(ByteBuffer buffer, byte type, Object object) throws IOException { + int length = sizeOf(type, object); + + buffer.limit(SIZEOF_INT + SIZEOF_INT + SIZEOF_INT + length); + + buffer.putInt(BYTE_ORDER); + buffer.putInt(currentVersion); + buffer.putInt(length); + + // body + serialize(buffer, type, object); + if (buffer.remaining() != 0) { + throw new IOException("Serialization failed: bad size"); + } + return buffer; + } + + public Object deserialize(InputStream source) throws IOException { + // header + ByteBuffer buffer = ByteBuffer.allocate(SIZEOF_INT + SIZEOF_INT + SIZEOF_INT); + + fillBuffer(source, buffer); + buffer.flip(); + int bo = buffer.getInt(); + + if (bo != BYTE_ORDER) { + throw new IOException("Different byte order is not supported"); + } + int version = buffer.getInt(); + + if (version != currentVersion) { + throw new IOException("Version of data is not supported. We support only strong match"); + } + int length = buffer.getInt(); + + // body + buffer = ByteBuffer.allocate(length); + fillBuffer(source, buffer); + buffer.flip(); + final Object res = deserializeAny(buffer); + + if (buffer.remaining() != 0) { + throw new IOException("Serialization failed"); + } + return res; + } + + public Object deserialize(final ByteBuffer buffer) throws IOException { + int bo = buffer.getInt(); + + if (bo != BYTE_ORDER) { + throw new IOException("Different byte order is not supported"); + } + + int version = buffer.getInt(); + + if (version != currentVersion) { + throw new IOException("Version of data is not supported. We support only strong match"); + } + int length = buffer.getInt(); + + if (length != buffer.remaining()) { + throw new IOException("Wrong buffer size, " + length + "expected but got " + buffer.remaining()); + } + + // body + final Object res = deserializeAny(buffer); + + if (buffer.remaining() != 0) { + throw new IOException("Serialization failed"); + } + return res; + } + + public void serialize(ByteBuffer buffer, byte type, Object object) { + ISerializableHelper helper = getHelper(type); + + // FOR-DEBUG int expect = sizeOf(type, object) + buffer.position(); + + if (object != null) { + buffer.put(type); + helper.serialize(this, buffer, object); + } else { + buffer.put(TERMINATOR_TYPE); + } + // FOR-DEBUG if (expect != buffer.position()) { + // FOR-DEBUG throw new Error("Bad size"); + // FOR-DEBUG } + } + + public void serialize(ByteBuffer buffer, String data) { + if (data == null) { + buffer.putInt(-1); + } else { + ByteBuffer slice = encode(data); + + buffer.putInt(slice.limit()); + buffer.put(slice); + } + } + + public void serialize(ByteBuffer buffer, byte[] data) { + if (data == null) { + buffer.putInt(-1); + } else { + buffer.putInt(data.length); + buffer.put(data); + } + } + + public void serialize(ByteBuffer buffer, int[] data) { + if (data == null) { + buffer.putInt(-1); + } else { + buffer.putInt(data.length); + for (int aData : data) { + buffer.putInt(aData); + } + } + } + + public void serialize(ByteBuffer buffer, char[] data) { + if (data == null) { + buffer.putInt(-1); + } else { + buffer.putInt(data.length); + for (char aData : data) { + buffer.putChar(aData); + } + } + } + + public void serialize(ByteBuffer buffer, double[] data) { + if (data == null) { + buffer.putInt(-1); + } else { + buffer.putInt(data.length); + for (double aData : data) { + buffer.putDouble(aData); + } + } + } + + public void serialize(ByteBuffer buffer, float[] data) { + if (data == null) { + buffer.putInt(-1); + } else { + buffer.putInt(data.length); + for (float aData : data) { + buffer.putFloat(aData); + } + } + } + + public void serialize(ByteBuffer buffer, boolean value) { + buffer.put((byte) (value ? 1 : 0)); + } + + public void serialize(ByteBuffer buffer, double value) { + buffer.putDouble(value); + } + + public void serialize(ByteBuffer buffer, char value) { + buffer.putChar(value); + } + + public void serialize(ByteBuffer buffer, long value) { + buffer.putLong(value); + } + + public void serialize(ByteBuffer buffer, int value) { + buffer.putInt(value); + } + + public void serialize(ByteBuffer buffer, Event event) { + final byte type = HiddenAccess.getSerializationType(event); + + serialize(buffer, type, event); + } + + public Object deserializeAny(ByteBuffer buffer) { + final byte type = buffer.get(); + + if (type == TERMINATOR_TYPE) { + return null; + } + return getHelper(type).deserialize(this, buffer); + } + + public String deserializeString(ByteBuffer buffer) { + final int bytes = buffer.getInt(); + + if (bytes == -1) { + return null; + } + final ByteBuffer slice = buffer.slice(); + + slice.limit(bytes); + final String res; + + try { + res = decoder.decode(slice).toString(); + } catch (CharacterCodingException e) { + throw new Error("Bad character", e); + } + buffer.position(buffer.position() + bytes); + return res; + } + + public byte[] deserializeBytes(ByteBuffer buffer) { + final int len = buffer.getInt(); + + if (len == -1) { + return null; + } + byte[] res = new byte[len]; + + buffer.get(res); + return res; + } + + public int[] deserializeIntegers(ByteBuffer buffer) { + final int len = buffer.getInt(); + + if (len == -1) { + return null; + } + int[] res = new int[len]; + + for (int i = 0; i < len; i++) { + res[i] = buffer.getInt(); + } + return res; + } + + public float[] deserializeFloats(ByteBuffer buffer) { + final int len = buffer.getInt(); + + if (len == -1) { + return null; + } + float[] res = new float[len]; + + for (int i = 0; i < len; i++) { + res[i] = buffer.getFloat(); + } + return res; + } + + public char[] deserializeChars(ByteBuffer buffer) { + final int len = buffer.getInt(); + + if (len == -1) { + return null; + } + char[] res = new char[len]; + + for (int i = 0; i < len; i++) { + res[i] = buffer.getChar(); + } + return res; + } + + public double[] deserializeDoubles(ByteBuffer buffer) { + final int len = buffer.getInt(); + + if (len == -1) { + return null; + } + double[] res = new double[len]; + + for (int i = 0; i < len; i++) { + res[i] = buffer.getDouble(); + } + return res; + } + + public boolean deserializeBoolean(ByteBuffer buffer) { + return buffer.get() != 0; + } + + public char deserializeChar(ByteBuffer buffer) { + return buffer.getChar(); + } + + public int deserializeInt(ByteBuffer buffer) { + return buffer.getInt(); + } + + public Float deserializeFloat(ByteBuffer buffer) { + return buffer.getFloat(); + } + + public double deserializeDouble(ByteBuffer buffer) { + return buffer.getDouble(); + } + + public long deserializeLong(ByteBuffer buffer) { + return buffer.getLong(); + } + + public int sizeOf(String data) { + return (data == null) ? SIZEOF_INT : SIZEOF_INT + encode(data).limit(); + } + + public int sizeOf(byte[] data) { + return (data == null) ? SIZEOF_INT : SIZEOF_INT + data.length; + } + + public int sizeOf(byte type, Object object) { + return getHelper(type).sizeOf(this, object); + } + + public int sizeOf(Event event) { + return sizeOf(HiddenAccess.getSerializationType(event), event); + } + + private ISerializableHelper getHelper(byte type) { + final ISerializableHelper helper = typeToHelper[type]; + + if (helper == null) { + throw new Error("Unknownd or unsupported data type"); + } + return helper; + } + + private ByteBuffer encode(String data) { + final ByteBuffer slice = ByteBuffer.allocate(data.length() * 3); + + encoder.encode(CharBuffer.wrap(data), slice, false); + slice.flip(); + return slice; + } + + private void fillBuffer(InputStream source, ByteBuffer buffer) throws IOException { + int res; + + do { + res = source.read(buffer.array(), buffer.position(), buffer.remaining()); + if (res == -1) { + throw new IOException("Unexpected EOF"); + } + buffer.position(buffer.position() + res); + } while (buffer.remaining() != 0); + } + + public static void register(Class realClass, byte type) { + try { + if (realClass != null) { + Method method = realClass.getDeclaredMethod("createHiddenSerializer"); + + method.setAccessible(true); + ISerializableHelper helper = (ISerializableHelper) method.invoke(null); + + method.setAccessible(false); + typeToHelper[type] = helper; + classToType.put(realClass, type); + } + } catch (NoSuchMethodException e) { + Logger.logError(e); + } catch (InvocationTargetException e) { + Logger.logError(e); + } catch (IllegalAccessException e) { + Logger.logError(e); + } + } + + public static ByteBuffer serializeToBuffer(Object src) throws IOException { + RbSerializer rbs = new RbSerializer(); + final Byte type = classToType.get(src.getClass()); + + return rbs.serialize(type, src); + } + + @SuppressWarnings({ "unchecked"}) + public static T deserializeFromBuffer(ByteBuffer buffer) throws IOException { + RbSerializer rbs = new RbSerializer(); + final Object res = rbs.deserialize(buffer); + + return (T) res; + } + + public static Object deepCopy(byte type, Object src) { + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + RbSerializer rbs = new RbSerializer(); + + try { + rbs.serialize(out, type, src); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + + return rbs.deserialize(in); + } catch (IOException e) { + Logger.logError(e); + return null; + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/util/StringUtil.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/util/StringUtil.java new file mode 100644 index 0000000..4feb2e3 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/util/StringUtil.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.util; + + +/** + * Class for utilizing strings. + * + * @author Flemming N. Larsen (original) + */ +public final class StringUtil { + + /** + * Returns a string encoded into Basic Latin, where characters that cannot + * be represented in Basic Latin are represented as encoded unicode characters. + * + * @param sequence + * @return + */ + public static String toBasicLatin(CharSequence sequence) { + StringBuilder out = new StringBuilder(); + + for (int i = 0; i < sequence.length(); i++) { + char ch = sequence.charAt(i); + + if (Character.UnicodeBlock.of(ch) == Character.UnicodeBlock.BASIC_LATIN) { + out.append(ch); + } else { + int codepoint = Character.codePointAt(sequence, i); + + // Handle supplementary range chars + i += Character.charCount(codepoint) - 1; + // Emit entity as a unicode character + out.append(String.format("\\u%1$04X", codepoint)); + } + } + return out.toString(); + } + + /** + * Returns the number of occurrences of a specific character. + * + * @param str is the string containing the character to look for. + * @param chr is the character we look for. + * @return the number of occurrences. + */ + public static int countChar(String str, char chr) { + int count = 0; + for (char c : str.toCharArray()) { + if (c == chr) { + count++; + } + } + return count; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/util/UrlUtil.java b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/util/UrlUtil.java new file mode 100644 index 0000000..e2c4372 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/net/sf/robocode/util/UrlUtil.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.util; + + +/** + * Utility class used for working on URLs. + * + * @author Flemming N. Larsen (original) + */ +public class UrlUtil { + + /** + * Removes a file extension from a string containing a file name, e.g. the string "filename.ext" would become using + * this method "filename". + * + * @param fileName is a string containing a file name with an extension to remove. + * @return a new string where the file extension has been removed from the file name. + * If no extension is found, the input file name is returned. + */ + public static String removeFileExtension(String fileName) { + if (fileName != null) { + int index = fileName.lastIndexOf('.'); + if (index > 0 && index < (fileName.length() - 1)) { + return fileName.substring(0, index); + } + } + return fileName; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/AdvancedRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/AdvancedRobot.java new file mode 100644 index 0000000..e391ceb --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/AdvancedRobot.java @@ -0,0 +1,2027 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import robocode.robotinterfaces.IAdvancedEvents; +import robocode.robotinterfaces.IAdvancedRobot; +import robocode.robotinterfaces.peer.IAdvancedRobotPeer; + +import java.io.File; +import java.util.Vector; + + +/** + * A more advanced type of robot than Robot that allows non-blocking calls, + * custom events, and writes to the filesystem. + *

+ * This call returns both positive and negative values. Positive values + * means that the robot is currently moving forwards. Negative values means + * that the robot is currently moving backwards. If the returned value is 0, + * the robot currently stands still. + * + * @return the distance remaining in the robot's current move measured in + * pixels. + * @see #getTurnRemaining() getTurnRemaining() + * @see #getTurnRemainingRadians() getTurnRemainingRadians() + * @see #getGunTurnRemaining() getGunTurnRemaining() + * @see #getGunTurnRemainingRadians() getGunTurnRemainingRadians() + * @see #getRadarTurnRemaining() getRadarTurnRemaining() + * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() + */ + public double getDistanceRemaining() { + if (peer != null) { + return peer.getDistanceRemaining(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the angle remaining in the robots's turn, in degrees. + *

+ * This call returns both positive and negative values. Positive values + * means that the robot is currently turning to the right. Negative values + * means that the robot is currently turning to the left. If the returned + * value is 0, the robot is currently not turning. + * + * @return the angle remaining in the robots's turn, in degrees + * @see #getTurnRemainingRadians() getTurnRemainingRadians() + * @see #getDistanceRemaining() getDistanceRemaining() + * @see #getGunTurnRemaining() getGunTurnRemaining() + * @see #getGunTurnRemainingRadians() getGunTurnRemainingRadians() + * @see #getRadarTurnRemaining() getRadarTurnRemaining() + * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() + */ + public double getTurnRemaining() { + if (peer != null) { + return Math.toDegrees(peer.getBodyTurnRemaining()); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the angle remaining in the gun's turn, in degrees. + *

+ * This call returns both positive and negative values. Positive values + * means that the gun is currently turning to the right. Negative values + * means that the gun is currently turning to the left. If the returned + * value is 0, the gun is currently not turning. + * + * @return the angle remaining in the gun's turn, in degrees + * @see #getGunTurnRemainingRadians() getGunTurnRemainingRadians() + * @see #getDistanceRemaining() getDistanceRemaining() + * @see #getTurnRemaining() getTurnRemaining() + * @see #getTurnRemainingRadians() getTurnRemainingRadians() + * @see #getRadarTurnRemaining() getRadarTurnRemaining() + * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() + */ + public double getGunTurnRemaining() { + if (peer != null) { + return Math.toDegrees(peer.getGunTurnRemaining()); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the angle remaining in the radar's turn, in degrees. + *

+ * This call returns both positive and negative values. Positive values + * means that the radar is currently turning to the right. Negative values + * means that the radar is currently turning to the left. If the returned + * value is 0, the radar is currently not turning. + * + * @return the angle remaining in the radar's turn, in degrees + * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() + * @see #getDistanceRemaining() getDistanceRemaining() + * @see #getGunTurnRemaining() getGunTurnRemaining() + * @see #getGunTurnRemainingRadians() getGunTurnRemainingRadians() + * @see #getRadarTurnRemaining() getRadarTurnRemaining() + * @see #getRadarTurnRemainingRadians() getRadarTurnRemainingRadians() + */ + public double getRadarTurnRemaining() { + if (peer != null) { + return Math.toDegrees(peer.getRadarTurnRemaining()); + } + uninitializedException(); + return 0; // never called + } + + /** + * Sets the robot to move ahead (forward) by distance measured in pixels + * when the next execution takes place. + *

+ * This call returns immediately, and will not execute until you call + * {@link #execute()} or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot is set to move ahead, and negative + * values means that the robot is set to move back. If 0 is given as input, + * the robot will stop its movement, but will have to decelerate + * till it stands still, and will thus not be able to stop its movement + * immediately, but eventually. + *

+ * Example: + *

+	 *   // Set the robot to move 50 pixels ahead
+	 *   setAhead(50);
+	 *
+	 *   // Set the robot to move 100 pixels back
+	 *   // (overrides the previous order)
+	 *   setAhead(-100);
+	 *
+	 *   ...
+	 *   // Executes the last setAhead()
+	 *   execute();
+	 * 
+ * + * @param distance the distance to move measured in pixels. + * If {@code distance} > 0 the robot is set to move ahead. + * If {@code distance} < 0 the robot is set to move back. + * If {@code distance} = 0 the robot is set to stop its movement. + * @see #ahead(double) ahead(double) + * @see #back(double) back(double) + * @see #setBack(double) + */ + public void setAhead(double distance) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setMove(distance); + } else { + uninitializedException(); + } + } + + /** + * Sets the robot to move back by distance measured in pixels when the next + * execution takes place. + *

+ * This call returns immediately, and will not execute until you call + * {@link #execute()} or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot is set to move back, and negative + * values means that the robot is set to move ahead. If 0 is given as input, + * the robot will stop its movement, but will have to decelerate + * till it stands still, and will thus not be able to stop its movement + * immediately, but eventually. + *

+ * Example: + *

+	 *   // Set the robot to move 50 pixels back
+	 *   setBack(50);
+	 *
+	 *   // Set the robot to move 100 pixels ahead
+	 *   // (overrides the previous order)
+	 *   setBack(-100);
+	 *
+	 *   ...
+	 *   // Executes the last setBack()
+	 *   execute();
+	 * 
+ * + * @param distance the distance to move measured in pixels. + * If {@code distance} > 0 the robot is set to move back. + * If {@code distance} < 0 the robot is set to move ahead. + * If {@code distance} = 0 the robot is set to stop its movement. + * @see #back(double) back(double) + * @see #ahead(double) ahead(double) + * @see #setAhead(double) + */ + public void setBack(double distance) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setMove(-distance); + } else { + uninitializedException(); + } + } + + /** + * Sets the robot's body to turn left by degrees when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's body is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Set the robot to turn 180 degrees to the left
+	 *   setTurnLeft(180);
+	 *
+	 *   // Set the robot to turn 90 degrees to the right instead of left
+	 *   // (overrides the previous order)
+	 *   setTurnLeft(-90);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnLeft()
+	 *   execute();
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's body to the left. + * If {@code degrees} > 0 the robot is set to turn left. + * If {@code degrees} < 0 the robot is set to turn right. + * If {@code degrees} = 0 the robot is set to stop turning. + * @see #setTurnLeftRadians(double) setTurnLeftRadians(double) + * @see #turnLeft(double) turnLeft(double) + * @see #turnLeftRadians(double) turnLeftRadians(double) + * @see #turnRight(double) turnRight(double) + * @see #turnRightRadians(double) turnRightRadians(double) + * @see #setTurnRight(double) setTurnRight(double) + * @see #setTurnRightRadians(double) setTurnRightRadians(double) + */ + public void setTurnLeft(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnBody(-Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Sets the robot's body to turn right by degrees when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's body is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Set the robot to turn 180 degrees to the right
+	 *   setTurnRight(180);
+	 *
+	 *   // Set the robot to turn 90 degrees to the left instead of right
+	 *   // (overrides the previous order)
+	 *   setTurnRight(-90);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnRight()
+	 *   execute();
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's body to the right. + * If {@code degrees} > 0 the robot is set to turn right. + * If {@code degrees} < 0 the robot is set to turn left. + * If {@code degrees} = 0 the robot is set to stop turning. + * @see #setTurnRightRadians(double) setTurnRightRadians(double) + * @see #turnRight(double) turnRight(double) + * @see #turnRightRadians(double) turnRightRadians(double) + * @see #turnLeft(double) turnLeft(double) + * @see #turnLeftRadians(double) turnLeftRadians(double) + * @see #setTurnLeft(double) setTurnLeft(double) + * @see #setTurnLeftRadians(double) setTurnLeftRadians(double) + */ + public void setTurnRight(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnBody(Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Sets the gun to fire a bullet when the next execution takes place. + * The bullet will travel in the direction the gun is pointing. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * The specified bullet power is an amount of energy that will be taken from + * the robot's energy. Hence, the more power you want to spend on the + * bullet, the more energy is taken from your robot. + *

+ * The bullet will do (4 * power) damage if it hits another robot. If power + * is greater than 1, it will do an additional 2 * (power - 1) damage. + * You will get (3 * power) back if you hit the other robot. You can call + * Rules#getBulletDamage(double)} for getting the damage that a + * bullet with a specific bullet power will do. + *

+ * The specified bullet power should be between + * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. + *

+ * Note that the gun cannot fire if the gun is overheated, meaning that + * {@link #getGunHeat()} returns a value > 0. + *

+ * An event is generated when the bullet hits a robot, wall, or another + * bullet. + *

+ * Example: + *

+	 *   // Fire a bullet with maximum power if the gun is ready
+	 *   if (getGunHeat() == 0) {
+	 *       setFire(Rules.MAX_BULLET_POWER);
+	 *   }
+	 *   ...
+	 *   execute();
+	 * 
+ * + * @param power the amount of energy given to the bullet, and subtracted + * from the robot's energy. + * @see #setFireBullet(double) + * @see #fire(double) fire(double) + * @see #fireBullet(double) fireBullet(double) + * @see #getGunHeat() getGunHeat() + * @see #getGunCoolingRate() getGunCoolingRate() + * @see #onBulletHit(BulletHitEvent) onBulletHit(BulletHitEvent) + * @see #onBulletHitBullet(BulletHitBulletEvent) onBulletHitBullet(BulletHitBulletEvent) + * @see #onBulletMissed(BulletMissedEvent) onBulletMissed(BulletMissedEvent) + */ + public void setFire(double power) { + if (peer != null) { + peer.setFire(power); + } else { + uninitializedException(); + } + } + + /** + * Sets the gun to fire a bullet when the next execution takes place. + * The bullet will travel in the direction the gun is pointing. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * The specified bullet power is an amount of energy that will be taken from + * the robot's energy. Hence, the more power you want to spend on the + * bullet, the more energy is taken from your robot. + *

+ * The bullet will do (4 * power) damage if it hits another robot. If power + * is greater than 1, it will do an additional 2 * (power - 1) damage. + * You will get (3 * power) back if you hit the other robot. You can call + * {@link Rules#getBulletDamage(double)} for getting the damage that a + * bullet with a specific bullet power will do. + *

+ * The specified bullet power should be between + * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. + *

+ * Note that the gun cannot fire if the gun is overheated, meaning that + * {@link #getGunHeat()} returns a value > 0. + *

+ * A event is generated when the bullet hits a robot + * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another + * bullet ({@link BulletHitBulletEvent}). + *

+ * Example: + *

+	 *   Bullet bullet = null;
+	 * 

+ * // Fire a bullet with maximum power if the gun is ready + * if (getGunHeat() == 0) { + * bullet = setFireBullet(Rules.MAX_BULLET_POWER); + * } + * ... + * execute(); + * ... + * // Get the velocity of the bullet + * if (bullet != null) { + * double bulletVelocity = bullet.getVelocity(); + * } + *

+ * + * @param power the amount of energy given to the bullet, and subtracted + * from the robot's energy. + * @return a {@link Bullet} that contains information about the bullet if it + * was actually fired, which can be used for tracking the bullet after it + * has been fired. If the bullet was not fired, {@code null} is returned. + * @see #setFire(double) + * @see Bullet + * @see #fire(double) fire(double) + * @see #fireBullet(double) fireBullet(double) + * @see #getGunHeat() getGunHeat() + * @see #getGunCoolingRate() getGunCoolingRate() + * @see #onBulletHit(BulletHitEvent) onBulletHit(BulletHitEvent) + * @see #onBulletHitBullet(BulletHitBulletEvent) onBulletHitBullet(BulletHitBulletEvent) + * @see #onBulletMissed(BulletMissedEvent) onBulletMissed(BulletMissedEvent) + */ + public Bullet setFireBullet(double power) { + if (peer != null) { + return peer.setFire(power); + } + uninitializedException(); + return null; + } + + /** + * Registers a custom event to be called when a condition is met. + * When you are finished with your condition or just want to remove it you + * must call {@link #removeCustomEvent(Condition)}. + *

+ * Example: + *

+	 *   // Create the condition for our custom event
+	 *   Condition triggerHitCondition = new Condition("triggerhit") {
+	 *       public boolean test() {
+	 *           return (getEnergy() <= trigger);
+	 *       }
+	 *   }
+	 *
+	 *   // Add our custom event based on our condition
+	 *   addCustomEvent(triggerHitCondition);
+	 * 
+ * + * @param condition the condition that must be met. + * @throws NullPointerException if the condition parameter has been set to + * {@code null}. + * @see Condition + * @see #removeCustomEvent(Condition) + */ + public void addCustomEvent(Condition condition) { + if (condition == null) { + throw new NullPointerException("the condition cannot be null"); + } + if (peer != null) { + ((IAdvancedRobotPeer) peer).addCustomEvent(condition); + } else { + uninitializedException(); + } + } + + /** + * Removes a custom event that was previously added by calling + * {@link #addCustomEvent(Condition)}. + *

+ * Example: + *

+	 *   // Create the condition for our custom event
+	 *   Condition triggerHitCondition = new Condition("triggerhit") {
+	 *       public boolean test() {
+	 *           return (getEnergy() <= trigger);
+	 *       }
+	 *   }
+	 *
+	 *   // Add our custom event based on our condition
+	 *   addCustomEvent(triggerHitCondition);
+	 *   ...
+	 *   do something with your robot
+	 *   ...
+	 *   // Remove the custom event based on our condition
+	 *   removeCustomEvent(triggerHitCondition);
+	 * 
+ * + * @param condition the condition that was previous added and that must be + * removed now. + * @throws NullPointerException if the condition parameter has been set to + * {@code null}. + * @see Condition + * @see #addCustomEvent(Condition) + */ + public void removeCustomEvent(Condition condition) { + if (condition == null) { + throw new NullPointerException("the condition cannot be null"); + } + if (peer != null) { + ((IAdvancedRobotPeer) peer).removeCustomEvent(condition); + } else { + uninitializedException(); + } + } + + /** + * Clears out any pending events in the robot's event queue immediately. + * + * @see #getAllEvents() + */ + public void clearAllEvents() { + if (peer != null) { + ((IAdvancedRobotPeer) peer).clearAllEvents(); + } else { + uninitializedException(); + } + } + + /** + * Executes any pending actions, or continues executing actions that are + * in process. This call returns after the actions have been started. + *

+ * Note that advanced robots must call this function in order to + * execute pending set* calls like e.g. {@link #setAhead(double)}, + * {@link #setFire(double)}, {@link #setTurnLeft(double)} etc. Otherwise, + * these calls will never get executed. + *

+ * In this example the robot will move while turning: + *

+	 *   setTurnRight(90);
+	 *   setAhead(100);
+	 *   execute();
+	 *
+	 *   while (getDistanceRemaining() > 0 && getTurnRemaining() > 0) {
+	 *       execute();
+	 *   }
+	 * 
+ */ + public void execute() { + if (peer != null) { + peer.execute(); + } else { + uninitializedException(); + } + } + + /** + * Returns a vector containing all events currently in the robot's queue. + * You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (Event event : getAllEvents()) {
+	 *       if (event instanceof HitRobotEvent) {
+	 *           // do something with the event
+	 *       } else if (event instanceof HitByBulletEvent) {
+	 *           // do something with the event
+	 *       }
+	 *   }
+	 * 
+ * + * @return a vector containing all events currently in the robot's queue + * @see Event + * @see #clearAllEvents() + * @see #getStatusEvents() + * @see #getScannedRobotEvents() + * @see #getBulletHitEvents() + * @see #getBulletMissedEvents() + * @see #getBulletHitBulletEvents() + * @see #getRobotDeathEvents() + */ + public Vector getAllEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getAllEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a vector containing all BulletHitBulletEvents currently in the + * robot's queue. You might, for example, call this while processing another + * event. + *

+ * Example: + *

+	 *   for (BulletHitBulletEvent event : getBulletHitBulletEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all BulletHitBulletEvents currently in the + * robot's queue + * @see #onBulletHitBullet(BulletHitBulletEvent) onBulletHitBullet(BulletHitBulletEvent) + * @see BulletHitBulletEvent + * @see #getAllEvents() + */ + public Vector getBulletHitBulletEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getBulletHitBulletEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a vector containing all BulletHitEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (BulletHitEvent event: getBulletHitEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all BulletHitEvents currently in the robot's + * queue + * @see #onBulletHit(BulletHitEvent) onBulletHit(BulletHitEvent) + * @see BulletHitEvent + * @see #getAllEvents() + */ + public Vector getBulletHitEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getBulletHitEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a vector containing all BulletMissedEvents currently in the + * robot's queue. You might, for example, call this while processing another + * event. + *

+ * Example: + *

+	 *   for (BulletMissedEvent event : getBulletMissedEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all BulletMissedEvents currently in the + * robot's queue + * @see #onBulletMissed(BulletMissedEvent) onBulletMissed(BulletMissedEvent) + * @see BulletMissedEvent + * @see #getAllEvents() + */ + public Vector getBulletMissedEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getBulletMissedEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a file representing a data directory for the robot, which can be + * written to using {@link RobocodeFileOutputStream} or + * {@link RobocodeFileWriter}. + *

+ * The system will automatically create the directory for you, so you do not + * need to create it by yourself. + * + * @return a file representing the data directory for your robot + * @see #getDataFile(String) + * @see RobocodeFileOutputStream + * @see RobocodeFileWriter + */ + public File getDataDirectory() { + if (peer != null) { + return ((IAdvancedRobotPeer) peer).getDataDirectory(); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a file in your data directory that you can write to using + * {@link RobocodeFileOutputStream} or {@link RobocodeFileWriter}. + *

+ * The system will automatically create the directory for you, so you do not + * need to create it by yourself. + *

+ * Please notice that the max. size of your data file is set to 200000 + * (~195 KB). + *

+ * See the {@code sample.SittingDuck} to see an example of how to use this + * method. + * + * @param filename the file name of the data file for your robot + * @return a file representing the data file for your robot or null if the data + * file could not be created due to an error. + * @see #getDataDirectory() + * @see RobocodeFileOutputStream + * @see RobocodeFileWriter + */ + public File getDataFile(String filename) { + if (peer != null) { + return ((IAdvancedRobotPeer) peer).getDataFile(filename); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns the data quota available in your data directory, i.e. the amount + * of bytes left in the data directory for the robot. + * + * @return the amount of bytes left in the robot's data directory + * @see #getDataDirectory() + * @see #getDataFile(String) + */ + public long getDataQuotaAvailable() { + if (peer != null) { + return ((IAdvancedRobotPeer) peer).getDataQuotaAvailable(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the current priority of a class of events. + * An event priority is a value from 0 - 99. The higher value, the higher + * priority. + *

+ * Example: + *

+	 *   int myHitRobotPriority = getEventPriority("HitRobotEvent");
+	 * 
+ *

+ * The default priorities are, from highest to lowest: + *

+	 *   {@link RoundEndedEvent}:      100 (reserved)
+	 *   {@link BattleEndedEvent}:     100 (reserved)
+	 *   {@link WinEvent}:             100 (reserved)
+	 *   {@link SkippedTurnEvent}:     100 (reserved)
+	 *   {@link StatusEvent}:           99
+	 *   Key and mouse events:  98
+	 *   {@link CustomEvent}:           80 (default value)
+	 *   {@link MessageEvent}:          75
+	 *   {@link RobotDeathEvent}:       70
+	 *   {@link BulletMissedEvent}:     60
+	 *   {@link BulletHitBulletEvent}:  55
+	 *   {@link BulletHitEvent}:        50
+	 *   {@link HitByBulletEvent}:      40
+	 *   {@link HitWallEvent}:          30
+	 *   {@link HitRobotEvent}:         20
+	 *   {@link ScannedRobotEvent}:     10
+	 *   {@link PaintEvent}:             5
+	 *   {@link DeathEvent}:            -1 (reserved)
+	 * 
+ * + * @param eventClass the name of the event class (string) + * @return the current priority of a class of events + * @see #setEventPriority(String, int) + */ + public int getEventPriority(String eventClass) { + if (peer != null) { + return ((IAdvancedRobotPeer) peer).getEventPriority(eventClass); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns a vector containing all HitByBulletEvents currently in the + * robot's queue. You might, for example, call this while processing + * another event. + *

+ * Example: + *

+	 *   for (HitByBulletEvent event : getHitByBulletEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all HitByBulletEvents currently in the + * robot's queue + * @see #onHitByBullet(HitByBulletEvent) onHitByBullet(HitByBulletEvent) + * @see HitByBulletEvent + * @see #getAllEvents() + */ + public Vector getHitByBulletEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getHitByBulletEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a vector containing all HitRobotEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (HitRobotEvent event : getHitRobotEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all HitRobotEvents currently in the robot's + * queue + * @see #onHitRobot(HitRobotEvent) onHitRobot(HitRobotEvent) + * @see HitRobotEvent + * @see #getAllEvents() + */ + public Vector getHitRobotEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getHitRobotEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a vector containing all HitWallEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (HitWallEvent event : getHitWallEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all HitWallEvents currently in the robot's + * queue + * @see #onHitWall(HitWallEvent) onHitWall(HitWallEvent) + * @see HitWallEvent + * @see #getAllEvents() + */ + public Vector getHitWallEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getHitWallEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a vector containing all RobotDeathEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (RobotDeathEvent event : getRobotDeathEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all RobotDeathEvents currently in the robot's + * queue + * @see #onRobotDeath(RobotDeathEvent) onRobotDeath(RobotDeathEvent) + * @see RobotDeathEvent + * @see #getAllEvents() + */ + public Vector getRobotDeathEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getRobotDeathEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a vector containing all ScannedRobotEvents currently in the + * robot's queue. You might, for example, call this while processing another + * event. + *

+ * Example: + *

+	 *   for (ScannedRobotEvent event : getScannedRobotEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all ScannedRobotEvents currently in the + * robot's queue + * @see #onScannedRobot(ScannedRobotEvent) onScannedRobot(ScannedRobotEvent) + * @see ScannedRobotEvent + * @see #getAllEvents() + */ + public Vector getScannedRobotEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getScannedRobotEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns a vector containing all StatusEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (StatusEvent event : getStatusEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all StatusEvents currently in the robot's queue + * @see #onStatus(StatusEvent) onStatus(StatusEvent) + * @see StatusEvent + * @see #getAllEvents() + * @since 1.6.1 + */ + public Vector getStatusEvents() { + if (peer != null) { + return new Vector(((IAdvancedRobotPeer) peer).getStatusEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Checks if the gun is set to adjust for the robot turning, i.e. to turn + * independent from the robot's body turn. + *

+ * This call returns {@code true} if the gun is set to turn independent of + * the turn of the robot's body. Otherwise, {@code false} is returned, + * meaning that the gun is set to turn with the robot's body turn. + * + * @return {@code true} if the gun is set to turn independent of the robot + * turning; {@code false} if the gun is set to turn with the robot + * turning + * @see #setAdjustGunForRobotTurn(boolean) setAdjustGunForRobotTurn(boolean) + * @see #isAdjustRadarForRobotTurn() + * @see #isAdjustRadarForGunTurn() + */ + public boolean isAdjustGunForRobotTurn() { + if (peer != null) { + return ((IAdvancedRobotPeer) peer).isAdjustGunForBodyTurn(); + } + uninitializedException(); + return false; // never called + } + + /** + * Checks if the radar is set to adjust for the robot turning, i.e. to turn + * independent from the robot's body turn. + *

+ * This call returns {@code true} if the radar is set to turn independent of + * the turn of the robot. Otherwise, {@code false} is returned, meaning that + * the radar is set to turn with the robot's turn. + * + * @return {@code true} if the radar is set to turn independent of the robot + * turning; {@code false} if the radar is set to turn with the robot + * turning + * @see #setAdjustRadarForRobotTurn(boolean) setAdjustRadarForRobotTurn(boolean) + * @see #isAdjustGunForRobotTurn() + * @see #isAdjustRadarForGunTurn() + */ + public boolean isAdjustRadarForRobotTurn() { + if (peer != null) { + return ((IAdvancedRobotPeer) peer).isAdjustRadarForBodyTurn(); + } + uninitializedException(); + return false; // never called + } + + /** + * Checks if the radar is set to adjust for the gun turning, i.e. to turn + * independent from the gun's turn. + *

+ * This call returns {@code true} if the radar is set to turn independent of + * the turn of the gun. Otherwise, {@code false} is returned, meaning that + * the radar is set to turn with the gun's turn. + * + * @return {@code true} if the radar is set to turn independent of the gun + * turning; {@code false} if the radar is set to turn with the gun + * turning + * @see #setAdjustRadarForGunTurn(boolean) setAdjustRadarForGunTurn(boolean) + * @see #isAdjustGunForRobotTurn() + * @see #isAdjustRadarForRobotTurn() + */ + public boolean isAdjustRadarForGunTurn() { + if (peer != null) { + return ((IAdvancedRobotPeer) peer).isAdjustRadarForGunTurn(); + } + uninitializedException(); + return false; // never called + } + + /** + * {@inheritDoc} + */ + public void onCustomEvent(CustomEvent event) {} + + /** + * Sets the priority of a class of events. + *

+ * Events are sent to the onXXX handlers in order of priority. + * Higher priority events can interrupt lower priority events. + * For events with the same priority, newer events are always sent first. + * Valid priorities are 0 - 99, where 100 is reserved and 80 is the default + * priority. + *

+ * Example: + *

+	 *   setEventPriority("RobotDeathEvent", 15);
+	 * 
+ *

+ * The default priorities are, from highest to lowest: + *

+	 * 	 {@link WinEvent}:             100 (reserved)
+	 * 	 {@link SkippedTurnEvent}:     100 (reserved)
+	 *   {@link StatusEvent}:           99
+	 * 	 {@link CustomEvent}:           80
+	 * 	 {@link MessageEvent}:          75
+	 * 	 {@link RobotDeathEvent}:       70
+	 * 	 {@link BulletMissedEvent}:     60
+	 * 	 {@link BulletHitBulletEvent}:  55
+	 * 	 {@link BulletHitEvent}:        50
+	 * 	 {@link HitByBulletEvent}:      40
+	 * 	 {@link HitWallEvent}:          30
+	 * 	 {@link HitRobotEvent}:         20
+	 * 	 {@link ScannedRobotEvent}:     10
+	 *   {@link PaintEvent}:             5
+	 * 	 {@link DeathEvent}:            -1 (reserved)
+	 * 
+ *

+ * Note that you cannot change the priority for events with the special + * priority value -1 or 100 (reserved) as these event are system events. + * Also note that you cannot change the priority of CustomEvent. + * Instead you must change the priority of the condition(s) for your custom + * event(s). + * + * @param eventClass the name of the event class (string) to set the + * priority for + * @param priority the new priority for that event class + * @see #getEventPriority(String) + * @see #setInterruptible(boolean) + * @since 1.5, the priority of DeathEvent was changed from 100 to -1 in + * order to let robots process pending events on its event queue before + * it dies. When the robot dies, it will not be able to process events. + */ + public void setEventPriority(String eventClass, int priority) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setEventPriority(eventClass, priority); + } else { + uninitializedException(); + } + } + + /** + * Call this during an event handler to allow new events of the same + * priority to restart the event handler. + *

+ *

Example: + *

+	 *   public void onScannedRobot(ScannedRobotEvent e) {
+	 *       fire(1);
+	 *       setInterruptible(true);
+	 *       ahead(100); // If you see a robot while moving ahead,
+	 *                   // this handler will start from the top
+	 *                   // Without setInterruptible(true), we wouldn't
+	 *                   // receive scan events at all!
+	 *       // We'll only get here if we don't see a robot during the move.
+	 *       out.println("Ok, I can't see anyone");
+	 *   }
+	 * 
+ * + * @param interruptible {@code true} if the event handler should be + * interrupted if new events of the same priority occurs; {@code false} + * otherwise + * @see #setEventPriority(String, int) + * @see Robot#onScannedRobot(ScannedRobotEvent) onScannedRobot(ScannedRobotEvent) + */ + @Override + public void setInterruptible(boolean interruptible) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setInterruptible(interruptible); + } else { + uninitializedException(); + } + } + + /** + * Sets the maximum turn rate of the robot measured in degrees if the robot + * should turn slower than {@link Rules#MAX_TURN_RATE} (10 degress/turn). + * + * @param newMaxTurnRate the new maximum turn rate of the robot measured in + * degrees. Valid values are 0 - {@link Rules#MAX_TURN_RATE} + * @see #turnRight(double) turnRight(double) + * @see #turnLeft(double) turnLeft(double) + * @see #setTurnRight(double) + * @see #setTurnLeft(double) + * @see #setMaxVelocity(double) + */ + public void setMaxTurnRate(double newMaxTurnRate) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setMaxTurnRate(Math.toRadians(newMaxTurnRate)); + } else { + uninitializedException(); + } + } + + /** + * Sets the maximum velocity of the robot measured in pixels/turn if the + * robot should move slower than {@link Rules#MAX_VELOCITY} (8 pixels/turn). + * + * @param newMaxVelocity the new maximum turn rate of the robot measured in + * pixels/turn. Valid values are 0 - {@link Rules#MAX_VELOCITY} + * @see #ahead(double) + * @see #setAhead(double) + * @see #back(double) + * @see #setBack(double) + * @see #setMaxTurnRate(double) + */ + public void setMaxVelocity(double newMaxVelocity) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setMaxVelocity(newMaxVelocity); + } else { + uninitializedException(); + } + } + + /** + * Sets the robot to resume the movement stopped by {@link #stop() stop()} + * or {@link #setStop()}, if any. + *

+ * This call returns immediately, and will not execute until you call + * {@link #execute()} or take an action that executes. + * + * @see #resume() resume() + * @see #stop() stop() + * @see #stop(boolean) stop(boolean) + * @see #setStop() + * @see #setStop(boolean) + * @see #execute() + */ + public void setResume() { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setResume(); + } else { + uninitializedException(); + } + } + + /** + * This call is identical to {@link #stop() stop()}, but returns immediately, and + * will not execute until you call {@link #execute()} or take an action that + * executes. + *

+ * If there is already movement saved from a previous stop, this will have + * no effect. + *

+ * This call is equivalent to calling {@code setStop(false)}; + * + * @see #stop() stop() + * @see #stop(boolean) stop(boolean) + * @see #resume() resume() + * @see #setResume() + * @see #setStop(boolean) + * @see #execute() + */ + public void setStop() { + setStop(false); + } + + /** + * This call is identical to {@link #stop(boolean) stop(boolean)}, but + * returns immediately, and will not execute until you call + * {@link #execute()} or take an action that executes. + *

+ * If there is already movement saved from a previous stop, you can + * overwrite it by calling {@code setStop(true)}. + * + * @param overwrite {@code true} if the movement saved from a previous stop + * should be overwritten; {@code false} otherwise. + * @see #stop() stop() + * @see #stop(boolean) stop(boolean) + * @see #resume() resume() + * @see #setResume() + * @see #setStop() + * @see #execute() + */ + public void setStop(boolean overwrite) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setStop(overwrite); + } else { + uninitializedException(); + } + } + + /** + * Sets the robot's gun to turn left by degrees when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's gun is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Set the gun to turn 180 degrees to the left
+	 *   setTurnGunLeft(180);
+	 *
+	 *   // Set the gun to turn 90 degrees to the right instead of left
+	 *   // (overrides the previous order)
+	 *   setTurnGunLeft(-90);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnGunLeft()
+	 *   execute();
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's gun to the left. + * If {@code degrees} > 0 the robot's gun is set to turn left. + * If {@code degrees} < 0 the robot's gun is set to turn right. + * If {@code degrees} = 0 the robot's gun is set to stop turning. + * @see #setTurnGunLeftRadians(double) setTurnGunLeftRadians(double) + * @see #turnGunLeft(double) turnGunLeft(double) + * @see #turnGunLeftRadians(double) turnGunLeftRadians(double) + * @see #turnGunRight(double) turnGunRight(double) + * @see #turnGunRightRadians(double) turnGunRightRadians(double) + * @see #setTurnGunRight(double) setTurnGunRight(double) + * @see #setTurnGunRightRadians(double) setTurnGunRightRadians(double) + * @see #setAdjustGunForRobotTurn(boolean) setAdjustGunForRobotTurn(boolean) + */ + public void setTurnGunLeft(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnGun(-Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Sets the robot's gun to turn right by degrees when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's gun is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Set the gun to turn 180 degrees to the right
+	 *   setTurnGunRight(180);
+	 *
+	 *   // Set the gun to turn 90 degrees to the left instead of right
+	 *   // (overrides the previous order)
+	 *   setTurnGunRight(-90);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnGunRight()
+	 *   execute();
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's gun to the right. + * If {@code degrees} > 0 the robot's gun is set to turn right. + * If {@code degrees} < 0 the robot's gun is set to turn left. + * If {@code degrees} = 0 the robot's gun is set to stop turning. + * @see #setTurnGunRightRadians(double) setTurnGunRightRadians(double) + * @see #turnGunRight(double) turnGunRight(double) + * @see #turnGunRightRadians(double) turnGunRightRadians(double) + * @see #turnGunLeft(double) turnGunLeft(double) + * @see #turnGunLeftRadians(double) turnGunLeftRadians(double) + * @see #setTurnGunLeft(double) setTurnGunLeft(double) + * @see #setTurnGunLeftRadians(double) setTurnGunLeftRadians(double) + * @see #setAdjustGunForRobotTurn(boolean) setAdjustGunForRobotTurn(boolean) + */ + public void setTurnGunRight(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnGun(Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Sets the robot's radar to turn left by degrees when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's radar is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Set the radar to turn 180 degrees to the left
+	 *   setTurnRadarLeft(180);
+	 *
+	 *   // Set the radar to turn 90 degrees to the right instead of left
+	 *   // (overrides the previous order)
+	 *   setTurnRadarLeft(-90);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnRadarLeft()
+	 *   execute();
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's radar to the left. + * If {@code degrees} > 0 the robot's radar is set to turn left. + * If {@code degrees} < 0 the robot's radar is set to turn right. + * If {@code degrees} = 0 the robot's radar is set to stop turning. + * @see #setTurnRadarLeftRadians(double) setTurnRadarLeftRadians(double) + * @see #turnRadarLeft(double) turnRadarLeft(double) + * @see #turnRadarLeftRadians(double) turnRadarLeftRadians(double) + * @see #turnRadarRight(double) turnRadarRight(double) + * @see #turnRadarRightRadians(double) turnRadarRightRadians(double) + * @see #setTurnRadarRight(double) setTurnRadarRight(double) + * @see #setTurnRadarRightRadians(double) setTurnRadarRightRadians(double) + * @see #setAdjustRadarForRobotTurn(boolean) setAdjustRadarForRobotTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) setAdjustRadarForGunTurn(boolean) + */ + public void setTurnRadarLeft(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnRadar(-Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Sets the robot's radar to turn right by degrees when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's radar is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Set the radar to turn 180 degrees to the right
+	 *   setTurnRadarRight(180);
+	 *
+	 *   // Set the radar to turn 90 degrees to the right instead of right
+	 *   // (overrides the previous order)
+	 *   setTurnRadarRight(-90);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnRadarRight()
+	 *   execute();
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's radar to the right. + * If {@code degrees} > 0 the robot's radar is set to turn right. + * If {@code degrees} < 0 the robot's radar is set to turn left. + * If {@code degrees} = 0 the robot's radar is set to stop turning. + * @see #setTurnRadarRightRadians(double) setTurnRadarRightRadians(double) + * @see #turnRadarRight(double) turnRadarRight(double) + * @see #turnRadarRightRadians(double) turnRadarRightRadians(double) + * @see #turnRadarLeft(double) turnRadarLeft(double) + * @see #turnRadarLeftRadians(double) turnRadarLeftRadians(double) + * @see #setTurnRadarLeft(double) setTurnRadarLeft(double) + * @see #setTurnRadarLeftRadians(double) setTurnRadarLeftRadians(double) + * @see #setAdjustRadarForRobotTurn(boolean) setAdjustRadarForRobotTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) setAdjustRadarForGunTurn(boolean) + */ + public void setTurnRadarRight(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnRadar(Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Does not return until a condition is met, i.e. when a + * {@link Condition#test()} returns {@code true}. + *

+ * This call executes immediately. + *

+ * See the {@code sample.Crazy} robot for how this method can be used. + * + * @param condition the condition that must be met before this call returns + * @see Condition + * @see Condition#test() + */ + public void waitFor(Condition condition) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).waitFor(condition); + } else { + uninitializedException(); + } + } + + /** + * This method is called if your robot dies. + *

+ * You should override it in your robot if you want to be informed of this + * event. Actions will have no effect if called from this section. The + * intent is to allow you to perform calculations or print something out + * when the robot is killed. + * + * @param event the death event set by the game + * @see DeathEvent + * @see Event + */ + @Override + public void onDeath(DeathEvent event) {} + + /** + * {@inheritDoc} + */ + public void onSkippedTurn(SkippedTurnEvent event) {} + + /** + * Returns the direction that the robot's body is facing, in radians. + * The value returned will be between 0 and 2 * PI (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * PI / 2 means East, PI means South, and 3 * PI / 2 means West. + * + * @return the direction that the robot's body is facing, in radians. + * @see #getHeadingDegrees() + * @see #getGunHeadingRadians() + * @see #getRadarHeadingRadians() + */ + public double getHeadingRadians() { + return super.getHeadingRadians(); + } + + /** + * Sets the robot's body to turn left by radians when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's body is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Set the robot to turn 180 degrees to the left
+	 *   setTurnLeftRadians(Math.PI);
+	 *
+	 *   // Set the robot to turn 90 degrees to the right instead of left
+	 *   // (overrides the previous order)
+	 *   setTurnLeftRadians(-Math.PI / 2);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnLeftRadians()
+	 *   execute();
+	 * 
+ * + * @param radians the amount of radians to turn the robot's body to the left. + * If {@code radians} > 0 the robot is set to turn left. + * If {@code radians} < 0 the robot is set to turn right. + * If {@code radians} = 0 the robot is set to stop turning. + * @see AdvancedRobot#setTurnLeft(double) setTurnLeft(double) + * @see #turnLeft(double) + * @see #turnLeftRadians(double) + * @see #turnRight(double) + * @see #turnRightRadians(double) + * @see AdvancedRobot#setTurnRight(double) setTurnRight(double) + * @see AdvancedRobot#setTurnRightRadians(double) setTurnRightRadians(double) + */ + public void setTurnLeftRadians(double radians) { + super.setTurnLeftRadians(radians); + } + + /** + * Sets the robot's body to turn right by radians when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's body is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Set the robot to turn 180 degrees to the right
+	 *   setTurnRightRadians(Math.PI);
+	 *
+	 *   // Set the robot to turn 90 degrees to the left instead of right
+	 *   // (overrides the previous order)
+	 *   setTurnRightRadians(-Math.PI / 2);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnRightRadians()
+	 *   execute();
+	 * 
+ * + * @param radians the amount of radians to turn the robot's body to the right. + * If {@code radians} > 0 the robot is set to turn right. + * If {@code radians} < 0 the robot is set to turn left. + * If {@code radians} = 0 the robot is set to stop turning. + * @see AdvancedRobot#setTurnRight(double) setTurnRight(double) + * @see #turnRight(double) + * @see #turnRightRadians(double) + * @see #turnLeft(double) + * @see #turnLeftRadians(double) + * @see AdvancedRobot#setTurnLeft(double) setTurnLeft(double) + * @see AdvancedRobot#setTurnLeftRadians(double) setTurnLeftRadians(double) + */ + public void setTurnRightRadians(double radians) { + super.setTurnRightRadians(radians); + } + + /** + * Immediately turns the robot's body to the left by radians. + *

+ * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the robot's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's body is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Turn the robot 180 degrees to the left
+	 *   turnLeftRadians(Math.PI);
+	 *
+	 *   // Afterwards, turn the robot 90 degrees to the right
+	 *   turnLeftRadians(-Math.PI / 2);
+	 * 
+ * + * @param radians the amount of radians to turn the robot's body to the left. + * If {@code radians} > 0 the robot will turn right. + * If {@code radians} < 0 the robot will turn left. + * If {@code radians} = 0 the robot will not turn, but execute. + * @see #turnLeft(double) + * @see #turnRight(double) + * @see #turnRightRadians(double) + * @see #turnGunLeft(double) + * @see #turnGunLeftRadians(double) + * @see #turnGunRight(double) + * @see #turnGunRightRadians(double) + * @see #turnRadarLeft(double) + * @see #turnRadarLeftRadians(double) + * @see #turnRadarRight(double) + * @see #turnRadarRightRadians(double) + * @see #setAdjustGunForRobotTurn(boolean) + */ + public void turnLeftRadians(double radians) { + super.turnLeftRadians(radians); + } + + /** + * Immediately turns the robot's body to the right by radians. + * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the robot's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's body is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Turn the robot 180 degrees to the right
+	 *   turnRightRadians(Math.PI);
+	 *
+	 *   // Afterwards, turn the robot 90 degrees to the left
+	 *   turnRightRadians(-Math.PI / 2);
+	 * 
+ * + * @param radians the amount of radians to turn the robot's body to the right. + * If {@code radians} > 0 the robot will turn right. + * If {@code radians} < 0 the robot will turn left. + * If {@code radians} = 0 the robot will not turn, but execute. + * @see #turnRight(double) + * @see #turnLeft(double) + * @see #turnLeftRadians(double) + * @see #turnGunLeft(double) + * @see #turnGunLeftRadians(double) + * @see #turnGunRight(double) + * @see #turnGunRightRadians(double) + * @see #turnRadarLeft(double) + * @see #turnRadarLeftRadians(double) + * @see #turnRadarRight(double) + * @see #turnRadarRightRadians(double) + * @see #setAdjustGunForRobotTurn(boolean) + */ + public void turnRightRadians(double radians) { + super.turnRightRadians(radians); + } + + /** + * Returns the direction that the robot's gun is facing, in radians. + * The value returned will be between 0 and 2 * PI (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * PI / 2 means East, PI means South, and 3 * PI / 2 means West. + * + * @return the direction that the robot's gun is facing, in radians. + * @see #getGunHeadingDegrees() + * @see #getHeadingRadians() + * @see #getRadarHeadingRadians() + */ + public double getGunHeadingRadians() { + return super.getGunHeadingRadians(); + } + + /** + * Returns the direction that the robot's radar is facing, in radians. + * The value returned will be between 0 and 2 * PI (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * PI / 2 means East, PI means South, and 3 * PI / 2 means West. + * + * @return the direction that the robot's radar is facing, in radians. + * @see #getRadarHeadingDegrees() + * @see #getHeadingRadians() + * @see #getGunHeadingRadians() + */ + public double getRadarHeadingRadians() { + return super.getRadarHeadingRadians(); + } + + /** + * Sets the robot's gun to turn left by radians when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's gun is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Set the gun to turn 180 degrees to the left
+	 *   setTurnGunLeftRadians(Math.PI);
+	 *
+	 *   // Set the gun to turn 90 degrees to the right instead of left
+	 *   // (overrides the previous order)
+	 *   setTurnGunLeftRadians(-Math.PI / 2);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnGunLeftRadians()
+	 *   execute();
+	 * 
+ * + * @param radians the amount of radians to turn the robot's gun to the left. + * If {@code radians} > 0 the robot's gun is set to turn left. + * If {@code radians} < 0 the robot's gun is set to turn right. + * If {@code radians} = 0 the robot's gun is set to stop turning. + * @see AdvancedRobot#setTurnGunLeft(double) setTurnGunLeft(double) + * @see #turnGunLeft(double) + * @see #turnGunLeftRadians(double) + * @see #turnGunRight(double) + * @see #turnGunRightRadians(double) + * @see AdvancedRobot#setTurnGunRight(double) setTurnGunRight(double) + * @see AdvancedRobot#setTurnGunRightRadians(double) setTurnGunRightRadians(double) + * @see #setAdjustGunForRobotTurn(boolean) + */ + public void setTurnGunLeftRadians(double radians) { + super.setTurnGunLeftRadians(radians); + } + + /** + * Sets the robot's gun to turn right by radians when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's gun is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Set the gun to turn 180 degrees to the right
+	 *   setTurnGunRightRadians(Math.PI);
+	 *
+	 *   // Set the gun to turn 90 degrees to the left instead of right
+	 *   // (overrides the previous order)
+	 *   setTurnGunRightRadians(-Math.PI / 2);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnGunRightRadians()
+	 *   execute();
+	 * 
+ * + * @param radians the amount of radians to turn the robot's gun to the right. + * If {@code radians} > 0 the robot's gun is set to turn left. + * If {@code radians} < 0 the robot's gun is set to turn right. + * If {@code radians} = 0 the robot's gun is set to stop turning. + * @see AdvancedRobot#setTurnGunRight(double) setTurnGunRight(double) + * @see #turnGunRight(double) + * @see #turnGunRightRadians(double) + * @see #turnGunLeft(double) + * @see #turnGunLeftRadians(double) + * @see AdvancedRobot#setTurnGunLeft(double) setTurnGunLeft(double) + * @see AdvancedRobot#setTurnGunLeftRadians(double) setTurnGunLeftRadians(double) + * @see #setAdjustGunForRobotTurn(boolean) + */ + public void setTurnGunRightRadians(double radians) { + super.setTurnGunRightRadians(radians); + } + + /** + * Sets the robot's radar to turn left by radians when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's radar is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Set the radar to turn 180 degrees to the left
+	 *   setTurnRadarLeftRadians(Math.PI);
+	 *
+	 *   // Set the radar to turn 90 degrees to the right instead of left
+	 *   // (overrides the previous order)
+	 *   setTurnRadarLeftRadians(-Math.PI / 2);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnRadarLeftRadians()
+	 *   execute();
+	 * 
+ * + * @param radians the amount of radians to turn the robot's radar to the left. + * If {@code radians} > 0 the robot's radar is set to turn left. + * If {@code radians} < 0 the robot's radar is set to turn right. + * If {@code radians} = 0 the robot's radar is set to stop turning. + * @see AdvancedRobot#setTurnRadarLeft(double) setTurnRadarLeft(double) + * @see #turnRadarLeft(double) + * @see #turnRadarLeftRadians(double) + * @see #turnRadarRight(double) + * @see #turnRadarRightRadians(double) + * @see AdvancedRobot#setTurnRadarRight(double) setTurnRadarRight(double) + * @see AdvancedRobot#setTurnRadarRightRadians(double) setTurnRadarRightRadians(double) + * @see #setAdjustRadarForRobotTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) + */ + public void setTurnRadarLeftRadians(double radians) { + super.setTurnRadarLeftRadians(radians); + } + + /** + * Sets the robot's radar to turn right by radians when the next execution + * takes place. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's radar is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Set the radar to turn 180 degrees to the right
+	 *   setTurnRadarRightRadians(Math.PI);
+	 *
+	 *   // Set the radar to turn 90 degrees to the right instead of right
+	 *   // (overrides the previous order)
+	 *   setTurnRadarRightRadians(-Math.PI / 2);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnRadarRightRadians()
+	 *   execute();
+	 * 
+ * + * @param radians the amount of radians to turn the robot's radar to the right. + * If {@code radians} > 0 the robot's radar is set to turn left. + * If {@code radians} < 0 the robot's radar is set to turn right. + * If {@code radians} = 0 the robot's radar is set to stop turning. + * @see AdvancedRobot#setTurnRadarRight(double) setTurnRadarRight(double) + * @see #turnRadarRight(double) + * @see #turnRadarRightRadians(double) + * @see #turnRadarLeft(double) + * @see #turnRadarLeftRadians(double) + * @see AdvancedRobot#setTurnRadarLeft(double) setTurnRadarLeft(double) + * @see AdvancedRobot#setTurnRadarLeftRadians(double) setTurnRadarLeftRadians(double) + * @see #setAdjustRadarForRobotTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) + */ + public void setTurnRadarRightRadians(double radians) { + super.setTurnRadarRightRadians(radians); + } + + /** + * Immediately turns the robot's gun to the left by radians. + *

+ * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the gun's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's gun is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Turn the robot's gun 180 degrees to the left
+	 *   turnGunLeftRadians(Math.PI);
+	 *
+	 *   // Afterwards, turn the robot's gun 90 degrees to the right
+	 *   turnGunLeftRadians(-Math.PI / 2);
+	 * 
+ * + * @param radians the amount of radians to turn the robot's gun to the left. + * If {@code radians} > 0 the robot's gun will turn left. + * If {@code radians} < 0 the robot's gun will turn right. + * If {@code radians} = 0 the robot's gun will not turn, but execute. + * @see #turnGunLeft(double) + * @see #turnGunRight(double) + * @see #turnGunRightRadians(double) + * @see #turnLeft(double) + * @see #turnLeftRadians(double) + * @see #turnRight(double) + * @see #turnRightRadians(double) + * @see #turnRadarLeft(double) + * @see #turnRadarLeftRadians(double) + * @see #turnRadarRight(double) + * @see #turnRadarRightRadians(double) + * @see #setAdjustGunForRobotTurn(boolean) + */ + public void turnGunLeftRadians(double radians) { + super.turnGunLeftRadians(radians); + } + + /** + * Immediately turns the robot's gun to the right by radians. + * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the gun's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's gun is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Turn the robot's gun 180 degrees to the right
+	 *   turnGunRightRadians(Math.PI);
+	 *
+	 *   // Afterwards, turn the robot's gun 90 degrees to the left
+	 *   turnGunRightRadians(-Math.PI / 2);
+	 * 
+ * + * @param radians the amount of radians to turn the robot's gun to the right. + * If {@code radians} > 0 the robot's gun will turn right. + * If {@code radians} < 0 the robot's gun will turn left. + * If {@code radians} = 0 the robot's gun will not turn, but execute. + * @see #turnGunRight(double) + * @see #turnGunLeft(double) + * @see #turnGunLeftRadians(double) + * @see #turnLeft(double) + * @see #turnLeftRadians(double) + * @see #turnRight(double) + * @see #turnRightRadians(double) + * @see #turnRadarLeft(double) + * @see #turnRadarLeftRadians(double) + * @see #turnRadarRight(double) + * @see #turnRadarRightRadians(double) + * @see #setAdjustGunForRobotTurn(boolean) + */ + public void turnGunRightRadians(double radians) { + super.turnGunRightRadians(radians); + } + + /** + * Immediately turns the robot's radar to the left by radians. + *

+ * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the radar's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's radar is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Turn the robot's radar 180 degrees to the left
+	 *   turnRadarLeftRadians(Math.PI);
+	 *
+	 *   // Afterwards, turn the robot's radar 90 degrees to the right
+	 *   turnRadarLeftRadians(-Math.PI / 2);
+	 * 
+ * + * @param radians the amount of radians to turn the robot's radar to the left. + * If {@code radians} > 0 the robot's radar will turn left. + * If {@code radians} < 0 the robot's radar will turn right. + * If {@code radians} = 0 the robot's radar will not turn, but execute. + * @see #turnRadarLeft(double) + * @see #turnRadarRight(double) + * @see #turnGunRightRadians(double) + * @see #turnLeft(double) + * @see #turnLeftRadians(double) + * @see #turnRight(double) + * @see #turnRightRadians(double) + * @see #turnGunLeft(double) + * @see #turnGunLeftRadians(double) + * @see #turnGunRight(double) + * @see #turnGunRightRadians(double) + * @see #setAdjustRadarForRobotTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) + */ + public void turnRadarLeftRadians(double radians) { + super.turnRadarLeftRadians(radians); + } + + /** + * Immediately turns the robot's radar to the right by radians. + * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the radar's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's radar is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Turn the robot's radar 180 degrees to the right
+	 *   turnRadarRightRadians(Math.PI);
+	 *
+	 *   // Afterwards, turn the robot's radar 90 degrees to the left
+	 *   turnRadarRightRadians(-Math.PI / 2);
+	 * 
+ * + * @param radians the amount of radians to turn the robot's radar to the right. + * If {@code radians} > 0 the robot's radar will turn right. + * If {@code radians} < 0 the robot's radar will turn left. + * If {@code radians} = 0 the robot's radar will not turn, but execute. + * @see #turnRadarRight(double) + * @see #turnRadarLeft(double) + * @see #turnGunLeftRadians(double) + * @see #turnLeft(double) + * @see #turnLeftRadians(double) + * @see #turnRight(double) + * @see #turnRightRadians(double) + * @see #turnGunLeft(double) + * @see #turnGunLeftRadians(double) + * @see #turnGunRight(double) + * @see #turnGunRightRadians(double) + * @see #setAdjustRadarForRobotTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) + */ + public void turnRadarRightRadians(double radians) { + super.turnRadarRightRadians(radians); + } + + /** + * Returns the angle remaining in the gun's turn, in radians. + *

+ * This call returns both positive and negative values. Positive values + * means that the gun is currently turning to the right. Negative values + * means that the gun is currently turning to the left. + * + * @return the angle remaining in the gun's turn, in radians + * @see AdvancedRobot#getGunTurnRemaining() + * @see AdvancedRobot#getTurnRemaining() getTurnRemaining() + * @see #getTurnRemainingRadians() + * @see AdvancedRobot#getRadarTurnRemaining() getRadarTurnRemaining() + * @see #getRadarTurnRemainingRadians() + */ + public double getGunTurnRemainingRadians() { + return super.getGunTurnRemainingRadians(); + } + + /** + * Returns the angle remaining in the radar's turn, in radians. + *

+ * This call returns both positive and negative values. Positive values + * means that the radar is currently turning to the right. Negative values + * means that the radar is currently turning to the left. + * + * @return the angle remaining in the radar's turn, in radians + * @see AdvancedRobot#getRadarTurnRemaining() + * @see AdvancedRobot#getTurnRemaining() getTurnRemaining() + * @see #getTurnRemainingRadians() + * @see AdvancedRobot#getGunTurnRemaining() getGunTurnRemaining() + * @see #getGunTurnRemainingRadians() + */ + public double getRadarTurnRemainingRadians() { + return super.getRadarTurnRemainingRadians(); + } + + /** + * Returns the angle remaining in the robot's turn, in radians. + *

+ * This call returns both positive and negative values. Positive values + * means that the robot is currently turning to the right. Negative values + * means that the robot is currently turning to the left. + * + * @return the angle remaining in the robot's turn, in radians + * @see AdvancedRobot#getTurnRemaining() + * @see AdvancedRobot#getGunTurnRemaining() getGunTurnRemaining() + * @see #getGunTurnRemainingRadians() + * @see AdvancedRobot#getRadarTurnRemaining() getRadarTurnRemaining() + * @see #getRadarTurnRemainingRadians() + */ + public double getTurnRemainingRadians() { + return super.getTurnRemainingRadians(); + } + + /** + * Do not call this method! + *

+ * {@inheritDoc} + */ + public final IAdvancedEvents getAdvancedEventListener() { + return this; // this robot is listening + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleEndedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleEndedEvent.java new file mode 100644 index 0000000..de3bd6a --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleEndedEvent.java @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicEvents2; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A BattleEndedEvent is sent to {@link Robot#onBattleEnded(BattleEndedEvent) + * onBattleEnded()} when the battle is ended. + * You can use the information contained in this event to determine if the + * battle was aborted and also get the results of the battle. + * + * @see BattleResults + * @see Robot#onBattleEnded(BattleEndedEvent) + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class BattleEndedEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 100; // System event -> cannot be changed! + + private final boolean aborted; + private final BattleResults results; + + /** + * Called by the game to create a new BattleEndedEvent. + * + * @param aborted {@code true} if the battle was aborted; {@code false} otherwise. + * @param results the battle results + */ + public BattleEndedEvent(boolean aborted, BattleResults results) { + this.aborted = aborted; + this.results = results; + } + + /** + * Checks if this battle was aborted. + * + * @return {@code true} if the battle was aborted; {@code false} otherwise. + */ + public boolean isAborted() { + return aborted; + } + + /** + * Returns the battle results. + * + * @return the battle results. + */ + public BattleResults getResults() { + return results; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + public final int getPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (robot != null) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null && IBasicEvents2.class.isAssignableFrom(listener.getClass())) { + ((IBasicEvents2) listener).onBattleEnded(this); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + final boolean isCriticalEvent() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.BattleEndedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + BattleEndedEvent obj = (BattleEndedEvent) object; + + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_BOOL + + serializer.sizeOf(RbSerializer.BattleResults_TYPE, obj.results); + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + BattleEndedEvent obj = (BattleEndedEvent) object; + + serializer.serialize(buffer, obj.aborted); + serializer.serialize(buffer, RbSerializer.BattleResults_TYPE, obj.results); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + boolean aborted = serializer.deserializeBoolean(buffer); + BattleResults results = (BattleResults) serializer.deserializeAny(buffer); + + return new BattleEndedEvent(aborted, results); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleResults.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleResults.java new file mode 100644 index 0000000..572d8e6 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleResults.java @@ -0,0 +1,282 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; + +import java.nio.ByteBuffer; + + +/** + * Contains the battle results returned by {@link BattleEndedEvent#getResults()} + * when a battle has ended. + * + * @see BattleEndedEvent#getResults() + * @see Robot#onBattleEnded(BattleEndedEvent) + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public class BattleResults implements java.io.Serializable, Comparable { + protected static final long serialVersionUID = 1L; + + protected String teamLeaderName; + protected int rank; + protected double score; + protected double survival; + protected double lastSurvivorBonus; + protected double bulletDamage; + protected double bulletDamageBonus; + protected double ramDamage; + protected double ramDamageBonus; + protected int firsts; + protected int seconds; + protected int thirds; + + /** + * Constructs this BattleResults object. + * + * @param teamLeaderName the name of the team leader. + * @param rank the rank of the robot in the battle. + * @param score the total score for the robot in the battle. + * @param survival the survival score for the robot in the battle. + * @param lastSurvivorBonus the last survivor bonus for the robot in the battle. + * @param bulletDamage the bullet damage score for the robot in the battle. + * @param bulletDamageBonus the bullet damage bonus for the robot in the battle. + * @param ramDamage the ramming damage for the robot in the battle. + * @param ramDamageBonus the ramming damage bonus for the robot in the battle. + * @param firsts the number of rounds this robot placed first. + * @param seconds the number of rounds this robot placed second. + * @param thirds the number of rounds this robot placed third. + */ + public BattleResults( + String teamLeaderName, + int rank, + double score, + double survival, + double lastSurvivorBonus, + double bulletDamage, + double bulletDamageBonus, + double ramDamage, + double ramDamageBonus, + int firsts, + int seconds, + int thirds + ) { + this.teamLeaderName = teamLeaderName; + this.rank = rank; + this.score = score; + this.survival = survival; + this.lastSurvivorBonus = lastSurvivorBonus; + this.bulletDamage = bulletDamage; + this.bulletDamageBonus = bulletDamageBonus; + this.ramDamage = ramDamage; + this.ramDamageBonus = ramDamageBonus; + this.firsts = firsts; + this.seconds = seconds; + this.thirds = thirds; + } + + /** + * Returns the name of the team leader in the team or the name of the + * robot if the robot is not participating in a team. + * + * @return the name of the team leader in the team or the name of the robot. + */ + public String getTeamLeaderName() { + return teamLeaderName; + } + + /** + * Returns the rank of this robot in the battle results. + * + * @return the rank of this robot in the battle results. + */ + public int getRank() { + return rank; + } + + /** + * Returns the total score of this robot in the battle. + * + * @return the total score of this robot in the battle. + */ + public int getScore() { + return (int) (score + 0.5); + } + + /** + * Returns the survival score of this robot in the battle. + * + * @return the survival score of this robot in the battle. + */ + public int getSurvival() { + return (int) (survival + 0.5); + } + + /** + * Returns the last survivor score of this robot in the battle. + * + * @return the last survivor score of this robot in the battle. + */ + public int getLastSurvivorBonus() { + return (int) (lastSurvivorBonus + 0.5); + } + + /** + * Returns the bullet damage score of this robot in the battle. + * + * @return the bullet damage score of this robot in the battle. + */ + public int getBulletDamage() { + return (int) (bulletDamage + 0.5); + } + + /** + * Returns the bullet damage bonus of this robot in the battle. + * + * @return the bullet damage bonus of this robot in the battle. + */ + public int getBulletDamageBonus() { + return (int) (bulletDamageBonus + 0.5); + } + + /** + * Returns the ram damage score of this robot in the battle. + * + * @return the ram damage score of this robot in the battle. + */ + public int getRamDamage() { + return (int) (ramDamage + 0.5); + } + + /** + * Returns the ram damage bonus of this robot in the battle. + * + * @return the ram damage bonus of this robot in the battle. + */ + public int getRamDamageBonus() { + return (int) (ramDamageBonus + 0.5); + } + + /** + * Returns the number of rounds this robot placed first in the battle. + * + * @return the number of rounds this robot placed first in the battle. + */ + public int getFirsts() { + return firsts; + } + + /** + * Returns the number of rounds this robot placed second in the battle. + * + * @return the number of rounds this robot placed second in the battle. + */ + public int getSeconds() { + return seconds; + } + + /** + * Returns the number of rounds this robot placed third in the battle. + * + * @return the number of rounds this robot placed third in the battle. + */ + public int getThirds() { + return thirds; + } + + /** + * {@inheritDoc} + */ + public int compareTo(BattleResults o) { + return ((Double) score).compareTo(o.score); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + + temp = Double.doubleToLongBits(score); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + BattleResults other = (BattleResults) obj; + + if (Double.doubleToLongBits(score) != Double.doubleToLongBits(other.score)) { + return false; + } + return true; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + BattleResults obj = (BattleResults) object; + + return RbSerializer.SIZEOF_TYPEINFO + serializer.sizeOf(obj.teamLeaderName) + 4 * RbSerializer.SIZEOF_INT + + 7 * RbSerializer.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + BattleResults obj = (BattleResults) object; + + serializer.serialize(buffer, obj.teamLeaderName); + serializer.serialize(buffer, obj.rank); + serializer.serialize(buffer, obj.score); + serializer.serialize(buffer, obj.survival); + serializer.serialize(buffer, obj.lastSurvivorBonus); + serializer.serialize(buffer, obj.bulletDamage); + serializer.serialize(buffer, obj.bulletDamageBonus); + serializer.serialize(buffer, obj.ramDamage); + serializer.serialize(buffer, obj.ramDamageBonus); + serializer.serialize(buffer, obj.firsts); + serializer.serialize(buffer, obj.seconds); + serializer.serialize(buffer, obj.thirds); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + String teamLeaderName = serializer.deserializeString(buffer); + int rank = buffer.getInt(); + double score = buffer.getDouble(); + double survival = buffer.getDouble(); + double lastSurvivorBonus = buffer.getDouble(); + double bulletDamage = buffer.getDouble(); + double bulletDamageBonus = buffer.getDouble(); + double ramDamage = buffer.getDouble(); + double ramDamageBonus = buffer.getDouble(); + int firsts = buffer.getInt(); + int seconds = buffer.getInt(); + int thirds = buffer.getInt(); + + return new BattleResults(teamLeaderName, rank, score, survival, lastSurvivorBonus, bulletDamage, + bulletDamageBonus, ramDamage, ramDamageBonus, firsts, seconds, thirds); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleRules.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleRules.java new file mode 100644 index 0000000..af70c8d --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BattleRules.java @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.security.IHiddenRulesHelper; + + +/** + * Contains the battle rules returned by {@link robocode.control.events.BattleStartedEvent#getBattleRules() + * BattleStartedEvent.getBattleRules()} when a battle is started and + * {@link robocode.control.events.BattleCompletedEvent#getBattleRules() BattleCompletedEvent.getBattleRules()} + * when a battle is completed. + * + * @see robocode.control.events.BattleStartedEvent BattleStartedEvent + * @see robocode.control.events.BattleCompletedEvent BattleCompletedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public final class BattleRules implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private final int battlefieldWidth; + private final int battlefieldHeight; + private final int numRounds; + private final double gunCoolingRate; + private final long inactivityTime; + private final boolean hideEnemyNames; + private final int sentryBorderSize; + + /** + * Returns the battlefield width. + * + * @return the battlefield width. + */ + public int getBattlefieldWidth() { + return battlefieldWidth; + } + + /** + * Returns the battlefield height. + * + * @return the battlefield height. + */ + public int getBattlefieldHeight() { + return battlefieldHeight; + } + + /** + * Returns the number of rounds. + * + * @return the number of rounds. + */ + public int getNumRounds() { + return numRounds; + } + + /** + * Returns the rate at which the gun will cool down, i.e. the amount of heat the gun heat will drop per turn. + *

+ * The gun cooling rate is default 0.1 per turn, but can be changed by the battle setup. + * So don't count on the cooling rate being 0.1! + * + * @return the gun cooling rate. + * @see Robot#getGunHeat() + * @see Robot#fire(double) + * @see Robot#fireBullet(double) + */ + public double getGunCoolingRate() { + return gunCoolingRate; + } + + /** + * Returns the allowed inactivity time, where the robot is not taking any action, before will begin to be zapped. + * The inactivity time is measured in turns, and is the allowed time that a robot is allowed to omit taking + * action before being punished by the game by zapping. + *

+ * When a robot is zapped by the game, it will loose 0.1 energy points per turn. Eventually the robot will be + * killed by zapping until the robot takes action. When the robot takes action, the inactivity time counter is + * reset. + *

+ * The allowed inactivity time is per default 450 turns, but can be changed by the battle setup. + * So don't count on the inactivity time being 450 turns! + * + * @return the allowed inactivity time. + * @see Robot#doNothing() + * @see AdvancedRobot#execute() + */ + public long getInactivityTime() { + return inactivityTime; + } + + /** + * Returns true if the enemy names are hidden, i.e. anonymous; false otherwise. + * + * @Since 1.7.3 + */ + public boolean getHideEnemyNames() { + return hideEnemyNames; + } + + /** + * Returns the sentry border size for a {@link robocode.BorderSentry BorderSentry} that defines the how + * far a BorderSentry is allowed to move from the border edges measured in units.
+ * Hence, the sentry border size defines the width/range of the border area surrounding the battlefield that + * BorderSentrys cannot leave (sentry robots robots must stay in the border area), but it also define the + * distance from the border edges where BorderSentrys are allowed/able to make damage to robots entering this + * border area. + * + * @return the border size in units/pixels. + * + * @since 1.9.0.0 + */ + public int getSentryBorderSize() { + return sentryBorderSize; + } + + private BattleRules(int battlefieldWidth, int battlefieldHeight, int numRounds, double gunCoolingRate, + long inactivityTime, boolean hideEnemyNames, int sentryBorderSize) { + this.battlefieldWidth = battlefieldWidth; + this.battlefieldHeight = battlefieldHeight; + this.numRounds = numRounds; + this.gunCoolingRate = gunCoolingRate; + this.inactivityTime = inactivityTime; + this.hideEnemyNames = hideEnemyNames; + this.sentryBorderSize = sentryBorderSize; + } + + static IHiddenRulesHelper createHiddenHelper() { + return new HiddenHelper(); + } + + private static class HiddenHelper implements IHiddenRulesHelper { + + public BattleRules createRules(int battlefieldWidth, int battlefieldHeight, int numRounds, double gunCoolingRate, long inactivityTime, boolean hideEnemyNames, int sentryBorderSize) { + return new BattleRules(battlefieldWidth, battlefieldHeight, numRounds, gunCoolingRate, inactivityTime, + hideEnemyNames, sentryBorderSize); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/BorderSentry.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BorderSentry.java new file mode 100644 index 0000000..ea99cf5 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BorderSentry.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * A robot that implements BorderSentry is a robot type used for keeping other robots away from the borders, + * i.e. guarding the borders in order to prevent "wall crawlers".
+ * Robots that implement BorderSentry have 400 extra life/energy (500 in total), but is placed at the border + * of the battlefield when the game is started.
+ * Border sentry robots cannot move away from the border area, and they can only make damage to robots that + * are moving into the border area. The size of the border area is determined by the + * {@link BattleRules#getSentryBorderSize() battle rules}.
+ * This type of robot is intended for use in battles where robots should be forced away from the borders + * in order to prevent "wall crawlers".
+ * Border sentry robots does not get scores, and will not occur in the battle results or rankings. + * + * @see BattleRules#getSentryBorderSize() + * @see JuniorRobot + * @see Robot + * @see AdvancedRobot + * @see TeamRobot + * @see RateControlRobot + * @see Droid + * + * @author Flemming N. Larsen (original) + * + * @since 1.9.0.0 + */ +public interface BorderSentry {} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/Bullet.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Bullet.java new file mode 100644 index 0000000..d0b1e1c --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Bullet.java @@ -0,0 +1,261 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.security.IHiddenBulletHelper; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; + +import java.io.Serializable; +import java.nio.ByteBuffer; + + +/** + * Represents a bullet. This is returned from {@link Robot#fireBullet(double)} + * and {@link AdvancedRobot#setFireBullet(double)}, and all the bullet-related + * events. + * + * @see Robot#fireBullet(double) + * @see AdvancedRobot#setFireBullet(double) + * @see BulletHitEvent + * @see BulletMissedEvent + * @see BulletHitBulletEvent + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class Bullet implements Serializable { + private static final long serialVersionUID = 1L; + + private final double headingRadians; + private double x; + private double y; + private final double power; + private final String ownerName; + private String victimName; + private boolean isActive; + private final int bulletId; + + /** + * Called by the game to create a new {@code Bullet} object + * + * @param heading the heading of the bullet, in radians. + * @param x the starting X position of the bullet. + * @param y the starting Y position of the bullet. + * @param power the power of the bullet. + * @param ownerName the name of the owner robot that owns the bullet. + * @param victimName the name of the robot hit by the bullet. + * @param isActive {@code true} if the bullet still moves; {@code false} otherwise. + * @param bulletId unique id of bullet for owner robot. + */ + public Bullet(double heading, double x, double y, double power, String ownerName, String victimName, boolean isActive, int bulletId) { + this.headingRadians = heading; + this.x = x; + this.y = y; + this.power = power; + this.ownerName = ownerName; + this.victimName = victimName; + this.isActive = isActive; + this.bulletId = bulletId; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + return bulletId == ((Bullet) obj).bulletId; + } + + @Override + public int hashCode() { + return bulletId; + } + + /** + * Returns the direction the bullet is/was heading, in degrees + * (0 <= getHeading() < 360). This is not relative to the direction you are + * facing. + * + * @return the direction the bullet is/was heading, in degrees + */ + public double getHeading() { + return Math.toDegrees(headingRadians); + } + + /** + * Returns the direction the bullet is/was heading, in radians + * (0 <= getHeadingRadians() < 2 * Math.PI). This is not relative to the + * direction you are facing. + * + * @return the direction the bullet is/was heading, in radians + */ + public double getHeadingRadians() { + return headingRadians; + } + + /** + * Returns the name of the robot that fired this bullet. + * + * @return the name of the robot that fired this bullet + */ + public String getName() { + return ownerName; + } + + /** + * Returns the power of this bullet. + *

+ * The bullet will do (4 * power) damage if it hits another robot. + * If power is greater than 1, it will do an additional 2 * (power - 1) + * damage. You will get (3 * power) back if you hit the other robot. + * + * @return the power of the bullet + */ + public double getPower() { + return power; + } + + /** + * Returns the velocity of this bullet. The velocity of the bullet is + * constant once it has been fired. + * + * @return the velocity of the bullet + */ + public double getVelocity() { + return Rules.getBulletSpeed(power); + } + + /** + * Returns the name of the robot that this bullet hit, or {@code null} if + * the bullet has not hit a robot. + * + * @return the name of the robot that this bullet hit, or {@code null} if + * the bullet has not hit a robot. + */ + public String getVictim() { + return victimName; + } + + /** + * Returns the X position of the bullet. + * + * @return the X position of the bullet + */ + public double getX() { + return x; + } + + /** + * Returns the Y position of the bullet. + * + * @return the Y position of the bullet + */ + public double getY() { + return y; + } + + /** + * Checks if this bullet is still active on the battlefield. + * + * @return {@code true} if the bullet is still active on the battlefield; + * {@code false} otherwise + */ + public boolean isActive() { + return isActive; + } + + /** + * Updates this bullet based on the specified bullet status. + * + * @param x the new X position of the bullet . + * @param y the new Y position of the bullet. + * @param victimName the name if the victim that has been hit by this bullet. + * @param isActive {@code true} if the bullet still moves; {@code false} otherwise. + */ + // this method is invisible on RobotAPI + private void update(double x, double y, String victimName, boolean isActive) { + this.x = x; + this.y = y; + this.victimName = victimName; + this.isActive = isActive; + } + + // this method is invisible on RobotAPI + /** + * @return unique id of bullet for owner robot + */ + int getBulletId() { + return bulletId; + } + + /** + * Creates a hidden bullet helper for accessing hidden methods on this object. + * + * @return a hidden bullet helper. + */ + // this method is invisible on RobotAPI + static IHiddenBulletHelper createHiddenHelper() { + return new HiddenBulletHelper(); + } + + /** + * Creates a hidden bullet helper for accessing hidden methods on this object. + * + * @return a hidden bullet helper. + */ + // this class is invisible on RobotAPI + static ISerializableHelper createHiddenSerializer() { + return new HiddenBulletHelper(); + } + + // this class is invisible on RobotAPI + private static class HiddenBulletHelper implements IHiddenBulletHelper, ISerializableHelper { + + public void update(Bullet bullet, double x, double y, String victimName, boolean isActive) { + bullet.update(x, y, victimName, isActive); + } + + public int sizeOf(RbSerializer serializer, Object object) { + Bullet obj = (Bullet) object; + + return RbSerializer.SIZEOF_TYPEINFO + 4 * RbSerializer.SIZEOF_DOUBLE + serializer.sizeOf(obj.ownerName) + + serializer.sizeOf(obj.victimName) + RbSerializer.SIZEOF_BOOL + RbSerializer.SIZEOF_INT; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + Bullet obj = (Bullet) object; + + serializer.serialize(buffer, obj.headingRadians); + serializer.serialize(buffer, obj.x); + serializer.serialize(buffer, obj.y); + serializer.serialize(buffer, obj.power); + serializer.serialize(buffer, obj.ownerName); + serializer.serialize(buffer, obj.victimName); + serializer.serialize(buffer, obj.isActive); + serializer.serialize(buffer, obj.bulletId); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + double headingRadians = buffer.getDouble(); + double x = buffer.getDouble(); + double y = buffer.getDouble(); + double power = buffer.getDouble(); + String ownerName = serializer.deserializeString(buffer); + String victimName = serializer.deserializeString(buffer); + boolean isActive = serializer.deserializeBoolean(buffer); + int bulletId = serializer.deserializeInt(buffer); + + return new Bullet(headingRadians, x, y, power, ownerName, victimName, isActive, bulletId); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletHitBulletEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletHitBulletEvent.java new file mode 100644 index 0000000..db738b9 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletHitBulletEvent.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * This event is sent to {@link Robot#onBulletHitBullet(BulletHitBulletEvent) + * onBulletHitBullet} when one of your bullets has hit another bullet. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class BulletHitBulletEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 55; + + private Bullet bullet; + private final Bullet hitBullet; + + /** + * Called by the game to create a new {@code BulletHitEvent}. + * + * @param bullet your bullet that hit another bullet + * @param hitBullet the bullet that was hit by your bullet + */ + public BulletHitBulletEvent(Bullet bullet, Bullet hitBullet) { + super(); + this.bullet = bullet; + this.hitBullet = hitBullet; + } + + /** + * Returns your bullet that hit another bullet. + * + * @return your bullet + */ + public Bullet getBullet() { + return bullet; + } + + /** + * Returns the bullet that was hit by your bullet. + * + * @return the bullet that was hit + */ + public Bullet getHitBullet() { + return hitBullet; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onBulletHitBullet(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.BulletHitBulletEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + BulletHitBulletEvent obj = (BulletHitBulletEvent) object; + + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_INT + + serializer.sizeOf(RbSerializer.Bullet_TYPE, obj.hitBullet); + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + BulletHitBulletEvent obj = (BulletHitBulletEvent) object; + + // no need to transmit whole bullet, rest of it is already known to proxy side + serializer.serialize(buffer, obj.bullet.getBulletId()); + serializer.serialize(buffer, RbSerializer.Bullet_TYPE, obj.hitBullet); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + Bullet bullet = new Bullet(0, 0, 0, 0, null, null, false, buffer.getInt()); + Bullet hitBullet = (Bullet) serializer.deserializeAny(buffer); + + return new BulletHitBulletEvent(bullet, hitBullet); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletHitEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletHitEvent.java new file mode 100644 index 0000000..3e08a88 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletHitEvent.java @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * This event is sent to {@link Robot#onBulletHit(BulletHitEvent) onBulletHit} + * when one of your bullets has hit another robot. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class BulletHitEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 50; + + private final String name; + private final double energy; + private Bullet bullet; + + /** + * Called by the game to create a new {@code BulletHitEvent}. + * + * @param name the name of the robot your bullet hit + * @param energy the remaining energy of the robot that your bullet has hit + * @param bullet the bullet that hit the robot + */ + public BulletHitEvent(String name, double energy, Bullet bullet) { + super(); + this.name = name; + this.energy = energy; + this.bullet = bullet; + } + + /** + * Returns the bullet of yours that hit the robot. + * + * @return the bullet that hit the robot + */ + public Bullet getBullet() { + return bullet; + } + + /** + * Returns the remaining energy of the robot your bullet has hit (after the + * damage done by your bullet). + * + * @return energy the remaining energy of the robot that your bullet has hit + */ + public double getEnergy() { + return energy; + } + + /** + * @return energy the remaining energy of the robot that your bullet has hit + * @deprecated Use {@link #getEnergy()} instead. + */ + @Deprecated + public double getLife() { + return energy; + } + + /** + * Returns the name of the robot your bullet hit. + * + * @return the name of the robot your bullet hit. + */ + public String getName() { + return name; + } + + /** + * @return energy the remaining energy of the robot that your bullet has hit + * @deprecated Use {@link #getEnergy()} instead. + */ + @Deprecated + public double getRobotLife() { + return energy; + } + + /** + * @return the name of the robot your bullet hit. + * @deprecated Use {@link #getName()} instead. + */ + @Deprecated + public String getRobotName() { + return name; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onBulletHit(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.BulletHitEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + BulletHitEvent obj = (BulletHitEvent) object; + + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_INT + serializer.sizeOf(obj.name) + + RbSerializer.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + BulletHitEvent obj = (BulletHitEvent) object; + + serializer.serialize(buffer, obj.bullet.getBulletId()); + serializer.serialize(buffer, obj.name); + serializer.serialize(buffer, obj.energy); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + Bullet bullet = new Bullet(0, 0, 0, 0, null, null, false, buffer.getInt()); + String name = serializer.deserializeString(buffer); + double energy = buffer.getDouble(); + + return new BulletHitEvent(name, energy, bullet); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletMissedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletMissedEvent.java new file mode 100644 index 0000000..5d0db37 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/BulletMissedEvent.java @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * This event is sent to {@link Robot#onBulletMissed(BulletMissedEvent) + * onBulletMissed} when one of your bullets has missed, i.e. when the bullet has + * reached the border of the battlefield. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class BulletMissedEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 60; + + private Bullet bullet; + + /** + * Called by the game to create a new {@code BulletMissedEvent}. + * + * @param bullet the bullet that missed + */ + public BulletMissedEvent(Bullet bullet) { + this.bullet = bullet; + } + + /** + * Returns the bullet that missed. + * + * @return the bullet that missed + */ + public Bullet getBullet() { + return bullet; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onBulletMissed(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.BulletMissedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_INT; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + BulletMissedEvent obj = (BulletMissedEvent) object; + + serializer.serialize(buffer, obj.bullet.getBulletId()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + Bullet bullet = new Bullet(0, 0, 0, 0, null, null, false, buffer.getInt()); + + return new BulletMissedEvent(bullet); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/Condition.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Condition.java new file mode 100644 index 0000000..58c6a1b --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Condition.java @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * Condition is used to define custom {@link AdvancedRobot#waitFor(Condition) + * waitFor(Condition)} and custom events for an {@link AdvancedRobot}. The code + * below is taken from the sample robot named {@code sample.Target}. See the + * {@code sample/Target.java} for details. + *

+ *   addCustomEvent(
+ *       new Condition("triggerhit") {
+ *           public boolean test() {
+ *               return (getEnergy() <= trigger);
+ *           };
+ *       }
+ *   );
+ * 
+ * You should note that by extending Condition this way, you are actually + * creating an inner class -- so if you distribute your robot, there will be + * multiple class files. (i.e. {@code Target$1.class}) + * + * @see AdvancedRobot#waitFor(Condition) + * @see AdvancedRobot#addCustomEvent(Condition) + * @see AdvancedRobot#removeCustomEvent(Condition) + * @see AdvancedRobot#onCustomEvent(CustomEvent) + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Nathaniel Troutman (contributor) + */ +public abstract class Condition { + + /** + * The priority of this condition. Defaults to 80. + */ + public int priority = 80; + + /** + * The name of this condition. + */ + public String name; + + /** + * Creates a new, unnamed Condition with the default priority, which is 80. + */ + public Condition() {} + + /** + * Creates a new Condition with the specified name, and default priority, + * which is 80. + * + * @param name the name for the new Condition + */ + public Condition(String name) { + this.name = name; + } + + /** + * Creates a new Condition with the specified name and priority. + * A condition priority is a value from 0 - 99. The higher value, the + * higher priority. The default priority is 80. + * + * @param name the name for the new condition + * @param priority the priority of the new condition + */ + public Condition(String name, int priority) { + this.name = name; + if (priority < 0) { + System.out.println("SYSTEM: Priority must be between 0 and 99."); + System.out.println("SYSTEM: Priority for condition " + name + " will be 0."); + priority = 0; + } else if (priority > 99) { + System.out.println("SYSTEM: Priority must be between 0 and 99."); + System.out.println("SYSTEM: Priority for condition " + name + " will be 99."); + priority = 99; + } + this.priority = priority; + } + + /** + * Returns the name of this condition. + * + * @return the name of this condition + */ + public String getName() { + return (name != null) ? name : getClass().getName(); + } + + /** + * Returns the priority of this condition. + * A condition priority is a value from 0 - 99. The higher value, the + * higher priority. The default priority is 80. + * + * @return the priority of this condition + */ + public final int getPriority() { + return priority; + } + + /** + * Sets the name of this condition. + * + * @param newName the new name of this condition + */ + public void setName(String newName) { + name = newName; + } + + /** + * Sets the priority of this condition. + * A condition priority is a value from 0 - 99. The higher value, the + * higher priority. The default priority is 80. + * + * @param newPriority the new priority of this condition. + */ + public void setPriority(int newPriority) { + priority = newPriority; + } + + /** + * Overriding the test() method is the point of a Condition. + * The game will call your test() function, and take action if it returns + * {@code true}. This is valid for both {@link AdvancedRobot#waitFor} and + * {@link AdvancedRobot#addCustomEvent}. + *

+ * You may not take any actions inside of test(). + * + * @return {@code true} if the condition has been met, {@code false} + * otherwise. + */ + public abstract boolean test(); + + /** + * Called by the system in order to clean up references to internal objects. + * + * @since 1.4.3 + */ + public void cleanup() {/* Do nothing: Should be overridden by sub-classes to perform needed + clean up to ensure that there are NO circular references */} +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/CustomEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/CustomEvent.java new file mode 100644 index 0000000..30be654 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/CustomEvent.java @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import robocode.robotinterfaces.IAdvancedEvents; +import robocode.robotinterfaces.IAdvancedRobot; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; + + +/** + * This event is sent to {@link AdvancedRobot#onCustomEvent(CustomEvent) + * onCustomEvent()} when a custom condition is met. Be sure to reset or remove + * the custom condition to avoid having it recurring repeatedly (see the + * example for the {@link #getCondition()} method. + * + * @see #getCondition() + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class CustomEvent extends Event { + private static final long serialVersionUID = 1L; + private static final int DEFAULT_PRIORITY = 80; + + private transient final Condition condition; + + /** + * Called by the game to create a new CustomEvent when a condition is met. + * + * @param condition the condition that must be met + */ + public CustomEvent(Condition condition) { + this.condition = condition; + if (condition != null) { + setPriority(condition.getPriority()); + } + } + + /** + * Called by the game to create a new CustomEvent when a condition is met. + * The event will have the given priority. + * An event priority is a value from 0 - 99. The higher value, the higher + * priority. The default priority is 80. + *

+ * This is equivalent to calling {@link Condition#setPriority(int)} on the + * Condition. + * + * @param condition the condition that must be met + * @param priority the priority of the condition + */ + public CustomEvent(Condition condition, int priority) { + this.condition = condition; + setPriority(priority); + if (condition != null) { + condition.setPriority(getPriority()); + } + } + + /** + * Returns the condition that fired, causing this event to be generated. + * Use this to determine which condition fired, and to remove the custom + * event. + *

+	 *   public void onCustomEvent(CustomEvent event) {
+	 *       if (event.getCondition().getName().equals("mycondition")) {
+	 *           removeCustomEvent(event.getCondition());
+	 *           // do something else
+	 *       }
+	 *   }
+	 * 
+ * + * @return the condition that fired, causing this event to be generated + */ + public Condition getCondition() { + return condition; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isAdvancedRobot()) { + IAdvancedEvents listener = ((IAdvancedRobot) robot).getAdvancedEventListener(); + + if (listener != null) { + listener.onCustomEvent(this); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + // final to disable overrides + public final int compareTo(Event event) { + return super.compareTo(event); + } + + /** + * {@inheritDoc} + */ + @Override + // final to disable overrides + final boolean isCriticalEvent() { + return false; + } + + /** + * {@inheritDoc} + */ + @Override + // final to disable overrides + public final int getPriority() { + return super.getPriority(); + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + throw new Error("Serialization not supported on this event type"); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/DeathEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/DeathEvent.java new file mode 100644 index 0000000..b5f6f0e --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/DeathEvent.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * This event is sent to {@link Robot#onDeath(DeathEvent) onDeath()} when your + * robot dies. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class DeathEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = -1; // System event -> cannot be changed! + + /** + * Called by the game to create a new DeathEvent. + */ + public DeathEvent() { + super(); + } + + /** + * {@inheritDoc} + */ + @Override + public final int getPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onDeath(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + final boolean isCriticalEvent() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.DeathEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) {} + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + return new DeathEvent(); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/Droid.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Droid.java new file mode 100644 index 0000000..73fffef --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Droid.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * Robots that implement Droid have no scanner, but an extra 20 life/energy. + * This class is intended for use in teams. + * + * @see JuniorRobot + * @see Robot + * @see AdvancedRobot + * @see TeamRobot + * @see RateControlRobot + * @see BorderSentry + * + * @author Mathew A. Nelson (original) + */ +public interface Droid {} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/Event.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Event.java new file mode 100644 index 0000000..ccb128c --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Event.java @@ -0,0 +1,266 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.IHiddenEventHelper; +import net.sf.robocode.io.Logger; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.io.Serializable; + + +// XXX Remember to update the .NET version whenever a change is made to this class! + +/** + * The superclass of all Robocode events. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public abstract class Event implements Comparable, Serializable { + private static final long serialVersionUID = 1L; + private static final int DEFAULT_PRIORITY = 80; + + private long time; + private int priority; + + // time is valid only after adding to event manager on proxy side, we do not update it on battle side + private transient boolean addedToQueue; + + /** + * Default constructor used by the game to create a new event. + */ + public Event() { + super(); + } + + /** + * Compares this event to another event regarding precedence. + * The event precedence is first and foremost determined by the event time, + * secondly the event priority, and lastly specific event information. + *

+ * This method will first compare the time of each event. If the event time + * is the same for both events, then this method compared the priority of + * each event. If the event priorities are equals, then this method will + * compare the two event based on specific event information. + *

+ * This method is called by the game in order to sort the event queue of a + * robot to make sure the events are listed in chronological order. + * + * @param event the event to compare to this event. + * @return a negative value if this event has higher precedence, i.e. must + * be listed before the specified event. A positive value if this event + * has a lower precedence, i.e. must be listed after the specified event. + * 0 means that the precedence of the two events are equal. + */ + public int compareTo(Event event) { + // Compare the time difference which has precedence over priority. + int timeDiff = (int) (time - event.time); + + if (timeDiff != 0) { + return timeDiff; // Time differ + } + + // Same time -> Compare the difference in priority + int priorityDiff = event.getPriority() - getPriority(); + + if (priorityDiff != 0) { + return priorityDiff; // Priority differ + } + + // Same time and priority -> Compare specific event types + // look at overrides in ScannedRobotEvent and HitRobotEvent + + // No difference found + return 0; + } + + /** + * Returns the time when this event occurred. + *

+ * Note that the time is equal to the turn of a battle round. + * + * @return the time when this event occurred. + */ + // Note: We rolled back the use of 'final' here due to Bug [2928688], where some old robots do override getTime() + // with their own events that inherits from robocode.Event. + public /* final*/long getTime() { + return time; + } + + /** + * Changes the time when this event occurred. + *

+ * Note that the time is equal to the turn of a battle round. + *

+ * This method is intended for letting robot developers create their own event types. + * It is not possible to change the time of an event after it has been added to the event + * queue of the robot. + * + * @param newTime the time this event occurred + */ + public void setTime(long newTime) { + if (addedToQueue) { + Logger.printlnToRobotsConsole( + "SYSTEM: The time of an event cannot be changed after it has been added the event queue."); + } else { + time = newTime; + } + } + + /** + * Returns the priority of this event. + *

+ * An event priority is a value from 0 - 99. The higher value, the higher priority. + *

+ * The default priority is 80, but varies depending on the type of event. + * + * @return the priority of this event. + */ + public int getPriority() { + return priority; + } + + /** + * Changes the priority of this event. + * An event priority is a value from 0 - 99. The higher value, the higher priority. + *

+ * The default priority is 80, but varies depending on the type of event. + *

+ * This method is intended for letting robot developers create their own event types. + * It is not possible to change the priority of an event after it has been added to the event + * queue of the robot. + * + * @param newPriority the new priority of this event + * @see AdvancedRobot#setEventPriority(String, int) + */ + public final void setPriority(int newPriority) { + if (addedToQueue) { + Logger.printlnToRobotsConsole( + "SYSTEM: The priority of an event cannot be changed after it has been added the event queue."); + } else { + setPriorityHidden(newPriority); + } + } + + /** + * Hidden method for setting the exact time when this event occurred. + *

+ * Notice: This method is called by the game engine only. + * + * @param time the time when this event occurred. + */ + // This method must be invisible on Robot API + private void setTimeHidden(long time) { + // we do not replace time which is set by robot to the future + if (this.time < time) { + this.time = time; + } + // when this flag is set, robots are not allowed to change the time or priority of the event anymore + addedToQueue = true; + } + + /** + * Hidden method for setting the priority from the game engine without checking for the 'addedToQueue' flag. + *

+ * Notice: This method is called by the game engine only. + * + * @param newPriority the new priority of this event. + */ + // This method must be invisible on Robot API + private void setPriorityHidden(int newPriority) { + if (newPriority < 0) { + Logger.printlnToRobotsConsole("SYSTEM: Priority must be between 0 and 99"); + Logger.printlnToRobotsConsole("SYSTEM: Priority for " + this.getClass().getName() + " will be 0"); + newPriority = 0; + } else if (newPriority > 99) { + Logger.printlnToRobotsConsole("SYSTEM: Priority must be between 0 and 99"); + Logger.printlnToRobotsConsole("SYSTEM: Priority for " + this.getClass().getName() + " will be 99"); + newPriority = 99; + } + priority = newPriority; + } + + /** + * Dispatch this event a the robot, it's statistics, and graphics context. + * + * @param robot the robot to dispatch to. + * @param statics the statistics to dispatch to. + * @param graphics the graphics to dispatch to. + */ + // This method must be invisible on Robot API + void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) {} + + /** + * Returns the default priority of this event class. + */ + // This method must be invisible on Robot API + int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * Checks if this event must be delivered even after timeout. + * + * @return {@code true} when this event must be delivered even after timeout; + * {@code false} otherwise. + */ + // This method must be invisible on Robot API + boolean isCriticalEvent() { + return false; + } + + // This method must be invisible on Robot API + byte getSerializationType() { + throw new Error("Serialization not supported on this event type"); + } + + /** + * Returns a hidden event helper for accessing hidden methods on this object. + */ + // This method must be invisible on Robot API + static IHiddenEventHelper createHiddenHelper() { + return new HiddenEventHelper(); + } + + /** + * Hidden event helper implementation for accessing the internal methods of an event. + *

+ * This class is used internally by the game engine. + */ + // This method must be invisible on Robot API + private static class HiddenEventHelper implements IHiddenEventHelper { + + public void setTime(Event event, long newTime) { + event.setTimeHidden(newTime); + } + + public void setDefaultPriority(Event event) { + event.setPriority(event.getDefaultPriority()); + } + + public void setPriority(Event event, int newPriority) { + event.setPriorityHidden(newPriority); + } + + public boolean isCriticalEvent(Event event) { + return event.isCriticalEvent(); + } + + public void dispatch(Event event, IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + event.dispatch(robot, statics, graphics); + } + + public byte getSerializationType(Event event) { + return event.getSerializationType(); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/GunTurnCompleteCondition.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/GunTurnCompleteCondition.java new file mode 100644 index 0000000..63deee1 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/GunTurnCompleteCondition.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * A prebuilt condition you can use that indicates your gun has finished + * turning. + * + * @see Condition + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Nathaniel Troutman (contributor) + */ +public class GunTurnCompleteCondition extends Condition { + private AdvancedRobot robot = null; + + /** + * Creates a new GunTurnCompleteCondition with default priority. + * The default priority is 80. + * + * @param robot your robot, which must be a {@link AdvancedRobot} + */ + public GunTurnCompleteCondition(AdvancedRobot robot) { + super(); + this.robot = robot; + } + + /** + * Creates a new GunTurnCompleteCondition with a specific priority. + * A condition priority is a value from 0 - 99. The higher value, the + * higher priority. The default priority is 80. + * + * @param robot your robot, which must be a {@link AdvancedRobot} + * @param priority the priority of this condition + * @see Condition#setPriority(int) + */ + public GunTurnCompleteCondition(AdvancedRobot robot, int priority) { + super(); + this.robot = robot; + this.priority = priority; + } + + /** + * Tests if the gun has stopped turning. + * + * @return {@code true} if the gun has stopped turning; {@code false} + * otherwise + */ + @Override + public boolean test() { + return (robot.getGunTurnRemaining() == 0); + } + + /** + * Called by the system in order to clean up references to internal objects. + * + * @since 1.4.3 + */ + @Override + public final void cleanup() { + robot = null; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/HitByBulletEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/HitByBulletEvent.java new file mode 100644 index 0000000..9d215d4 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/HitByBulletEvent.java @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A HitByBulletEvent is sent to {@link Robot#onHitByBullet(HitByBulletEvent) + * onHitByBullet()} when your robot has been hit by a bullet. + * You can use the information contained in this event to determine what to do. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class HitByBulletEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 20; + + private final double bearing; + private final Bullet bullet; + + /** + * Called by the game to create a new HitByBulletEvent. + * + * @param bearing the bearing of the bullet that hit your robot, in radians + * @param bullet the bullet that has hit your robot + */ + public HitByBulletEvent(double bearing, Bullet bullet) { + super(); + this.bearing = bearing; + this.bullet = bullet; + } + + /** + * Returns the bearing to the bullet, relative to your robot's heading, + * in degrees (-180 < getBearing() <= 180). + *

+ * If you were to turnRight(event.getBearing()), you would be facing the + * direction the bullet came from. The calculation used here is: + * (bullet's heading in degrees + 180) - (your heading in degrees) + * + * @return the bearing to the bullet, in degrees + */ + public double getBearing() { + return bearing * 180.0 / Math.PI; + } + + /** + * Returns the bearing to the bullet, relative to your robot's heading, + * in radians (-Math.PI < getBearingRadians() <= Math.PI). + *

+ * If you were to turnRightRadians(event.getBearingRadians()), you would be + * facing the direction the bullet came from. The calculation used here is: + * (bullet's heading in radians + Math.PI) - (your heading in radians) + * + * @return the bearing to the bullet, in radians + */ + public double getBearingRadians() { + return bearing; + } + + /** + * Returns the bullet that hit your robot. + * + * @return the bullet that hit your robot + */ + public Bullet getBullet() { + return bullet; + } + + /** + * Returns the heading of the bullet when it hit you, in degrees + * (0 <= getHeading() < 360). + *

+ * Note: This is not relative to the direction you are facing. The robot + * that fired the bullet was in the opposite direction of getHeading() when + * it fired the bullet. + * + * @return the heading of the bullet, in degrees + */ + public double getHeading() { + return bullet.getHeading(); + } + + /** + * @return the heading of the bullet, in degrees + * @deprecated Use {@link #getHeading()} instead. + */ + @Deprecated + public double getHeadingDegrees() { + return getHeading(); + } + + /** + * Returns the heading of the bullet when it hit you, in radians + * (0 <= getHeadingRadians() < 2 * PI). + *

+ * Note: This is not relative to the direction you are facing. The robot + * that fired the bullet was in the opposite direction of + * getHeadingRadians() when it fired the bullet. + * + * @return the heading of the bullet, in radians + */ + public double getHeadingRadians() { + return bullet.getHeadingRadians(); + } + + /** + * Returns the name of the robot that fired the bullet. + * + * @return the name of the robot that fired the bullet + */ + public String getName() { + return bullet.getName(); + } + + /** + * Returns the power of this bullet. The damage you take (in fact, already + * took) is 4 * power, plus 2 * (power-1) if power > 1. The robot that fired + * the bullet receives 3 * power back. + * + * @return the power of the bullet + */ + public double getPower() { + return bullet.getPower(); + } + + /** + * Returns the velocity of this bullet. + * + * @return the velocity of the bullet + */ + public double getVelocity() { + return bullet.getVelocity(); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onHitByBullet(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.HitByBulletEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + HitByBulletEvent obj = (HitByBulletEvent) object; + + return RbSerializer.SIZEOF_TYPEINFO + serializer.sizeOf(RbSerializer.Bullet_TYPE, obj.bullet) + + RbSerializer.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + HitByBulletEvent obj = (HitByBulletEvent) object; + + serializer.serialize(buffer, RbSerializer.Bullet_TYPE, obj.bullet); + serializer.serialize(buffer, obj.bearing); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + Bullet bullet = (Bullet) serializer.deserializeAny(buffer); + double bearing = buffer.getDouble(); + + return new HitByBulletEvent(bearing, bullet); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/HitRobotEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/HitRobotEvent.java new file mode 100644 index 0000000..81307c2 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/HitRobotEvent.java @@ -0,0 +1,209 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A HitRobotEvent is sent to {@link Robot#onHitRobot(HitRobotEvent) onHitRobot()} + * when your robot collides with another robot. + * You can use the information contained in this event to determine what to do. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class HitRobotEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 40; + + private final String robotName; + private final double bearing; + private final double energy; + private final boolean atFault; + + /** + * Called by the game to create a new HitRobotEvent. + * + * @param name the name of the robot you hit + * @param bearing the bearing to the robot that your robot hit, in radians + * @param energy the amount of energy of the robot you hit + * @param atFault {@code true} if your robot was moving toward the other + * robot; {@code false} otherwise + */ + public HitRobotEvent(String name, double bearing, double energy, boolean atFault) { + this.robotName = name; + this.bearing = bearing; + this.energy = energy; + this.atFault = atFault; + } + + /** + * Returns the bearing to the robot you hit, relative to your robot's + * heading, in degrees (-180 <= getBearing() < 180) + * + * @return the bearing to the robot you hit, in degrees + */ + public double getBearing() { + return bearing * 180.0 / Math.PI; + } + + /** + * @return the bearing to the robot you hit, in degrees + * @deprecated Use {@link #getBearing()} instead. + */ + @Deprecated + public double getBearingDegrees() { + return getBearing(); + } + + /** + * Returns the bearing to the robot you hit, relative to your robot's + * heading, in radians (-PI <= getBearingRadians() < PI) + * + * @return the bearing to the robot you hit, in radians + */ + public double getBearingRadians() { + return bearing; + } + + /** + * Returns the amount of energy of the robot you hit. + * + * @return the amount of energy of the robot you hit + */ + public double getEnergy() { + return energy; + } + + /** + * Returns the name of the robot you hit. + * + * @return the name of the robot you hit + */ + public String getName() { + return robotName; + } + + /** + * @return the name of the robot you hit + * @deprecated Use {@link #getName()} instead. + */ + @Deprecated + public String getRobotName() { + return robotName; + } + + /** + * Checks if your robot was moving towards the robot that was hit. + *

+ * If {@link #isMyFault()} returns {@code true} then your robot's movement + * (including turning) will have stopped and been marked complete. + *

+ * Note: If two robots are moving toward each other and collide, they will + * each receive two HitRobotEvents. The first will be the one if + * {@link #isMyFault()} returns {@code true}. + * + * @return {@code true} if your robot was moving towards the robot that was + * hit; {@code false} otherwise. + */ + public boolean isMyFault() { + return atFault; + } + + /** + * {@inheritDoc} + */ + @Override + public final int compareTo(Event event) { + final int res = super.compareTo(event); + + if (res != 0) { + return res; + } + + // Compare the isMyFault, if the events are HitRobotEvents + // The isMyFault has higher priority when it is set compared to when it is not set + if (event instanceof HitRobotEvent) { + int compare1 = (this).isMyFault() ? -1 : 0; + int compare2 = ((HitRobotEvent) event).isMyFault() ? -1 : 0; + + return compare1 - compare2; + } + + // No difference found + return 0; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onHitRobot(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.HitRobotEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + HitRobotEvent obj = (HitRobotEvent) object; + + return RbSerializer.SIZEOF_TYPEINFO + serializer.sizeOf(obj.robotName) + 2 * RbSerializer.SIZEOF_DOUBLE + + RbSerializer.SIZEOF_BOOL; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + HitRobotEvent obj = (HitRobotEvent) object; + + serializer.serialize(buffer, obj.robotName); + serializer.serialize(buffer, obj.bearing); + serializer.serialize(buffer, obj.energy); + serializer.serialize(buffer, obj.atFault); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + String robotName = serializer.deserializeString(buffer); + double bearing = buffer.getDouble(); + double energy = buffer.getDouble(); + boolean atFault = serializer.deserializeBoolean(buffer); + + return new HitRobotEvent(robotName, bearing, energy, atFault); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/HitWallEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/HitWallEvent.java new file mode 100644 index 0000000..4043070 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/HitWallEvent.java @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A HitWallEvent is sent to {@link Robot#onHitWall(HitWallEvent) onHitWall()} + * when you collide a wall. + * You can use the information contained in this event to determine what to do. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class HitWallEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 30; + + private final double bearing; + + /** + * Called by the game to create a new HitWallEvent. + * + * @param bearing the bearing to the wall that your robot hit, in radians + */ + public HitWallEvent(double bearing) { + this.bearing = bearing; + } + + /** + * Returns the bearing to the wall you hit, relative to your robot's + * heading, in degrees (-180 <= getBearing() < 180) + * + * @return the bearing to the wall you hit, in degrees + */ + public double getBearing() { + return bearing * 180.0 / Math.PI; + } + + /** + * @return the bearing to the wall you hit, in degrees + * @deprecated Use {@link #getBearing()} instead. + */ + @Deprecated + public double getBearingDegrees() { + return getBearing(); + } + + /** + * Returns the bearing to the wall you hit, relative to your robot's + * heading, in radians (-PI <= getBearingRadians() < PI) + * + * @return the bearing to the wall you hit, in radians + */ + public double getBearingRadians() { + return bearing; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onHitWall(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.HitWallEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + HitWallEvent obj = (HitWallEvent) object; + + serializer.serialize(buffer, obj.bearing); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + double bearing = buffer.getDouble(); + + return new HitWallEvent(bearing); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/JuniorRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/JuniorRobot.java new file mode 100644 index 0000000..8531c7b --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/JuniorRobot.java @@ -0,0 +1,907 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IJuniorRobot; +import robocode.robotinterfaces.peer.IJuniorRobotPeer; +import robocode.util.Utils; + +import java.awt.*; +import static java.lang.Math.toRadians; + + +/** + * This is the simplest robot type, which is simpler than the {@link Robot} and + * {@link AdvancedRobot} classes. The JuniorRobot has a simplified model, in + * purpose of teaching programming skills to inexperienced in programming + * students. The simplified robot model will keep player from overwhelming of + * Robocode's rules, programming syntax and programming concept. + *

+ * Instead of using getters and setters, public fields are provided for + * receiving information like the last scanned robot, the coordinate of the + * robot etc. + *

+ * All methods on this class are blocking calls, i.e. they do not return before + * their action has been completed and will at least take one turn to execute. + * However, setting colors is executed immediately and does not cost a turn to + * perform. + * + * @see Robot + * @see AdvancedRobot + * @see TeamRobot + * @see RateControlRobot + * @see Droid + * @see BorderSentry + * + * @author Nutch Poovarawan from Cubic Creative (designer) + * @author Flemming N. Larsen (original) + * @author Pavel Savara (contributor) + * + * @since 1.4 + */ +public class JuniorRobot extends _RobotBase implements IJuniorRobot { + + /** + * The color black (0x000000) + */ + public final static int black = 0x000000; + + /** + * The color white (0xFFFFFF) + */ + public final static int white = 0xFFFFFF; + + /** + * The color red (0xFF0000) + */ + public final static int red = 0xFF0000; + + /** + * The color orange (0xFFA500) + */ + public final static int orange = 0xFFA500; + + /** + * The color yellow (0xFFFF00) + */ + public final static int yellow = 0xFFFF00; + + /** + * The color green (0x008000) + */ + public final static int green = 0x008000; + + /** + * The color blue (0x0000FF) + */ + public final static int blue = 0x0000FF; + + /** + * The color purple (0x800080) + */ + public final static int purple = 0x800080; + + /** + * The color brown (0x8B4513) + */ + public final static int brown = 0x8B4513; + + /** + * The color gray (0x808080) + */ + public final static int gray = 0x808080; + + /** + * Contains the width of the battlefield. + * + * @see #fieldWidth + */ + public int fieldWidth; + + /** + * Contains the height of the battlefield. + * + * @see #fieldWidth + */ + public int fieldHeight; + + /** + * Current number of other robots on the battle field. + */ + public int others; + + /** + * Current energy of this robot, where 100 means full energy and 0 means no energy (dead). + */ + public int energy; + + /** + * Current horizontal location of this robot (in pixels). + * + * @see #robotY + */ + public int robotX; + + /** + * Current vertical location of this robot (in pixels). + * + * @see #robotX + */ + public int robotY; + + /** + * Current heading angle of this robot (in degrees). + * + * @see #turnLeft(int) + * @see #turnRight(int) + * @see #turnTo(int) + * @see #turnAheadLeft(int, int) + * @see #turnAheadRight(int, int) + * @see #turnBackLeft(int, int) + * @see #turnBackRight(int, int) + */ + public int heading; + + /** + * Current gun heading angle of this robot (in degrees). + * + * @see #gunBearing + * @see #turnGunLeft(int) + * @see #turnGunRight(int) + * @see #turnGunTo(int) + * @see #bearGunTo(int) + */ + public int gunHeading; + + /** + * Current gun heading angle of this robot compared to its body (in degrees). + * + * @see #gunHeading + * @see #turnGunLeft(int) + * @see #turnGunRight(int) + * @see #turnGunTo(int) + * @see #bearGunTo(int) + */ + public int gunBearing; + + /** + * Flag specifying if the gun is ready to fire, i.e. gun heat <= 0. + * {@code true} means that the gun is able to fire; {@code false} + * means that the gun cannot fire yet as it still needs to cool down. + * + * @see #fire() + * @see #fire(double) + */ + public boolean gunReady; + + /** + * Current distance to the scanned nearest other robot (in pixels). + * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + * This field will not be updated while {@link #onScannedRobot()} event is active. + * + * @see #onScannedRobot() + * @see #scannedAngle + * @see #scannedBearing + * @see #scannedEnergy + * @see #scannedVelocity + * @see #scannedHeading + */ + public int scannedDistance = -1; + + /** + * Current angle to the scanned nearest other robot (in degrees). + * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + * This field will not be updated while {@link #onScannedRobot()} event is active. + * + * @see #onScannedRobot() + * @see #scannedDistance + * @see #scannedBearing + * @see #scannedEnergy + * @see #scannedVelocity + * @see #scannedHeading + */ + public int scannedAngle = -1; + + /** + * Current angle to the scanned nearest other robot (in degrees) compared to + * the body of this robot. + * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + * This field will not be updated while {@link #onScannedRobot()} event is active. + * + * @see #onScannedRobot() + * @see #scannedDistance + * @see #scannedAngle + * @see #scannedEnergy + * @see #scannedVelocity + * @see #scannedHeading + */ + public int scannedBearing = -1; + + /** + * Current velocity of the scanned nearest other robot. + * If there is no robot in the radar's sight, this field will be -99. + * Note that a positive value means that the robot moves forward, a negative + * value means that the robot moved backward, and 0 means that the robot is + * not moving at all. + * This field will not be updated while {@link #onScannedRobot()} event is active. + * + * @see #onScannedRobot() + * @see #scannedDistance + * @see #scannedAngle + * @see #scannedBearing + * @see #scannedEnergy + * @see #scannedHeading + */ + public int scannedVelocity = -99; + + /** + * Current heading of the scanned nearest other robot (in degrees). + * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + * This field will not be updated while {@link #onScannedRobot()} event is active. + * + * @see #onScannedRobot() + * @see #scannedDistance + * @see #scannedAngle + * @see #scannedBearing + * @see #scannedEnergy + * @see #scannedVelocity + */ + public int scannedHeading = -1; + + /** + * Current energy of scanned nearest other robot. + * If there is no robot in the radar's sight, this field will be less than 0, i.e -1. + * This field will not be updated while {@link #onScannedRobot()} event is active. + * + * @see #onScannedRobot() + * @see #scannedDistance + * @see #scannedAngle + * @see #scannedBearing + * @see #scannedVelocity + */ + public int scannedEnergy = -1; + + /** + * Latest angle from where this robot was hit by a bullet (in degrees). + * If the robot has never been hit, this field will be less than 0, i.e. -1. + * This field will not be updated while {@link #onHitByBullet()} event is active. + * + * @see #onHitByBullet() + * @see #hitByBulletBearing + */ + public int hitByBulletAngle = -1; + + /** + * Latest angle from where this robot was hit by a bullet (in degrees) + * compared to the body of this robot. + * If the robot has never been hit, this field will be less than 0, i.e. -1. + * This field will not be updated while {@link #onHitByBullet()} event is active. + * + * @see #onHitByBullet() + * @see #hitByBulletAngle + */ + public int hitByBulletBearing = -1; + + /** + * Latest angle where this robot has hit another robot (in degrees). + * If this robot has never hit another robot, this field will be less than 0, i.e. -1. + * This field will not be updated while {@link #onHitRobot()} event is active. + * + * @see #onHitRobot() + * @see #hitRobotBearing + */ + public int hitRobotAngle = -1; + + /** + * Latest angle where this robot has hit another robot (in degrees) + * compared to the body of this robot. + * If this robot has never hit another robot, this field will be less than 0, i.e. -1. + * This field will not be updated while {@link #onHitRobot()} event is active. + * + * @see #onHitRobot() + * @see #hitRobotAngle + */ + public int hitRobotBearing = -1; + + /** + * Latest angle where this robot has hit a wall (in degrees). + * If this robot has never hit a wall, this field will be less than 0, i.e. -1. + * This field will not be updated while {@link #onHitWall()} event is active. + * + * @see #onHitWall() + * @see #hitWallBearing + */ + public int hitWallAngle = -1; + + /** + * Latest angle where this robot has hit a wall (in degrees) + * compared to the body of this robot. + * If this robot has never hit a wall, this field will be less than 0, i.e. -1. + * This field will not be updated while {@link #onHitWall()} event is active. + * + * @see #onHitWall() + * @see #hitWallAngle + */ + public int hitWallBearing = -1; + + /** + * The robot event handler for this robot. + */ + private InnerEventHandler innerEventHandler; + + /** + * Moves this robot forward by pixels. + * + * @param distance the amount of pixels to move forward + * @see #back(int) + * @see #robotX + * @see #robotY + */ + public void ahead(int distance) { + if (peer != null) { + peer.move(distance); + } else { + uninitializedException(); + } + } + + /** + * Moves this robot backward by pixels. + * + * @param distance the amount of pixels to move backward + * @see #ahead(int) + * @see #robotX + * @see #robotY + */ + public void back(int distance) { + ahead(-distance); + } + + /** + * Turns the gun to the specified angle (in degrees) relative to body of this robot. + * The gun will turn to the side with the shortest delta angle to the specified angle. + * + * @param angle the angle to turn the gun to relative to the body of this robot + * @see #gunHeading + * @see #gunBearing + * @see #turnGunLeft(int) + * @see #turnGunRight(int) + * @see #turnGunTo(int) + */ + public void bearGunTo(int angle) { + if (peer != null) { + peer.turnGun(Utils.normalRelativeAngle(peer.getBodyHeading() + toRadians(angle) - peer.getGunHeading())); + } else { + uninitializedException(); + } + } + + /** + * Skips a turn. + * + * @see #doNothing(int) + */ + public void doNothing() { + if (peer != null) { + peer.execute(); + } else { + uninitializedException(); + } + } + + /** + * Skips the specified number of turns. + * + * @param turns the number of turns to skip + * @see #doNothing() + */ + public void doNothing(int turns) { + if (turns <= 0) { + return; + } + if (peer != null) { + for (int i = 0; i < turns; i++) { + peer.execute(); + } + } else { + uninitializedException(); + } + } + + /** + * Fires a bullet with the default power of 1. + * If the gun heat is more than 0 and hence cannot fire, this method will + * suspend until the gun is ready to fire, and then fire a bullet. + * + * @see #gunReady + */ + public void fire() { + fire(1); + } + + /** + * Fires a bullet with the specified bullet power, which is between 0.1 and 3 + * where 3 is the maximum bullet power. + * If the gun heat is more than 0 and hence cannot fire, this method will + * suspend until the gun is ready to fire, and then fire a bullet. + * + * @param power between 0.1 and 3 + * @see #gunReady + */ + public void fire(double power) { + if (peer != null) { + getEventHandler().juniorFirePower = power; + peer.execute(); + } else { + uninitializedException(); + } + } + + /** + * Do not call this method! + *

+ * {@inheritDoc} + */ + public final IBasicEvents getBasicEventListener() { + return getEventHandler(); + } + + /** + * Do not call this method! + *

+ * {@inheritDoc} + */ + public final Runnable getRobotRunnable() { + return getEventHandler(); + } + + /** + * This event methods is called from the game when this robot has been hit + * by another robot's bullet. When this event occurs the + * {@link #hitByBulletAngle} and {@link #hitByBulletBearing} fields values + * are automatically updated. + * + * @see #hitByBulletAngle + * @see #hitByBulletBearing + */ + public void onHitByBullet() {} + + /** + * This event methods is called from the game when a bullet from this robot + * has hit another robot. When this event occurs the {@link #hitRobotAngle} + * and {@link #hitRobotBearing} fields values are automatically updated. + * + * @see #hitRobotAngle + * @see #hitRobotBearing + */ + public void onHitRobot() {} + + /** + * This event methods is called from the game when this robot has hit a wall. + * When this event occurs the {@link #hitWallAngle} and {@link #hitWallBearing} + * fields values are automatically updated. + * + * @see #hitWallAngle + * @see #hitWallBearing + */ + public void onHitWall() {} + + /** + * This event method is called from the game when the radar detects another + * robot. When this event occurs the {@link #scannedDistance}, + * {@link #scannedAngle}, {@link #scannedBearing}, and {@link #scannedEnergy} + * field values are automatically updated. + * + * @see #scannedDistance + * @see #scannedAngle + * @see #scannedBearing + * @see #scannedEnergy + */ + public void onScannedRobot() {} + + /** + * The main method in every robot. You must override this to set up your + * robot's basic behavior. + *

+ * Example: + *

+	 *   // A basic robot that moves around in a square
+	 *   public void run() {
+	 *       ahead(100);
+	 *       turnRight(90);
+	 *   }
+	 * 
+ * This method is automatically re-called when it has returned. + */ + public void run() {} + + /** + * Sets the colors of the robot. The color values are RGB values. + * You can use the colors that are already defined for this class. + * + * @param bodyColor the RGB color value for the body + * @param gunColor the RGB color value for the gun + * @param radarColor the RGB color value for the radar + * @see #setColors(int, int, int, int, int) + */ + public void setColors(int bodyColor, int gunColor, int radarColor) { + if (peer != null) { + peer.setBodyColor(new Color(bodyColor)); + peer.setGunColor(new Color(gunColor)); + peer.setRadarColor(new Color(radarColor)); + } else { + uninitializedException(); + } + } + + /** + * Sets the colors of the robot. The color values are RGB values. + * You can use the colors that are already defined for this class. + * + * @param bodyColor the RGB color value for the body + * @param gunColor the RGB color value for the gun + * @param radarColor the RGB color value for the radar + * @param bulletColor the RGB color value for the bullets + * @param scanArcColor the RGB color value for the scan arc + * @see #setColors(int, int, int) + */ + public void setColors(int bodyColor, int gunColor, int radarColor, int bulletColor, int scanArcColor) { + if (peer != null) { + peer.setBodyColor(new Color(bodyColor)); + peer.setGunColor(new Color(gunColor)); + peer.setRadarColor(new Color(radarColor)); + peer.setBulletColor(new Color(bulletColor)); + peer.setScanColor(new Color(scanArcColor)); + } else { + uninitializedException(); + } + } + + /** + * Moves this robot forward by pixels and turns this robot left by degrees + * at the same time. The robot will move in a curve that follows a perfect + * circle, and the moving and turning will end at the same time. + *

+ * Note that the max. velocity and max. turn rate is automatically adjusted, + * which means that the robot will move slower the sharper the turn is + * compared to the distance. + * + * @param distance the amount of pixels to move forward + * @param degrees the amount of degrees to turn to the left + * @see #heading + * @see #robotX + * @see #robotY + * @see #turnLeft(int) + * @see #turnRight(int) + * @see #turnTo(int) + * @see #turnAheadRight(int, int) + * @see #turnBackLeft(int, int) + * @see #turnBackRight(int, int) + */ + public void turnAheadLeft(int distance, int degrees) { + turnAheadRight(distance, -degrees); + } + + /** + * Moves this robot forward by pixels and turns this robot right by degrees + * at the same time. The robot will move in a curve that follows a perfect + * circle, and the moving and turning will end at the same time. + *

+ * Note that the max. velocity and max. turn rate is automatically adjusted, + * which means that the robot will move slower the sharper the turn is + * compared to the distance. + * + * @param distance the amount of pixels to move forward + * @param degrees the amount of degrees to turn to the right + * @see #heading + * @see #robotX + * @see #robotY + * @see #turnLeft(int) + * @see #turnRight(int) + * @see #turnTo(int) + * @see #turnAheadLeft(int, int) + * @see #turnBackLeft(int, int) + * @see #turnBackRight(int, int) + */ + public void turnAheadRight(int distance, int degrees) { + if (peer != null) { + ((IJuniorRobotPeer) peer).turnAndMove(distance, toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Moves this robot backward by pixels and turns this robot left by degrees + * at the same time. The robot will move in a curve that follows a perfect + * circle, and the moving and turning will end at the same time. + *

+ * Note that the max. velocity and max. turn rate is automatically adjusted, + * which means that the robot will move slower the sharper the turn is + * compared to the distance. + * + * @param distance the amount of pixels to move backward + * @param degrees the amount of degrees to turn to the left + * @see #heading + * @see #robotX + * @see #robotY + * @see #turnLeft(int) + * @see #turnRight(int) + * @see #turnTo(int) + * @see #turnAheadLeft(int, int) + * @see #turnAheadRight(int, int) + * @see #turnBackRight(int, int) + */ + public void turnBackLeft(int distance, int degrees) { + turnAheadRight(-distance, degrees); + } + + /** + * Moves this robot backward by pixels and turns this robot right by degrees + * at the same time. The robot will move in a curve that follows a perfect + * circle, and the moving and turning will end at the same time. + *

+ * Note that the max. velocity and max. turn rate is automatically adjusted, + * which means that the robot will move slower the sharper the turn is + * compared to the distance. + * + * @param distance the amount of pixels to move backward + * @param degrees the amount of degrees to turn to the right + * @see #heading + * @see #robotX + * @see #robotY + * @see #turnLeft(int) + * @see #turnRight(int) + * @see #turnTo(int) + * @see #turnAheadLeft(int, int) + * @see #turnAheadRight(int, int) + * @see #turnBackLeft(int, int) + */ + public void turnBackRight(int distance, int degrees) { + turnAheadRight(-distance, -degrees); + } + + /** + * Turns the gun left by degrees. + * + * @param degrees the amount of degrees to turn the gun to the left + * @see #gunHeading + * @see #gunBearing + * @see #turnGunRight(int) + * @see #turnGunTo(int) + * @see #bearGunTo(int) + */ + public void turnGunLeft(int degrees) { + turnGunRight(-degrees); + } + + /** + * Turns the gun right by degrees. + * + * @param degrees the amount of degrees to turn the gun to the right + * @see #gunHeading + * @see #gunBearing + * @see #turnGunLeft(int) + * @see #turnGunTo(int) + * @see #bearGunTo(int) + */ + public void turnGunRight(int degrees) { + if (peer != null) { + peer.turnGun(toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Turns the gun to the specified angle (in degrees). + * The gun will turn to the side with the shortest delta angle to the + * specified angle. + * + * @param angle the angle to turn the gun to + * @see #gunHeading + * @see #gunBearing + * @see #turnGunLeft(int) + * @see #turnGunRight(int) + * @see #bearGunTo(int) + */ + public void turnGunTo(int angle) { + if (peer != null) { + peer.turnGun(Utils.normalRelativeAngle(toRadians(angle) - peer.getGunHeading())); + } else { + uninitializedException(); + } + } + + /** + * Turns this robot left by degrees. + * + * @param degrees the amount of degrees to turn to the left + * @see #heading + * @see #turnRight(int) + * @see #turnTo(int) + * @see #turnAheadLeft(int, int) + * @see #turnAheadRight(int, int) + * @see #turnBackLeft(int, int) + * @see #turnBackRight(int, int) + */ + public void turnLeft(int degrees) { + turnRight(-degrees); + } + + /** + * Turns this robot right by degrees. + * + * @param degrees the amount of degrees to turn to the right + * @see #heading + * @see #turnLeft(int) + * @see #turnTo(int) + * @see #turnAheadLeft(int, int) + * @see #turnAheadRight(int, int) + * @see #turnBackLeft(int, int) + * @see #turnBackRight(int, int) + */ + public void turnRight(int degrees) { + if (peer != null) { + peer.turnBody(toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Turns this robot to the specified angle (in degrees). + * The robot will turn to the side with the shortest delta angle to the + * specified angle. + * + * @param angle the angle to turn this robot to + * @see #heading + * @see #turnLeft(int) + * @see #turnRight(int) + * @see #turnAheadLeft(int, int) + * @see #turnAheadRight(int, int) + * @see #turnBackLeft(int, int) + * @see #turnBackRight(int, int) + */ + public void turnTo(int angle) { + if (peer != null) { + peer.turnBody(Utils.normalRelativeAngle(toRadians(angle) - peer.getBodyHeading())); + } else { + uninitializedException(); + } + } + + /* + * Returns the event handler of this robot. + */ + private InnerEventHandler getEventHandler() { + if (innerEventHandler == null) { + innerEventHandler = new InnerEventHandler(); + } + return innerEventHandler; + } + + /* + * The JuniorRobot event handler, which implements the basic robot events, + * JuniorRobot event, and Runnable. + */ + private final class InnerEventHandler implements IBasicEvents, Runnable { + + private double juniorFirePower; + private long currentTurn; + + public void onBulletHit(BulletHitEvent event) {} + + public void onBulletHitBullet(BulletHitBulletEvent event) {} + + public void onBulletMissed(BulletMissedEvent event) {} + + public void onDeath(DeathEvent event) {} + + public void onHitByBullet(HitByBulletEvent event) { + double angle = peer.getBodyHeading() + event.getBearingRadians(); + + hitByBulletAngle = (int) (Math.toDegrees(Utils.normalAbsoluteAngle(angle)) + 0.5); + hitByBulletBearing = (int) (event.getBearing() + 0.5); + JuniorRobot.this.onHitByBullet(); + } + + public void onHitRobot(HitRobotEvent event) { + double angle = peer.getBodyHeading() + event.getBearingRadians(); + + hitRobotAngle = (int) (Math.toDegrees(Utils.normalAbsoluteAngle(angle)) + 0.5); + hitRobotBearing = (int) (event.getBearing() + 0.5); + JuniorRobot.this.onHitRobot(); + } + + public void onHitWall(HitWallEvent event) { + double angle = peer.getBodyHeading() + event.getBearingRadians(); + + hitWallAngle = (int) (Math.toDegrees(Utils.normalAbsoluteAngle(angle)) + 0.5); + hitWallBearing = (int) (event.getBearing() + 0.5); + JuniorRobot.this.onHitWall(); + } + + public void onRobotDeath(RobotDeathEvent event) { + others = peer.getOthers(); + } + + public void onScannedRobot(ScannedRobotEvent event) { + scannedDistance = (int) (event.getDistance() + 0.5); + scannedEnergy = Math.max(1, (int) (event.getEnergy() + 0.5)); + scannedAngle = (int) (Math.toDegrees( + Utils.normalAbsoluteAngle(peer.getBodyHeading() + event.getBearingRadians())) + + 0.5); + scannedBearing = (int) (event.getBearing() + 0.5); + scannedHeading = (int) (event.getHeading() + 0.5); + scannedVelocity = (int) (event.getVelocity() + 0.5); + + JuniorRobot.this.onScannedRobot(); + } + + public void onStatus(StatusEvent e) { + final RobotStatus s = e.getStatus(); + + others = peer.getOthers(); + energy = Math.max(1, (int) (s.getEnergy() + 0.5)); + robotX = (int) (s.getX() + 0.5); + robotY = (int) (s.getY() + 0.5); + heading = (int) (s.getHeading() + 0.5); + gunHeading = (int) (s.getGunHeading() + 0.5); + gunBearing = (int) (Utils.normalRelativeAngle(s.getGunHeading() - s.getHeading()) + 0.5); + gunReady = (s.getGunHeat() <= 0); + + currentTurn = e.getTime(); + + // Auto fire + if (juniorFirePower > 0 && gunReady && (peer.getGunTurnRemaining() == 0)) { + if (peer.setFire(juniorFirePower) != null) { + gunReady = false; + juniorFirePower = 0; + } + } + + // Reset event data + scannedDistance = -1; + scannedAngle = -1; + scannedBearing = -1; + scannedVelocity = -99; + scannedHeading = -1; + scannedEnergy = -1; + hitByBulletAngle = -1; + hitByBulletBearing = -1; + hitRobotAngle = -1; + hitRobotBearing = -1; + hitWallAngle = -1; + hitWallBearing = -1; + } + + public void onWin(WinEvent event) {} + + public void run() { + fieldWidth = (int) (peer.getBattleFieldWidth() + 0.5); + fieldHeight = (int) (peer.getBattleFieldHeight() + 0.5); + + // noinspection InfiniteLoopStatement + while (true) { + long lastTurn = currentTurn; // Used for the rescan check + + JuniorRobot.this.run(); // Run the code in the JuniorRobot + + // Make sure that we rescan if the robot did not execute anything this turn. + // When the robot executes the currentTurn will automatically be increased by 1, + // So when the turn stays the same, the robot did not take any action this turn. + if (lastTurn == currentTurn) { + peer.rescan(); // Spend a turn on rescanning + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyEvent.java new file mode 100644 index 0000000..4189d3e --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyEvent.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * Super class of all events that originates from the keyboard. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public abstract class KeyEvent extends Event { + private static final long serialVersionUID = 1L; + private final java.awt.event.KeyEvent source; + + /** + * Called by the game to create a new KeyEvent. + * + * @param source the source key event originating from the AWT. + */ + public KeyEvent(java.awt.event.KeyEvent source) { + this.source = source; + } + + /** + * Do not call this method! + *

+ * This method is used by the game to determine the type of the source key + * event that occurred in the AWT. + * + * @return the source key event that originates from the AWT. + */ + public java.awt.event.KeyEvent getSourceEvent() { + return source; + } + +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyPressedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyPressedEvent.java new file mode 100644 index 0000000..ba8d1f8 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyPressedEvent.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A KeyPressedEvent is sent to {@link Robot#onKeyPressed(java.awt.event.KeyEvent) + * onKeyPressed()} when a key has been pressed on the keyboard. + * + * @see KeyReleasedEvent + * @see KeyTypedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class KeyPressedEvent extends KeyEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new KeyPressedEvent. + * + * @param source the source key event originating from the AWT. + */ + public KeyPressedEvent(java.awt.event.KeyEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onKeyPressed(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.KeyPressedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_CHAR + RbSerializer.SIZEOF_INT + + RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG + RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_INT; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + KeyPressedEvent obj = (KeyPressedEvent) object; + java.awt.event.KeyEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getKeyChar()); + serializer.serialize(buffer, src.getKeyCode()); + serializer.serialize(buffer, src.getKeyLocation()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + char keyChar = buffer.getChar(); + int keyCode = buffer.getInt(); + int keyLocation = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new KeyPressedEvent( + new java.awt.event.KeyEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, keyCode, keyChar, + keyLocation)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyReleasedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyReleasedEvent.java new file mode 100644 index 0000000..0c44ab8 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyReleasedEvent.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A KeyReleasedEvent is sent to {@link Robot#onKeyReleased(java.awt.event.KeyEvent) + * onKeyReleased()} when a key has been released on the keyboard. + * + * @see KeyPressedEvent + * @see KeyTypedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class KeyReleasedEvent extends KeyEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new KeyReleasedEvent. + * + * @param source the source key event originating from the AWT. + */ + public KeyReleasedEvent(java.awt.event.KeyEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onKeyReleased(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.KeyReleasedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_CHAR + RbSerializer.SIZEOF_INT + + RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG + RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_INT; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + KeyReleasedEvent obj = (KeyReleasedEvent) object; + java.awt.event.KeyEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getKeyChar()); + serializer.serialize(buffer, src.getKeyCode()); + serializer.serialize(buffer, src.getKeyLocation()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + char keyChar = buffer.getChar(); + int keyCode = buffer.getInt(); + int keyLocation = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new KeyReleasedEvent( + new java.awt.event.KeyEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, keyCode, keyChar, + keyLocation)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyTypedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyTypedEvent.java new file mode 100644 index 0000000..271b0f1 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/KeyTypedEvent.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A KeyTypedEvent is sent to {@link Robot#onKeyTyped(java.awt.event.KeyEvent) + * onKeyTyped()} when a key has been typed (pressed and released) on the keyboard. + * + * @see KeyPressedEvent + * @see KeyReleasedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class KeyTypedEvent extends KeyEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new KeyTypedEvent. + * + * @param source the source key event originating from the AWT. + */ + public KeyTypedEvent(java.awt.event.KeyEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onKeyTyped(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.KeyTypedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_CHAR + RbSerializer.SIZEOF_INT + + RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG + RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_INT; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + KeyTypedEvent obj = (KeyTypedEvent) object; + java.awt.event.KeyEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getKeyChar()); + serializer.serialize(buffer, src.getKeyCode()); + serializer.serialize(buffer, src.getKeyLocation()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + char keyChar = buffer.getChar(); + int keyCode = buffer.getInt(); + int keyLocation = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new KeyTypedEvent( + new java.awt.event.KeyEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, keyCode, keyChar, + keyLocation)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MessageEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MessageEvent.java new file mode 100644 index 0000000..c9bbf08 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MessageEvent.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.ITeamEvents; +import robocode.robotinterfaces.ITeamRobot; + +import java.awt.*; +import java.io.Serializable; + + +/** + * A MessageEvent is sent to {@link TeamRobot#onMessageReceived(MessageEvent) + * onMessageReceived()} when a teammate sends a message to your robot. + * You can use the information contained in this event to determine what to do. + * + * @author Mathew A. Nelson (original) + */ +public final class MessageEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 75; + + private final String sender; + private final Serializable message; + + /** + * Called by the game to create a new MessageEvent. + * + * @param sender the name of the sending robot + * @param message the message for your robot + */ + public MessageEvent(String sender, Serializable message) { + this.sender = sender; + this.message = message; + } + + /** + * Returns the name of the sending robot. + * + * @return the name of the sending robot + */ + public String getSender() { + return sender; + } + + /** + * Returns the message itself. + * + * @return the message + */ + public Serializable getMessage() { + return message; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isTeamRobot()) { + ITeamEvents listener = ((ITeamRobot) robot).getTeamEventListener(); + + if (listener != null) { + listener.onMessageReceived(this); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + throw new Error("Serialization of event type not supported"); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseClickedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseClickedEvent.java new file mode 100644 index 0000000..0cda6f9 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseClickedEvent.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A MouseClickedEvent is sent to {@link Robot#onMouseClicked(java.awt.event.MouseEvent) + * onMouseClicked()} when the mouse is clicked inside the battle view. + * + * @see MousePressedEvent + * @see MouseReleasedEvent + * @see MouseEnteredEvent + * @see MouseExitedEvent + * @see MouseMovedEvent + * @see MouseDraggedEvent + * @see MouseWheelMovedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class MouseClickedEvent extends MouseEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new MouseClickedEvent. + * + * @param source the source mouse event originating from the AWT. + */ + public MouseClickedEvent(java.awt.event.MouseEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onMouseClicked(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.MouseClickedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 6 * RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + MouseClickedEvent obj = (MouseClickedEvent) object; + java.awt.event.MouseEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getButton()); + serializer.serialize(buffer, src.getClickCount()); + serializer.serialize(buffer, src.getX()); + serializer.serialize(buffer, src.getY()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseClickedEvent( + new java.awt.event.MouseEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, x, y, + clickCount, false, button)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseDraggedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseDraggedEvent.java new file mode 100644 index 0000000..4f57fe8 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseDraggedEvent.java @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A MouseDraggedEvent is sent to {@link Robot#onMouseDragged(java.awt.event.MouseEvent) + * onMouseDragged()} when the mouse is dragged inside the battle view. + * + * @see MouseClickedEvent + * @see MousePressedEvent + * @see MouseReleasedEvent + * @see MouseEnteredEvent + * @see MouseExitedEvent + * @see MouseMovedEvent + * @see MouseWheelMovedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class MouseDraggedEvent extends MouseEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new MouseDraggedEvent. + * + * @param source the source mouse event originating from the AWT. + */ + public MouseDraggedEvent(java.awt.event.MouseEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onMouseDragged(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.MouseDraggedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 6 * RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + MouseDraggedEvent obj = (MouseDraggedEvent) object; + java.awt.event.MouseEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getButton()); + serializer.serialize(buffer, src.getClickCount()); + serializer.serialize(buffer, src.getX()); + serializer.serialize(buffer, src.getY()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseDraggedEvent( + new java.awt.event.MouseEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, x, y, + clickCount, false, button)); + } + } + +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseEnteredEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseEnteredEvent.java new file mode 100644 index 0000000..18a91f2 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseEnteredEvent.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A MouseEnteredEvent is sent to {@link Robot#onMouseEntered(java.awt.event.MouseEvent) + * onMouseEntered()} when the mouse has entered the battle view. + * + * @see MouseClickedEvent + * @see MousePressedEvent + * @see MouseReleasedEvent + * @see MouseExitedEvent + * @see MouseMovedEvent + * @see MouseDraggedEvent + * @see MouseWheelMovedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class MouseEnteredEvent extends MouseEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new MouseEnteredEvent. + * + * @param source the source mouse event originating from the AWT. + */ + public MouseEnteredEvent(java.awt.event.MouseEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onMouseEntered(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.MouseEnteredEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 6 * RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + MouseEnteredEvent obj = (MouseEnteredEvent) object; + java.awt.event.MouseEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getButton()); + serializer.serialize(buffer, src.getClickCount()); + serializer.serialize(buffer, src.getX()); + serializer.serialize(buffer, src.getY()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseEnteredEvent( + new java.awt.event.MouseEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, x, y, + clickCount, false, button)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseEvent.java new file mode 100644 index 0000000..62836c8 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseEvent.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * Super class of all events that originates from the mouse. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public abstract class MouseEvent extends Event { + private static final long serialVersionUID = 1L; + private final java.awt.event.MouseEvent source; + + /** + * Called by the game to create a new MouseEvent. + * + * @param source the source mouse event originating from the AWT. + */ + public MouseEvent(java.awt.event.MouseEvent source) { + this.source = source; + } + + /** + * Do not call this method! + *

+ * This method is used by the game to determine the type of the source mouse + * event that occurred in the AWT. + * + * @return the source mouse event that originates from the AWT. + */ + public java.awt.event.MouseEvent getSourceEvent() { + return source; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseExitedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseExitedEvent.java new file mode 100644 index 0000000..f4e8907 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseExitedEvent.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A MouseExitedEvent is sent to {@link Robot#onMouseExited(java.awt.event.MouseEvent) + * onMouseExited()} when the mouse has exited the battle view. + * + * @see MouseClickedEvent + * @see MousePressedEvent + * @see MouseReleasedEvent + * @see MouseEnteredEvent + * @see MouseMovedEvent + * @see MouseDraggedEvent + * @see MouseWheelMovedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class MouseExitedEvent extends MouseEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new MouseExitedEvent. + * + * @param source the source mouse event originating from the AWT. + */ + public MouseExitedEvent(java.awt.event.MouseEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onMouseExited(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.MouseExitedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 6 * RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + MouseExitedEvent obj = (MouseExitedEvent) object; + java.awt.event.MouseEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getButton()); + serializer.serialize(buffer, src.getClickCount()); + serializer.serialize(buffer, src.getX()); + serializer.serialize(buffer, src.getY()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseExitedEvent( + new java.awt.event.MouseEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, x, y, + clickCount, false, button)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseMovedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseMovedEvent.java new file mode 100644 index 0000000..46cfa56 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseMovedEvent.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A MouseMovedEvent is sent to {@link Robot#onMouseMoved(java.awt.event.MouseEvent) + * onMouseMoved()} when the mouse has moved inside the battle view. + * + * @see MouseClickedEvent + * @see MousePressedEvent + * @see MouseReleasedEvent + * @see MouseEnteredEvent + * @see MouseExitedEvent + * @see MouseDraggedEvent + * @see MouseWheelMovedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class MouseMovedEvent extends MouseEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new MouseMovedEvent. + * + * @param source the source mouse event originating from the AWT. + */ + public MouseMovedEvent(java.awt.event.MouseEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onMouseMoved(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.MouseMovedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 6 * RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + MouseMovedEvent obj = (MouseMovedEvent) object; + java.awt.event.MouseEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getButton()); + serializer.serialize(buffer, src.getClickCount()); + serializer.serialize(buffer, src.getX()); + serializer.serialize(buffer, src.getY()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseMovedEvent( + new java.awt.event.MouseEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, x, y, + clickCount, false, button)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MousePressedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MousePressedEvent.java new file mode 100644 index 0000000..9b0ddb2 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MousePressedEvent.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A MousePressedEvent is sent to {@link Robot#onMousePressed(java.awt.event.MouseEvent) + * onMousePressed()} when the mouse is pressed inside the battle view. + * + * @see MouseClickedEvent + * @see MouseReleasedEvent + * @see MouseEnteredEvent + * @see MouseExitedEvent + * @see MouseMovedEvent + * @see MouseDraggedEvent + * @see MouseWheelMovedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class MousePressedEvent extends MouseEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new MousePressedEvent. + * + * @param source the source mouse event originating from the AWT. + */ + public MousePressedEvent(java.awt.event.MouseEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onMousePressed(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.MousePressedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 6 * RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + MousePressedEvent obj = (MousePressedEvent) object; + java.awt.event.MouseEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getButton()); + serializer.serialize(buffer, src.getClickCount()); + serializer.serialize(buffer, src.getX()); + serializer.serialize(buffer, src.getY()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MousePressedEvent( + new java.awt.event.MouseEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, x, y, + clickCount, false, button)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseReleasedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseReleasedEvent.java new file mode 100644 index 0000000..17a4323 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseReleasedEvent.java @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A MouseReleasedEvent is sent to {@link Robot#onMouseReleased(java.awt.event.MouseEvent) + * onMouseReleased()} when the mouse is released inside the battle view. + * + * @see MouseClickedEvent + * @see MousePressedEvent + * @see MouseEnteredEvent + * @see MouseExitedEvent + * @see MouseMovedEvent + * @see MouseDraggedEvent + * @see MouseWheelMovedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class MouseReleasedEvent extends MouseEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new MouseReleasedEvent. + * + * @param source the source mouse event originating from the AWT. + */ + public MouseReleasedEvent(java.awt.event.MouseEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onMouseReleased(getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.MouseReleasedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 6 * RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + MouseReleasedEvent obj = (MouseReleasedEvent) object; + java.awt.event.MouseEvent src = obj.getSourceEvent(); + + serializer.serialize(buffer, src.getButton()); + serializer.serialize(buffer, src.getClickCount()); + serializer.serialize(buffer, src.getX()); + serializer.serialize(buffer, src.getY()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int button = buffer.getInt(); + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseReleasedEvent( + new java.awt.event.MouseEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, x, y, + clickCount, false, button)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseWheelMovedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseWheelMovedEvent.java new file mode 100644 index 0000000..cb6e27b --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MouseWheelMovedEvent.java @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.security.SafeComponent; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.IInteractiveRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A MouseWheelMovedEvent is sent to {@link Robot#onMouseWheelMoved(java.awt.event.MouseWheelEvent e) + * onMouseWheelMoved()} when the mouse wheel is rotated inside the battle view. + * + * @see MouseClickedEvent + * @see MousePressedEvent + * @see MouseReleasedEvent + * @see MouseEnteredEvent + * @see MouseExitedEvent + * @see MouseMovedEvent + * @see MouseDraggedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public final class MouseWheelMovedEvent extends MouseEvent { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 98; + + /** + * Called by the game to create a new MouseWheelMovedEvent. + * + * @param source the source mouse event originating from the AWT. + */ + public MouseWheelMovedEvent(java.awt.event.MouseEvent source) { + super(source); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isInteractiveRobot()) { + IInteractiveEvents listener = ((IInteractiveRobot) robot).getInteractiveEventListener(); + + if (listener != null) { + listener.onMouseWheelMoved((java.awt.event.MouseWheelEvent) getSourceEvent()); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.MouseWheelMovedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 8 * RbSerializer.SIZEOF_INT + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + MouseWheelMovedEvent obj = (MouseWheelMovedEvent) object; + java.awt.event.MouseWheelEvent src = (java.awt.event.MouseWheelEvent) obj.getSourceEvent(); + + serializer.serialize(buffer, src.getClickCount()); + serializer.serialize(buffer, src.getX()); + serializer.serialize(buffer, src.getY()); + serializer.serialize(buffer, src.getScrollType()); + serializer.serialize(buffer, src.getScrollAmount()); + serializer.serialize(buffer, src.getWheelRotation()); + serializer.serialize(buffer, src.getID()); + serializer.serialize(buffer, src.getModifiersEx()); + serializer.serialize(buffer, src.getWhen()); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int clickCount = buffer.getInt(); + int x = buffer.getInt(); + int y = buffer.getInt(); + int scrollType = buffer.getInt(); + int scrollAmount = buffer.getInt(); + int wheelRotation = buffer.getInt(); + int id = buffer.getInt(); + int modifiersEx = buffer.getInt(); + long when = buffer.getLong(); + + return new MouseWheelMovedEvent( + new java.awt.event.MouseWheelEvent(SafeComponent.getSafeEventComponent(), id, when, modifiersEx, x, y, + clickCount, false, scrollType, scrollAmount, wheelRotation)); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/MoveCompleteCondition.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MoveCompleteCondition.java new file mode 100644 index 0000000..00ea5fc --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/MoveCompleteCondition.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * A prebuilt condition you can use that indicates your robot has finished + * moving. + * + * @see Condition + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Nathaniel Troutman (contributor) + */ +public class MoveCompleteCondition extends Condition { + private AdvancedRobot robot; + + /** + * Creates a new MoveCompleteCondition with default priority. + * The default priority is 80. + * + * @param robot your robot, which must be a {@link AdvancedRobot} + */ + public MoveCompleteCondition(AdvancedRobot robot) { + super(); + this.robot = robot; + } + + /** + * Creates a new MoveCompleteCondition with the specified priority. + * A condition priority is a value from 0 - 99. The higher value, the + * higher priority. The default priority is 80. + * + * @param robot your robot, which must be a {@link AdvancedRobot} + * @param priority the priority of this condition + * @see Condition#setPriority(int) + */ + public MoveCompleteCondition(AdvancedRobot robot, int priority) { + super(); + this.robot = robot; + this.priority = priority; + } + + /** + * Tests if the robot has stopped moving. + * + * @return {@code true} if the robot has stopped moving; {@code false} + * otherwise + */ + @Override + public boolean test() { + return (robot.getDistanceRemaining() == 0); + } + + /** + * Called by the system in order to clean up references to internal objects. + * + * @since 1.4.3 + */ + @Override + public void cleanup() { + robot = null; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/PaintEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/PaintEvent.java new file mode 100644 index 0000000..e189284 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/PaintEvent.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.IPaintEvents; +import robocode.robotinterfaces.IPaintRobot; + +import java.awt.*; + + +/** + * This event occurs when your robot should paint, where the {@link + * Robot#onPaint(Graphics2D) onPaint()} is called on your robot. + *

+ * You can use this event for setting the event priority by calling + * {@link AdvancedRobot#setEventPriority(String, int) + * setEventPriority("PaintEvent", priority)} + * + * @author Flemming N. Larsen (original) + */ +public final class PaintEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 5; + + /** + * Called by the game to create a new PaintEvent. + */ + public PaintEvent() { + super(); + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isPaintRobot()) { + IPaintEvents listener = ((IPaintRobot) robot).getPaintEventListener(); + + if (listener != null) { + listener.onPaint(graphics); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + throw new Error("Serialization of this type is not supported"); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/RadarTurnCompleteCondition.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RadarTurnCompleteCondition.java new file mode 100644 index 0000000..e5fc586 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RadarTurnCompleteCondition.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * A prebuilt condition you can use that indicates your radar has finished + * turning. + * + * @see Condition + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Nathaniel Troutman (contributor) + */ +public class RadarTurnCompleteCondition extends Condition { + private AdvancedRobot robot; + + /** + * Creates a new RadarTurnCompleteCondition with default priority. + * The default priority is 80. + * + * @param robot your robot, which must be a {@link AdvancedRobot} + */ + public RadarTurnCompleteCondition(AdvancedRobot robot) { + super(); + this.robot = robot; + } + + /** + * Creates a new RadarTurnCompleteCondition with the specified priority. + * A condition priority is a value from 0 - 99. The higher value, the + * higher priority. The default priority is 80. + * + * @param robot your robot, which must be a {@link AdvancedRobot} + * @param priority the priority of this condition + * @see Condition#setPriority(int) + */ + public RadarTurnCompleteCondition(AdvancedRobot robot, int priority) { + super(); + this.robot = robot; + this.priority = priority; + } + + /** + * Tests if the radar has stopped turning. + * + * @return {@code true} if the radar has stopped turning; {@code false} + * otherwise + */ + @Override + public boolean test() { + return (robot.getRadarTurnRemaining() == 0); + } + + /** + * Called by the system in order to clean up references to internal objects. + * + * @since 1.4.3 + */ + @Override + public void cleanup() { + robot = null; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/RateControlRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RateControlRobot.java new file mode 100644 index 0000000..1cb647d --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RateControlRobot.java @@ -0,0 +1,450 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import static java.lang.Math.toRadians; +import static java.lang.Math.toDegrees; + + +/** + * This advanced robot type allows you to set a rate for each of the robot's movements. + *

+ * You can set the rate for:

    + *
  • velocity - pixels per turn
  • + *
  • robot turn - radians per turn
  • + *
  • gun rotation - radians per turn
  • + *
  • radar rotation - radians per turn
  • + *
+ * When you set a rate for one of the above movements, the movement will continue the move by + * specified rate for ever, until the rate is changed. In order to move ahead or right, the + * rate must be set to a positive value. If a negative value is used instead, the movement + * will go back or to the left. In order to stop the movement, the rate must be + * set to 0. + *

+ * Note: When calling {@code setVelocityRate()}, {@code setTurnRate()}, {@code setGunRotationRate()}, + * {@code setRadarRotationRate()} and variants, Any previous calls to "movement" functions outside of + * {@code RateControlRobot}, such as {@code setAhead()}, {@code setTurnLeft()}, + * {@code setTurnRadarRightRadians()} and similar will be overridden when calling the + * {@link #execute() execute()} on this robot class. + *

+ * Look into the source code for the {@code sample.VelociRobot} in order to see how to use this + * robot type. + * + * @see JuniorRobot + * @see Robot + * @see AdvancedRobot + * @see TeamRobot + * @see Droid + * @see BorderSentry + * + * @author Joshua Galecki (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.7.1.3 + */ +public class RateControlRobot extends TeamRobot { + + private double velocityRate; // Pixels per turn + private double turnRate; // Radians per turn + private double gunRotationRate; // Radians per turn + private double radarRotationRate; // Radians per turn + + /** + * Sets the speed the robot will move (forward), in pixels per turn. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot will move backwards + *

+ * Example: + *

+	 *   // Set the robot to move forward 2 pixels per turn
+	 *   setVelocityRate(2);
+	 *
+	 *   // Set the robot to move backwards 8 pixels per turn
+	 *   // (overrides the previous order)
+	 *   setVelocityRate(-8);
+	 *
+	 *   ...
+	 *   // Executes the last setVelocityRate()
+	 *   execute();
+	 * 
+ * + * Note: This method overrules {@link robocode.AdvancedRobot#setAhead(double)} and + * {@link robocode.AdvancedRobot#setBack(double)}. + * + * @param velocityRate pixels per turn the robot will move. + * + * @see #getVelocityRate() + * @see #setTurnRate(double) + * @see #setGunRotationRate(double) + * @see #setRadarRotationRate(double) + * @see AdvancedRobot#setAhead(double) + * @see AdvancedRobot#setBack(double) + */ + public void setVelocityRate(double velocityRate) { + this.velocityRate = velocityRate; + } + + /** + * Returns the speed the robot will move, in pixels per turn. + * Positive values means that the robot will move forward. + * Negative values means that the robot will move backwards. + * If the value is 0, the robot will stand still. + * + * @return The speed of the robot in pixels per turn + * + * @see #setVelocityRate(double) + */ + public double getVelocityRate() { + return velocityRate; + } + + /** + * Sets the robot's clockwise (right) rotation per turn, in degrees. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot turns counterclockwise (left) + *

+ * Example: + *

+	 *   // Set the robot to turn right 10 degrees per turn
+	 *   setTurnRate(10);
+	 *
+	 *   // Set the robot to turn left 4 degrees per turn
+	 *   // (overrides the previous order)
+	 *   setTurnRate(-5);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnRate()
+	 *   execute();
+	 * 
+ * + * @param turnRate angle of the clockwise rotation, in degrees. + * + * @see #getTurnRate() + * @see #setVelocityRate(double) + * @see #setGunRotationRate(double) + * @see #setRadarRotationRate(double) + * @see AdvancedRobot#setTurnRight(double) + * @see AdvancedRobot#setTurnLeft(double) + */ + public void setTurnRate(double turnRate) { + this.turnRate = toRadians(turnRate); + } + + /** + * Gets the robot's clockwise rotation per turn, in degrees. + * Positive values means that the robot will turn to the right. + * Negative values means that the robot will turn to the left. + * If the value is 0, the robot will not turn. + * + * @return Angle of the clockwise rotation, in degrees. + * + * @see #setTurnRate(double) + */ + public double getTurnRate() { + return toDegrees(turnRate); + } + + /** + * Sets the robot's clockwise (right) rotation per turn, in radians. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot turns counterclockwise (left) + *

+ * Example: + *

+	 *   // Set the robot to turn right pi / 32 radians per turn
+	 *   setTurnRateRadians(Math.PI / 32);
+	 *
+	 *   // Set the robot to turn left pi / 20 radians per turn
+	 *   // (overrides the previous order)
+	 *   setTurnRateRadians(-Math.PI / 20);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnRateRadians()
+	 *   execute();
+	 * 
+ * + * @param turnRate angle of the clockwise rotation, in radians. + * + * @see #getTurnRateRadians()() + * @see #setVelocityRate(double) + * @see #setGunRotationRateRadians(double) + * @see #setRadarRotationRateRadians(double) + * @see AdvancedRobot#setTurnRightRadians(double) + * @see AdvancedRobot#setTurnLeftRadians(double) + */ + public void setTurnRateRadians(double turnRate) { + this.turnRate = turnRate; + } + + /** + * Gets the robot's clockwise rotation per turn, in radians. + * Positive values means that the robot will turn to the right. + * Negative values means that the robot will turn to the left. + * If the value is 0, the robot will not turn. + * + * @return Angle of the clockwise rotation, in radians. + * + * @see #getTurnRateRadians() + */ + public double getTurnRateRadians() { + return turnRate; + } + + /** + * Sets the gun's clockwise (right) rotation per turn, in degrees. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the gun turns counterclockwise (left) + *

+ * Example: + *

+	 *   // Set the gun to turn right 15 degrees per turn
+	 *   setGunRotationRate(15);
+	 *
+	 *   // Set the gun to turn left 9 degrees per turn
+	 *   // (overrides the previous order)
+	 *   setGunRotationRate(-9);
+	 *
+	 *   ...
+	 *   // Executes the last setGunRotationRate()
+	 *   execute();
+	 * 
+ * + * @param gunRotationRate angle of the clockwise rotation, in degrees. + * + * @see #getGunRotationRate() + * @see #setVelocityRate(double) + * @see #setTurnRate(double) + * @see #setRadarRotationRate(double) + * @see AdvancedRobot#setTurnGunRight(double) + * @see AdvancedRobot#setTurnGunLeft(double) + */ + public void setGunRotationRate(double gunRotationRate) { + this.gunRotationRate = toRadians(gunRotationRate); + } + + /** + * Gets the gun's clockwise rotation per turn, in degrees. + * Positive values means that the gun will turn to the right. + * Negative values means that the gun will turn to the left. + * If the value is 0, the gun will not turn. + * + * @return Angle of the clockwise rotation, in degrees. + * + * @see #setGunRotationRate(double) + */ + public double getGunRotationRate() { + return toDegrees(gunRotationRate); + } + + /** + * Sets the gun's clockwise (right) rotation per turn, in radians. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the gun turns counterclockwise (left) + *

+ * Example: + *

+	 *   // Set the gun to turn right pi / 16 radians per turn
+	 *   setGunRotationRateRadians(Math.PI / 16);
+	 *
+	 *   // Set the gun to turn left pi / 12 radians per turn
+	 *   // (overrides the previous order)
+	 *   setGunRotationRateRadians(-Math.PI / 12);
+	 *
+	 *   ...
+	 *   // Executes the last setGunRotationRateRadians()
+	 *   execute();
+	 * 
+ * + * @param gunRotationRate angle of the clockwise rotation, in radians. + * + * @see #getGunRotationRateRadians() + * @see #setVelocityRate(double) + * @see #setTurnRateRadians(double) + * @see #setRadarRotationRateRadians(double) + * @see AdvancedRobot#setTurnGunRightRadians(double) + * @see AdvancedRobot#setTurnGunLeftRadians(double) + */ + public void setGunRotationRateRadians(double gunRotationRate) { + this.gunRotationRate = gunRotationRate; + } + + /** + * Gets the gun's clockwise rotation per turn, in radians. + * Positive values means that the gun will turn to the right. + * Negative values means that the gun will turn to the left. + * If the value is 0, the gun will not turn. + * + * @return Angle of the clockwise rotation, in radians. + * + * @see #setGunRotationRateRadians(double) + */ + public double getGunRotationRateRadians() { + return gunRotationRate; + } + + /** + * Sets the radar's clockwise (right) rotation per turn, in degrees. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the radar turns counterclockwise (left) + *

+ * Example: + *

+	 *   // Set the radar to turn right 45 degrees per turn
+	 *   setRadarRotationRate(45);
+	 *
+	 *   // Set the radar to turn left 15 degrees per turn
+	 *   // (overrides the previous order)
+	 *   setRadarRotationRate(-15);
+	 *
+	 *   ...
+	 *   // Executes the last setRadarRotationRate()
+	 *   execute();
+	 * 
+ * + * @param radarRotationRate angle of the clockwise rotation, in degrees. + * + * @see #getRadarRotationRate() + * @see #setVelocityRate(double) + * @see #setTurnRate(double) + * @see #setGunRotationRate(double) + * @see AdvancedRobot#setTurnRadarRight(double) + * @see AdvancedRobot#setTurnRadarLeft(double) + */ + public void setRadarRotationRate(double radarRotationRate) { + this.radarRotationRate = toRadians(radarRotationRate); + } + + /** + * Gets the radar's clockwise rotation per turn, in degrees. + * Positive values means that the radar will turn to the right. + * Negative values means that the radar will turn to the left. + * If the value is 0, the radar will not turn. + * + * @return Angle of the clockwise rotation, in degrees. + * + * @see #setRadarRotationRate(double) + */ + public double getRadarRotationRate() { + return toDegrees(radarRotationRate); + } + + /** + * Sets the radar's clockwise (right) rotation per turn, in radians. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the radar turns counterclockwise (left) + *

+ * Example: + *

+	 *   // Set the radar to turn right pi / 4 radians per turn
+	 *   setRadarRotationRateRadians(Math.PI / 4);
+	 *
+	 *   // Set the radar to turn left pi / 8 radians per turn
+	 *   // (overrides the previous order)
+	 *   setRadarRotationRateRadians(-Math.PI / 8);
+	 *
+	 *   ...
+	 *   // Executes the last setRadarRotationRateRadians()
+	 *   execute();
+	 * 
+ * + * @param radarRotationRate angle of the clockwise rotation, in radians. + * + * @see #getRadarRotationRateRadians() + * @see #setVelocityRate(double) + * @see #setTurnRateRadians(double) + * @see #setGunRotationRateRadians(double) + * @see AdvancedRobot#setTurnRadarRightRadians(double) + * @see AdvancedRobot#setTurnRadarLeftRadians(double) + */ + public void setRadarRotationRateRadians(double radarRotationRate) { + this.radarRotationRate = radarRotationRate; + } + + /** + * Gets the radar's clockwise rotation per turn, in radians. + * Positive values means that the radar will turn to the right. + * Negative values means that the radar will turn to the left. + * If the value is 0, the radar will not turn. + * + * @return Angle of the clockwise rotation, in radians. + * + * @see #setRadarRotationRateRadians(double) + */ + public double getRadarRotationRateRadians() { + return radarRotationRate; + } + + /** + * Executes any pending actions, or continues executing actions that are + * in process. This call returns after the actions have been started. + *

+ * Note that advanced robots must call this function in order to + * execute pending set* calls like e.g. {@code setVelocityRate()}, {@code setFire()}, + * {@code setTurnRate()} etc. Otherwise, these calls will never get executed. + *

+ * Any previous calls to "movement" functions outside of {@code RateControlRobot}, + * such as {@code setAhead()}, {@code setTurnLeft()}, {@code setTurnRadarLeftRadians()} + * etc. will be overridden when this method is called on this robot class. + *

+ * In this example the robot will move while turning: + *

+	 *   setVelocityRate(6);
+	 *   setTurnRate(7);
+	 *
+	 *   while (true) {
+	 *       execute();
+	 *   }
+	 * 
+ */ + @Override + public void execute() { + setMaxVelocity(velocityRate); + if (velocityRate > 0) { + setAhead(Double.POSITIVE_INFINITY); + } else if (velocityRate < 0) { + setBack(Double.POSITIVE_INFINITY); + } else { + setAhead(0); + } + + setTurnGunRightRadians(gunRotationRate); + setTurnRadarRightRadians(radarRotationRate); + setTurnRightRadians(turnRate); + + super.execute(); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/Robocode.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Robocode.java new file mode 100644 index 0000000..d9fad25 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Robocode.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.security.HiddenAccess; + + +/** + * Robocode - A programming game involving battling AI tanks.
+ * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * + * @see
robocode.sourceforge.net + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Pavel Savara (contributor) + */ +public class Robocode { + + public static void main(final String[] args) { + HiddenAccess.robocodeMain(args); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobocodeFileOutputStream.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobocodeFileOutputStream.java new file mode 100644 index 0000000..3972331 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobocodeFileOutputStream.java @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.core.ContainerBase; +import net.sf.robocode.security.IThreadManagerBase; +import robocode.exception.RobotException; + +import java.io.*; + + +/** + * RobocodeFileOutputStream is similar to a {@link java.io.FileOutputStream} + * and is used for streaming/writing data out to a file, which you got + * previously by calling {@link AdvancedRobot#getDataFile(String) getDataFile()}. + *

+ * You should read {@link java.io.FileOutputStream} for documentation of this + * class. + *

+ * Please notice that the max. size of your data file is set to 200000 + * (~195 KB). + * + * @see AdvancedRobot#getDataFile(String) + * @see java.io.FileOutputStream + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobocodeFileOutputStream extends OutputStream { + private final FileOutputStream out; + private final String fileName; + + /** + * Constructs a new RobocodeFileOutputStream. + * See {@link java.io.FileOutputStream#FileOutputStream(File)} + * for documentation about this constructor. + * + * @see java.io.FileOutputStream#FileOutputStream(File) + */ + public RobocodeFileOutputStream(File file) throws IOException { + this(file.getPath()); + } + + /** + * Constructs a new RobocodeFileOutputStream. + * See {@link java.io.FileOutputStream#FileOutputStream(FileDescriptor)} + * for documentation about this constructor. + * + * @see java.io.FileOutputStream#FileOutputStream(FileDescriptor) + */ + public RobocodeFileOutputStream(FileDescriptor fdObj) { + throw new RobotException("Creating a RobocodeFileOutputStream with a FileDescriptor is not supported."); + } + + /** + * Constructs a new RobocodeFileOutputStream. + * See {@link java.io.FileOutputStream#FileOutputStream(String)} + * for documentation about this constructor. + * + * @see java.io.FileOutputStream#FileOutputStream(String) + */ + public RobocodeFileOutputStream(String fileName) throws java.io.IOException { + this(fileName, false); + } + + /** + * Constructs a new RobocodeFileOutputStream. + * See {@link java.io.FileOutputStream#FileOutputStream(String, boolean)} + * for documentation about this constructor. + * + * @see java.io.FileOutputStream#FileOutputStream(String, boolean) + */ + public RobocodeFileOutputStream(String fileName, boolean append) throws IOException { + this.fileName = fileName; + + final IThreadManagerBase threadManager = ContainerBase.getComponent(IThreadManagerBase.class); + + if (threadManager == null) { + throw new RobotException("ThreadManager cannot be null!"); + } + + out = threadManager.createRobotFileStream(fileName, append); + } + + /** + * Closes this output stream. See {@link java.io.FileOutputStream#close()} + * for documentation about this method. + * + * @see java.io.FileOutputStream#close() + */ + @Override + public final void close() throws IOException { + out.close(); + } + + /** + * Flushes this output stream. See {@link java.io.FileOutputStream#flush()} + * for documentation about this method. + * + * @see java.io.FileOutputStream#flush() + */ + @Override + public final void flush() throws IOException { + out.flush(); + } + + /** + * Returns the filename of this output stream. + * + * @return the filename of this output stream. + */ + public final String getName() { + return fileName; + } + + /** + * Writes a byte array to this output stream. + * See {@link java.io.FileOutputStream#write(byte[])} for documentation + * about this method. + * + * @see java.io.FileOutputStream#write(byte[]) + */ + @Override + public final void write(byte[] b) throws IOException { + out.write(b); + } + + /** + * Writes a byte array to this output stream. + * See {@link java.io.FileOutputStream#write(byte[], int, int)} for + * documentation about this method. + * + * @see java.io.FileOutputStream#write(byte[], int, int) + */ + @Override + public final void write(byte[] b, int off, int len) throws IOException { + out.write(b, off, len); + } + + /** + * Writes a single byte to this output stream. + * See {@link java.io.FileOutputStream#write(int)} for documentation about + * this method. + * + * @see java.io.FileOutputStream#write(int) + */ + @Override + public final void write(int b) throws IOException { + out.write(b); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobocodeFileWriter.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobocodeFileWriter.java new file mode 100644 index 0000000..98cd0d8 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobocodeFileWriter.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import java.io.File; +import java.io.FileDescriptor; +import java.io.IOException; + + +/** + * RobocodeFileWriter is similar to a {@link java.io.FileWriter} and is used for + * writing data out to a file, which you got by calling {@link + * AdvancedRobot#getDataFile(String) getDataFile()}. + *

+ * You should read {@link java.io.FileWriter} for documentation of this class. + *

+ * Please notice that the max. size of your data file is set to 200000 + * (~195 KB). + * + * @see AdvancedRobot#getDataFile(String) + * @see java.io.FileWriter + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobocodeFileWriter extends java.io.OutputStreamWriter { + + /** + * Constructs a new RobocodeFileWriter. + * See {@link java.io.FileWriter#FileWriter(File)} for documentation about + * this constructor. + * + * @param file the file to write to. + * @throws java.io.IOException if an I/O exception occurs. + * @see java.io.FileWriter#FileWriter(File) + */ + public RobocodeFileWriter(File file) throws IOException { + super(new RobocodeFileOutputStream(file)); + } + + /** + * Constructs a new RobocodeFileWriter. + * See {@link java.io.FileWriter#FileWriter(FileDescriptor)} for + * documentation about this constructor. + * + * @param fd the file descriptor of the file to write to. + * @see java.io.FileWriter#FileWriter(FileDescriptor) + */ + public RobocodeFileWriter(FileDescriptor fd) { + super(new RobocodeFileOutputStream(fd)); + } + + /** + * Constructs a new RobocodeFileWriter. + * See {@link java.io.FileWriter#FileWriter(String)} for documentation about + * this constructor. + * + * @param fileName the filename of the file to write to. + * @throws java.io.IOException if an I/O exception occurs. + * @see java.io.FileWriter#FileWriter(String) + */ + public RobocodeFileWriter(String fileName) throws IOException { + super(new RobocodeFileOutputStream(fileName)); + } + + /** + * Constructs a new RobocodeFileWriter. + * See {@link java.io.FileWriter#FileWriter(String, boolean)} for + * documentation about this constructor. + * + * @param fileName the filename of the file to write to. + * @param append set this to true if the output must be appended to the file. + * @throws java.io.IOException if an I/O exception occurs. + * @see java.io.FileWriter#FileWriter(String, boolean) + */ + public RobocodeFileWriter(String fileName, boolean append) throws IOException { + super(new RobocodeFileOutputStream(fileName, append)); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/Robot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Robot.java new file mode 100644 index 0000000..d289a5d --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Robot.java @@ -0,0 +1,1550 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import robocode.robotinterfaces.*; +import robocode.robotinterfaces.peer.IStandardRobotPeer; + +import java.awt.*; + + +/** + * The basic robot class that you will extend to create your own robots. + *

+ *

Please note the following standards will be used: + *
heading - absolute angle in degrees with 0 facing up the screen, + * positive clockwise. 0 <= heading < 360. + *
bearing - relative angle to some object from your robot's heading, + * positive clockwise. -180 < bearing <= 180 + *
All coordinates are expressed as (x,y). + *
All coordinates are positive. + *
The origin (0,0) is at the bottom left of the screen. + *
Positive x is right. + *
Positive y is up. + * + * @see + * robocode.sourceforge.net + * @see + * Building your first robot + * + * @see JuniorRobot + * @see AdvancedRobot + * @see TeamRobot + * @see Droid + * @see RateControlRobot + * @see BorderSentry + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Matthew Reeder (contributor) + * @author Stefan Westen (contributor) + * @author Pavel Savara (contributor) + */ +public class Robot extends _Robot implements IInteractiveRobot, IPaintRobot, IBasicEvents3, IInteractiveEvents, IPaintEvents { + + private static final int + WIDTH = 36, + HEIGHT = 36; + + /** + * Constructs a new robot. + */ + public Robot() {} + + /** + * {@inheritDoc}} + */ + public final Runnable getRobotRunnable() { + return this; + } + + /** + * {@inheritDoc}} + */ + public final IBasicEvents getBasicEventListener() { + return this; + } + + /** + * {@inheritDoc}} + */ + public final IInteractiveEvents getInteractiveEventListener() { + return this; + } + + /** + * {@inheritDoc}} + */ + public final IPaintEvents getPaintEventListener() { + return this; + } + + /** + * Immediately moves your robot ahead (forward) by distance measured in + * pixels. + *

+ * This call executes immediately, and does not return until it is complete, + * i.e. when the remaining distance to move is 0. + *

+ * If the robot collides with a wall, the move is complete, meaning that the + * robot will not move any further. If the robot collides with another + * robot, the move is complete if you are heading toward the other robot. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot is set to move backward + * instead of forward. + *

+ * Example: + *

+	 *   // Move the robot 100 pixels forward
+	 *   ahead(100);
+	 *
+	 *   // Afterwards, move the robot 50 pixels backward
+	 *   ahead(-50);
+	 * 
+ * + * @param distance the distance to move ahead measured in pixels. + * If this value is negative, the robot will move back instead of ahead. + * @see #back(double) + * @see #onHitWall(HitWallEvent) + * @see #onHitRobot(HitRobotEvent) + */ + public void ahead(double distance) { + if (peer != null) { + peer.move(distance); + } else { + uninitializedException(); + } + } + + /** + * Immediately moves your robot backward by distance measured in pixels. + *

+ * This call executes immediately, and does not return until it is complete, + * i.e. when the remaining distance to move is 0. + *

+ * If the robot collides with a wall, the move is complete, meaning that the + * robot will not move any further. If the robot collides with another + * robot, the move is complete if you are heading toward the other robot. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot is set to move forward instead + * of backward. + *

+ * Example: + *

+	 *   // Move the robot 100 pixels backward
+	 *   back(100);
+	 *
+	 *   // Afterwards, move the robot 50 pixels forward
+	 *   back(-50);
+	 * 
+ * + * @param distance the distance to move back measured in pixels. + * If this value is negative, the robot will move ahead instead of back. + * @see #ahead(double) + * @see #onHitWall(HitWallEvent) + * @see #onHitRobot(HitRobotEvent) + */ + public void back(double distance) { + if (peer != null) { + peer.move(-distance); + } else { + uninitializedException(); + } + } + + /** + * Returns the width of the current battlefield measured in pixels. + * + * @return the width of the current battlefield measured in pixels. + */ + public double getBattleFieldWidth() { + if (peer != null) { + return peer.getBattleFieldWidth(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the height of the current battlefield measured in pixels. + * + * @return the height of the current battlefield measured in pixels. + */ + public double getBattleFieldHeight() { + if (peer != null) { + return peer.getBattleFieldHeight(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the direction that the robot's body is facing, in degrees. + * The value returned will be between 0 and 360 (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * 90 means East, 180 means South, and 270 means West. + * + * @return the direction that the robot's body is facing, in degrees. + * @see #getGunHeading() + * @see #getRadarHeading() + */ + public double getHeading() { + if (peer != null) { + double rv = 180.0 * peer.getBodyHeading() / Math.PI; + + while (rv < 0) { + rv += 360; + } + while (rv >= 360) { + rv -= 360; + } + return rv; + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the height of the robot measured in pixels. + * + * @return the height of the robot measured in pixels. + * @see #getWidth() + */ + public double getHeight() { + if (peer == null) { + uninitializedException(); + } + return HEIGHT; + } + + /** + * Returns the width of the robot measured in pixels. + * + * @return the width of the robot measured in pixels. + * @see #getHeight() + */ + public double getWidth() { + if (peer == null) { + uninitializedException(); + } + return WIDTH; + } + + /** + * Returns the robot's name. + * + * @return the robot's name. + */ + public String getName() { + if (peer != null) { + return peer.getName(); + } + uninitializedException(); + return null; // never called + } + + /** + * Returns the X position of the robot. (0,0) is at the bottom left of the + * battlefield. + * + * @return the X position of the robot. + * @see #getY() + */ + public double getX() { + if (peer != null) { + return peer.getX(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the Y position of the robot. (0,0) is at the bottom left of the + * battlefield. + * + * @return the Y position of the robot. + * @see #getX() + */ + public double getY() { + if (peer != null) { + return peer.getY(); + } + uninitializedException(); + return 0; // never called + } + + /** + * The main method in every robot. You must override this to set up your + * robot's basic behavior. + *

+ * Example: + *

+	 *   // A basic robot that moves around in a square
+	 *   public void run() {
+	 *       while (true) {
+	 *           ahead(100);
+	 *           turnRight(90);
+	 *       }
+	 *   }
+	 * 
+ */ + public void run() {} + + /** + * Immediately turns the robot's body to the left by degrees. + *

+ * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the robot's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's body is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Turn the robot 180 degrees to the left
+	 *   turnLeft(180);
+	 *
+	 *   // Afterwards, turn the robot 90 degrees to the right
+	 *   turnLeft(-90);
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's body to the left. + * If {@code degrees} > 0 the robot will turn left. + * If {@code degrees} < 0 the robot will turn right. + * If {@code degrees} = 0 the robot will not turn, but execute. + * @see #turnRight(double) + * @see #turnGunLeft(double) + * @see #turnGunRight(double) + * @see #turnRadarLeft(double) + * @see #turnRadarRight(double) + */ + public void turnLeft(double degrees) { + if (peer != null) { + peer.turnBody(-Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Immediately turns the robot's body to the right by degrees. + * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the robot's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's body is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Turn the robot 180 degrees to the right
+	 *   turnRight(180);
+	 *
+	 *   // Afterwards, turn the robot 90 degrees to the left
+	 *   turnRight(-90);
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's body to the right. + * If {@code degrees} > 0 the robot will turn right. + * If {@code degrees} < 0 the robot will turn left. + * If {@code degrees} = 0 the robot will not turn, but execute. + * @see #turnLeft(double) + * @see #turnGunLeft(double) + * @see #turnGunRight(double) + * @see #turnRadarLeft(double) + * @see #turnRadarRight(double) + */ + public void turnRight(double degrees) { + if (peer != null) { + peer.turnBody(Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Do nothing this turn, meaning that the robot will skip it's turn. + *

+ * This call executes immediately, and does not return until the turn is + * over. + */ + public void doNothing() { + if (peer != null) { + peer.execute(); + } else { + uninitializedException(); + } + } + + /** + * Immediately fires a bullet. The bullet will travel in the direction the + * gun is pointing. + *

+ * The specified bullet power is an amount of energy that will be taken from + * the robot's energy. Hence, the more power you want to spend on the + * bullet, the more energy is taken from your robot. + *

+ * The bullet will do (4 * power) damage if it hits another robot. If power + * is greater than 1, it will do an additional 2 * (power - 1) damage. + * You will get (3 * power) back if you hit the other robot. You can call + * {@link Rules#getBulletDamage(double)} for getting the damage that a + * bullet with a specific bullet power will do. + *

+ * The specified bullet power should be between + * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. + *

+ * Note that the gun cannot fire if the gun is overheated, meaning that + * {@link #getGunHeat()} returns a value > 0. + *

+ * A event is generated when the bullet hits a robot + * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another + * bullet ({@link BulletHitBulletEvent}). + *

+ * Example: + *

+	 *   // Fire a bullet with maximum power if the gun is ready
+	 *   if (getGunHeat() == 0) {
+	 *       fire(Rules.MAX_BULLET_POWER);
+	 *   }
+	 * 
+ * + * @param power the amount of energy given to the bullet, and subtracted + * from the robot's energy. + * @see #fireBullet(double) + * @see #getGunHeat() + * @see #getGunCoolingRate() + * @see #onBulletHit(BulletHitEvent) + * @see #onBulletHitBullet(BulletHitBulletEvent) + * @see #onBulletMissed(BulletMissedEvent) + */ + public void fire(double power) { + if (peer != null) { + peer.setFire(power); + peer.execute(); + } else { + uninitializedException(); + } + } + + /** + * Immediately fires a bullet. The bullet will travel in the direction the + * gun is pointing. + *

+ * The specified bullet power is an amount of energy that will be taken from + * the robot's energy. Hence, the more power you want to spend on the + * bullet, the more energy is taken from your robot. + *

+ * The bullet will do (4 * power) damage if it hits another robot. If power + * is greater than 1, it will do an additional 2 * (power - 1) damage. + * You will get (3 * power) back if you hit the other robot. You can call + * {@link Rules#getBulletDamage(double)} for getting the damage that a + * bullet with a specific bullet power will do. + *

+ * The specified bullet power should be between + * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. + *

+ * Note that the gun cannot fire if the gun is overheated, meaning that + * {@link #getGunHeat()} returns a value > 0. + *

+ * A event is generated when the bullet hits a robot + * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another + * bullet ({@link BulletHitBulletEvent}). + *

+ * Example: + *

+	 *   // Fire a bullet with maximum power if the gun is ready
+	 *   if (getGunHeat() == 0) {
+	 *       Bullet bullet = fireBullet(Rules.MAX_BULLET_POWER);
+	 *
+	 *       // Get the velocity of the bullet
+	 *       if (bullet != null) {
+	 *           double bulletVelocity = bullet.getVelocity();
+	 *       }
+	 *   }
+	 * 
+ * + * @param power the amount of energy given to the bullet, and subtracted + * from the robot's energy. + * @return a {@link Bullet} that contains information about the bullet if it + * was actually fired, which can be used for tracking the bullet after it + * has been fired. If the bullet was not fired, {@code null} is returned. + * @see #fire(double) + * @see Bullet + * @see #getGunHeat() + * @see #getGunCoolingRate() + * @see #onBulletHit(BulletHitEvent) + * @see #onBulletHitBullet(BulletHitBulletEvent) + * @see #onBulletMissed(BulletMissedEvent) + */ + public Bullet fireBullet(double power) { + if (peer != null) { + return peer.fire(power); + } + uninitializedException(); + return null; + } + + /** + * Returns the rate at which the gun will cool down, i.e. the amount of heat + * the gun heat will drop per turn. + *

+ * The gun cooling rate is default 0.1 / turn, but can be changed by the + * battle setup. So don't count on the cooling rate being 0.1! + * + * @return the gun cooling rate + * @see #getGunHeat() + * @see #fire(double) + * @see #fireBullet(double) + */ + public double getGunCoolingRate() { + if (peer != null) { + return peer.getGunCoolingRate(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the direction that the robot's gun is facing, in degrees. + * The value returned will be between 0 and 360 (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * 90 means East, 180 means South, and 270 means West. + * + * @return the direction that the robot's gun is facing, in degrees. + * @see #getHeading() + * @see #getRadarHeading() + */ + public double getGunHeading() { + if (peer != null) { + return peer.getGunHeading() * 180.0 / Math.PI; + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the current heat of the gun. The gun cannot fire unless this is + * 0. (Calls to fire will succeed, but will not actually fire unless + * getGunHeat() == 0). + *

+ * The amount of gun heat generated when the gun is fired is + * 1 + (firePower / 5). Each turn the gun heat drops by the amount returned + * by {@link #getGunCoolingRate()}, which is a battle setup. + *

+ * Note that all guns are "hot" at the start of each round, where the gun + * heat is 3. + * + * @return the current gun heat + * @see #getGunCoolingRate() + * @see #fire(double) + * @see #fireBullet(double) + */ + public double getGunHeat() { + if (peer != null) { + return peer.getGunHeat(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the number of rounds in the current battle. + * + * @return the number of rounds in the current battle + * @see #getRoundNum() + */ + public int getNumRounds() { + if (peer != null) { + return peer.getNumRounds(); + } + uninitializedException(); + return 0; // never called + } + + + public int getSentryBorderSize() { + if (peer != null) { + return peer.getSentryBorderSize(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns how many opponents that are left in the current round. + * + * @return how many opponents that are left in the current round. + */ + public int getOthers() { + if (peer != null) { + return peer.getOthers(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns how many sentry robots that are left in the current round. + * + * @return how many sentry robots that are left in the current round. + * + * @since 1.9.1.0 + */ + public int getNumSentries() { + if (peer != null) { + return peer.getNumSentries(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the direction that the robot's radar is facing, in degrees. + * The value returned will be between 0 and 360 (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * 90 means East, 180 means South, and 270 means West. + * + * @return the direction that the robot's radar is facing, in degrees. + * @see #getHeading() + * @see #getGunHeading() + */ + public double getRadarHeading() { + if (peer != null) { + return peer.getRadarHeading() * 180.0 / Math.PI; + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the current round number (0 to {@link #getNumRounds()} - 1) of + * the battle. + * + * @return the current round number of the battle (zero indexed). + * @see #getNumRounds() + */ + public int getRoundNum() { + if (peer != null) { + return peer.getRoundNum(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the game time of the current round, where the time is equal to + * the current turn in the round. + *

+ * A battle consists of multiple rounds. + *

+ * Time is reset to 0 at the beginning of every round. + * + * @return the game time/turn of the current round. + */ + public long getTime() { + if (peer != null) { + return peer.getTime(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns the velocity of the robot measured in pixels/turn. + *

+ * The maximum velocity of a robot is defined by {@link Rules#MAX_VELOCITY} + * (8 pixels / turn). + * + * @return the velocity of the robot measured in pixels/turn. + * @see Rules#MAX_VELOCITY + */ + public double getVelocity() { + if (peer != null) { + return peer.getVelocity(); + } + uninitializedException(); + return 0; // never called + } + + /** + * {@inheritDoc} + */ + public void onBulletHit(BulletHitEvent event) {} + + /** + * {@inheritDoc} + */ + public void onBulletHitBullet(BulletHitBulletEvent event) {} + + /** + * {@inheritDoc} + */ + public void onBulletMissed(BulletMissedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onDeath(DeathEvent event) {} + + /** + * {@inheritDoc} + */ + public void onHitByBullet(HitByBulletEvent event) {} + + /** + * {@inheritDoc} + */ + public void onHitRobot(HitRobotEvent event) {} + + /** + * {@inheritDoc} + */ + public void onHitWall(HitWallEvent event) {} + + /** + * {@inheritDoc} + */ + public void onRobotDeath(RobotDeathEvent event) {} + + /** + * {@inheritDoc} + */ + public void onScannedRobot(ScannedRobotEvent event) {} + + /** + * {@inheritDoc} + */ + public void onWin(WinEvent event) {} + + /** + * {@inheritDoc} + */ + public void onRoundEnded(RoundEndedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onBattleEnded(BattleEndedEvent event) {} + + /** + * Scans for other robots. This method is called automatically by the game, + * as long as the robot is moving, turning its body, turning its gun, or + * turning its radar. + *

+ * Scan will cause {@link #onScannedRobot(ScannedRobotEvent) + * onScannedRobot(ScannedRobotEvent)} to be called if you see a robot. + *

+ * There are 2 reasons to call {@code scan()} manually: + *

    + *
  1. You want to scan after you stop moving. + *
  2. You want to interrupt the {@code onScannedRobot} event. This is more + * likely. If you are in {@code onScannedRobot} and call {@code scan()}, + * and you still see a robot, then the system will interrupt your + * {@code onScannedRobot} event immediately and start it from the top. + *
+ *

+ * This call executes immediately. + * + * @see #onScannedRobot(ScannedRobotEvent) + * @see ScannedRobotEvent + */ + public void scan() { + if (peer != null) { + ((IStandardRobotPeer) peer).rescan(); + } else { + uninitializedException(); + } + } + + /** + * Sets the gun to turn independent from the robot's turn. + *

+ * Ok, so this needs some explanation: The gun is mounted on the robot's + * body. So, normally, if the robot turns 90 degrees to the right, then the + * gun will turn with it as it is mounted on top of the robot's body. To + * compensate for this, you can call {@code setAdjustGunForRobotTurn(true)}. + * When this is set, the gun will turn independent from the robot's turn, + * i.e. the gun will compensate for the robot's body turn. + *

+ * Note: This method is additive until you reach the maximum the gun can + * turn. The "adjust" is added to the amount you set for turning the robot, + * then capped by the physics of the game. If you turn infinite, then the + * adjust is ignored (and hence overridden). + *

+ * Example, assuming both the robot and gun start out facing up (0 degrees): + *

+	 *   // Set gun to turn with the robot's turn
+	 *   setAdjustGunForRobotTurn(false); // This is the default
+	 *   turnRight(90);
+	 *   // At this point, both the robot and gun are facing right (90 degrees)
+	 *   turnLeft(90);
+	 *   // Both are back to 0 degrees
+	 *
+	 *   -- or --
+	 *
+	 *   // Set gun to turn independent from the robot's turn
+	 *   setAdjustGunForRobotTurn(true);
+	 *   turnRight(90);
+	 *   // At this point, the robot is facing right (90 degrees), but the gun is still facing up.
+	 *   turnLeft(90);
+	 *   // Both are back to 0 degrees.
+	 * 
+ *

+ * Note: The gun compensating this way does count as "turning the gun". + * See {@link #setAdjustRadarForGunTurn(boolean)} for details. + * + * @param independent {@code true} if the gun must turn independent from the + * robot's turn; {@code false} if the gun must turn with the robot's turn. + * @see #setAdjustRadarForGunTurn(boolean) + */ + public void setAdjustGunForRobotTurn(boolean independent) { + if (peer != null) { + ((IStandardRobotPeer) peer).setAdjustGunForBodyTurn(independent); + } else { + uninitializedException(); + } + } + + /** + * Sets the radar to turn independent from the robot's turn. + *

+ * Ok, so this needs some explanation: The radar is mounted on the gun, and + * the gun is mounted on the robot's body. So, normally, if the robot turns + * 90 degrees to the right, the gun turns, as does the radar. Hence, if the + * robot turns 90 degrees to the right, then the gun and radar will turn + * with it as the radar is mounted on top of the gun. To compensate for + * this, you can call {@code setAdjustRadarForRobotTurn(true)}. When this is + * set, the radar will turn independent from the robot's turn, i.e. the + * radar will compensate for the robot's turn. + *

+ * Note: This method is additive until you reach the maximum the radar can + * turn. The "adjust" is added to the amount you set for turning the robot, + * then capped by the physics of the game. If you turn infinite, then the + * adjust is ignored (and hence overridden). + *

+ * Example, assuming the robot, gun, and radar all start out facing up (0 + * degrees): + *

+	 *   // Set radar to turn with the robots's turn
+	 *   setAdjustRadarForRobotTurn(false); // This is the default
+	 *   turnRight(90);
+	 *   // At this point, the body, gun, and radar are all facing right (90 degrees);
+	 *
+	 *   -- or --
+	 *
+	 *   // Set radar to turn independent from the robot's turn
+	 *   setAdjustRadarForRobotTurn(true);
+	 *   turnRight(90);
+	 *   // At this point, the robot and gun are facing right (90 degrees), but the radar is still facing up.
+	 * 
+ * + * @param independent {@code true} if the radar must turn independent from + * the robots's turn; {@code false} if the radar must turn with the robot's + * turn. + * @see #setAdjustGunForRobotTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) + */ + public void setAdjustRadarForRobotTurn(boolean independent) { + if (peer != null) { + ((IStandardRobotPeer) peer).setAdjustRadarForBodyTurn(independent); + } else { + uninitializedException(); + } + } + + /** + * Sets the radar to turn independent from the gun's turn. + *

+ * Ok, so this needs some explanation: The radar is mounted on the robot's + * gun. So, normally, if the gun turns 90 degrees to the right, then the + * radar will turn with it as it is mounted on top of the gun. To compensate + * for this, you can call {@code setAdjustRadarForGunTurn(true)}. When this + * is set, the radar will turn independent from the robot's turn, i.e. the + * radar will compensate for the gun's turn. + *

+ * Note: This method is additive until you reach the maximum the radar can + * turn. The "adjust" is added to the amount you set for turning the gun, + * then capped by the physics of the game. If you turn infinite, then the + * adjust is ignored (and hence overridden). + *

+ * Example, assuming both the gun and radar start out facing up (0 degrees): + *

+	 *   // Set radar to turn with the gun's turn
+	 *   setAdjustRadarForGunTurn(false); // This is the default
+	 *   turnGunRight(90);
+	 *   // At this point, both the radar and gun are facing right (90 degrees);
+	 *
+	 *   -- or --
+	 *
+	 *   // Set radar to turn independent from the gun's turn
+	 *   setAdjustRadarForGunTurn(true);
+	 *   turnGunRight(90);
+	 *   // At this point, the gun is facing right (90 degrees), but the radar is still facing up.
+	 * 
+ * Note: Calling {@code setAdjustRadarForGunTurn(boolean)} will + * automatically call {@link #setAdjustRadarForRobotTurn(boolean)} with the + * same value, unless you have already called it earlier. This behavior is + * primarily for backward compatibility with older Robocode robots. + * + * @param independent {@code true} if the radar must turn independent from + * the gun's turn; {@code false} if the radar must turn with the gun's + * turn. + * @see #setAdjustRadarForRobotTurn(boolean) + * @see #setAdjustGunForRobotTurn(boolean) + */ + public void setAdjustRadarForGunTurn(boolean independent) { + if (peer != null) { + ((IStandardRobotPeer) peer).setAdjustRadarForGunTurn(independent); + } else { + uninitializedException(); + } + } + + /** + * Sets the color of the robot's body, gun, and radar in the same time. + *

+ * You may only call this method one time per battle. A {@code null} + * indicates the default (blue) color. + *

+ * Example: + *

+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 *
+	 *   public void run() {
+	 *       setColors(null, Color.RED, new Color(150, 0, 150));
+	 *       ...
+	 *   }
+	 * 
+ * + * @param bodyColor the new body color + * @param gunColor the new gun color + * @param radarColor the new radar color + * @see #setColors(Color, Color, Color, Color, Color) + * @see #setAllColors(Color) + * @see #setBodyColor(Color) + * @see #setGunColor(Color) + * @see #setRadarColor(Color) + * @see #setBulletColor(Color) + * @see #setScanColor(Color) + * @see Color + */ + public void setColors(Color bodyColor, Color gunColor, Color radarColor) { + if (peer != null) { + peer.setBodyColor(bodyColor); + peer.setGunColor(gunColor); + peer.setRadarColor(radarColor); + } else { + uninitializedException(); + } + } + + /** + * Sets the color of the robot's body, gun, radar, bullet, and scan arc in + * the same time. + *

+ * You may only call this method one time per battle. A {@code null} + * indicates the default (blue) color for the body, gun, radar, and scan + * arc, but white for the bullet color. + *

+ * Example: + *

+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 *
+	 *   public void run() {
+	 *       setColors(null, Color.RED, Color.GREEN, null, new Color(150, 0, 150));
+	 *       ...
+	 *   }
+	 * 
+ * + * @param bodyColor the new body color + * @param gunColor the new gun color + * @param radarColor the new radar color + * @param bulletColor the new bullet color + * @param scanArcColor the new scan arc color + * @see #setColors(Color, Color, Color) + * @see #setAllColors(Color) + * @see #setBodyColor(Color) + * @see #setGunColor(Color) + * @see #setRadarColor(Color) + * @see #setBulletColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.3 + */ + public void setColors(Color bodyColor, Color gunColor, Color radarColor, Color bulletColor, Color scanArcColor) { + if (peer != null) { + peer.setBodyColor(bodyColor); + peer.setGunColor(gunColor); + peer.setRadarColor(radarColor); + peer.setBulletColor(bulletColor); + peer.setScanColor(scanArcColor); + } else { + uninitializedException(); + } + } + + /** + * Sets all the robot's color to the same color in the same time, i.e. the + * color of the body, gun, radar, bullet, and scan arc. + *

+ * You may only call this method one time per battle. A {@code null} + * indicates the default (blue) color for the body, gun, radar, and scan + * arc, but white for the bullet color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 *
+	 *   public void run() {
+	 *       setAllColors(Color.RED);
+	 *       ...
+	 *   }
+	 * 
+ * + * @param color the new color for all the colors of the robot + * @see #setColors(Color, Color, Color) + * @see #setColors(Color, Color, Color, Color, Color) + * @see #setBodyColor(Color) + * @see #setGunColor(Color) + * @see #setRadarColor(Color) + * @see #setBulletColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.3 + */ + public void setAllColors(Color color) { + if (peer != null) { + peer.setBodyColor(color); + peer.setGunColor(color); + peer.setRadarColor(color); + peer.setBulletColor(color); + peer.setScanColor(color); + } else { + uninitializedException(); + } + } + + /** + * Sets the color of the robot's body. + *

+ * A {@code null} indicates the default (blue) color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 *
+	 *   public void run() {
+	 *       setBodyColor(Color.BLACK);
+	 *       ...
+	 *   }
+	 * 
+ * + * @param color the new body color + * @see #setColors(Color, Color, Color) + * @see #setColors(Color, Color, Color, Color, Color) + * @see #setAllColors(Color) + * @see #setGunColor(Color) + * @see #setRadarColor(Color) + * @see #setBulletColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.2 + */ + public void setBodyColor(Color color) { + if (peer != null) { + peer.setBodyColor(color); + } else { + uninitializedException(); + } + } + + /** + * Sets the color of the robot's gun. + *

+ * A {@code null} indicates the default (blue) color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 *
+	 *   public void run() {
+	 *       setGunColor(Color.RED);
+	 *       ...
+	 *   }
+	 * 
+ * + * @param color the new gun color + * @see #setColors(Color, Color, Color) + * @see #setColors(Color, Color, Color, Color, Color) + * @see #setAllColors(Color) + * @see #setBodyColor(Color) + * @see #setRadarColor(Color) + * @see #setBulletColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.2 + */ + public void setGunColor(Color color) { + if (peer != null) { + peer.setGunColor(color); + } else { + uninitializedException(); + } + } + + /** + * Sets the color of the robot's radar. + *

+ * A {@code null} indicates the default (blue) color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 *
+	 *   public void run() {
+	 *       setRadarColor(Color.YELLOW);
+	 *       ...
+	 *   }
+	 * 
+ * + * @param color the new radar color + * @see #setColors(Color, Color, Color) + * @see #setColors(Color, Color, Color, Color, Color) + * @see #setAllColors(Color) + * @see #setBodyColor(Color) + * @see #setGunColor(Color) + * @see #setBulletColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.2 + */ + public void setRadarColor(Color color) { + if (peer != null) { + peer.setRadarColor(color); + } else { + uninitializedException(); + } + } + + /** + * Sets the color of the robot's bullets. + *

+ * A {@code null} indicates the default white color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 *
+	 *   public void run() {
+	 *       setBulletColor(Color.GREEN);
+	 *       ...
+	 *   }
+	 * 
+ * + * @param color the new bullet color + * @see #setColors(Color, Color, Color) + * @see #setColors(Color, Color, Color, Color, Color) + * @see #setAllColors(Color) + * @see #setBodyColor(Color) + * @see #setGunColor(Color) + * @see #setRadarColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.2 + */ + public void setBulletColor(Color color) { + if (peer != null) { + peer.setBulletColor(color); + } else { + uninitializedException(); + } + } + + /** + * Sets the color of the robot's scan arc. + *

+ * A {@code null} indicates the default (blue) color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 *
+	 *   public void run() {
+	 *       setScanColor(Color.WHITE);
+	 *       ...
+	 *   }
+	 * 
+ * + * @param color the new scan arc color + * @see #setColors(Color, Color, Color) + * @see #setColors(Color, Color, Color, Color, Color) + * @see #setAllColors(Color) + * @see #setBodyColor(Color) + * @see #setGunColor(Color) + * @see #setRadarColor(Color) + * @see #setBulletColor(Color) + * @see Color + * @since 1.1.2 + */ + public void setScanColor(Color color) { + if (peer != null) { + peer.setScanColor(color); + } else { + uninitializedException(); + } + } + + /** + * Immediately stops all movement, and saves it for a call to + * {@link #resume()}. If there is already movement saved from a previous + * stop, this will have no effect. + *

+ * This method is equivalent to {@code #stop(false)}. + * + * @see #resume() + * @see #stop(boolean) + */ + public void stop() { + stop(false); + } + + /** + * Immediately stops all movement, and saves it for a call to + * {@link #resume()}. If there is already movement saved from a previous + * stop, you can overwrite it by calling {@code stop(true)}. + * + * @param overwrite If there is already movement saved from a previous stop, + * you can overwrite it by calling {@code stop(true)}. + * @see #resume() + * @see #stop() + */ + public void stop(boolean overwrite) { + if (peer != null) { + ((IStandardRobotPeer) peer).stop(overwrite); + } else { + uninitializedException(); + } + } + + /** + * Immediately resumes the movement you stopped by {@link #stop()}, if any. + *

+ * This call executes immediately, and does not return until it is complete. + * + * @see #stop() + * @see #stop(boolean) + */ + public void resume() { + if (peer != null) { + ((IStandardRobotPeer) peer).resume(); + } else { + uninitializedException(); + } + } + + /** + * Immediately turns the robot's gun to the left by degrees. + *

+ * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the gun's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's gun is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Turn the robot's gun 180 degrees to the left
+	 *   turnGunLeft(180);
+	 *
+	 *   // Afterwards, turn the robot's gun 90 degrees to the right
+	 *   turnGunLeft(-90);
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's gun to the left. + * If {@code degrees} > 0 the robot's gun will turn left. + * If {@code degrees} < 0 the robot's gun will turn right. + * If {@code degrees} = 0 the robot's gun will not turn, but execute. + * @see #turnGunRight(double) + * @see #turnLeft(double) + * @see #turnRight(double) + * @see #turnRadarLeft(double) + * @see #turnRadarRight(double) + * @see #setAdjustGunForRobotTurn(boolean) + */ + public void turnGunLeft(double degrees) { + if (peer != null) { + peer.turnGun(-Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Immediately turns the robot's gun to the right by degrees. + * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the gun's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's gun is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Turn the robot's gun 180 degrees to the right
+	 *   turnGunRight(180);
+	 *
+	 *   // Afterwards, turn the robot's gun 90 degrees to the left
+	 *   turnGunRight(-90);
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's gun to the right. + * If {@code degrees} > 0 the robot's gun will turn right. + * If {@code degrees} < 0 the robot's gun will turn left. + * If {@code degrees} = 0 the robot's gun will not turn, but execute. + * @see #turnGunLeft(double) + * @see #turnLeft(double) + * @see #turnRight(double) + * @see #turnRadarLeft(double) + * @see #turnRadarRight(double) + * @see #setAdjustGunForRobotTurn(boolean) + */ + public void turnGunRight(double degrees) { + if (peer != null) { + peer.turnGun(Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Immediately turns the robot's radar to the left by degrees. + *

+ * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the radar's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's radar is set to turn right + * instead of left. + *

+ * Example: + *

+	 *   // Turn the robot's radar 180 degrees to the left
+	 *   turnRadarLeft(180);
+	 *
+	 *   // Afterwards, turn the robot's radar 90 degrees to the right
+	 *   turnRadarLeft(-90);
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's radar to the left. + * If {@code degrees} > 0 the robot's radar will turn left. + * If {@code degrees} < 0 the robot's radar will turn right. + * If {@code degrees} = 0 the robot's radar will not turn, but execute. + * @see #turnRadarRight(double) + * @see #turnLeft(double) + * @see #turnRight(double) + * @see #turnGunLeft(double) + * @see #turnGunRight(double) + * @see #setAdjustRadarForRobotTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) + */ + public void turnRadarLeft(double degrees) { + if (peer != null) { + ((IStandardRobotPeer) peer).turnRadar(-Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Immediately turns the robot's radar to the right by degrees. + * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the radar's turn is 0. + *

+ * Note that both positive and negative values can be given as input, + * where negative values means that the robot's radar is set to turn left + * instead of right. + *

+ * Example: + *

+	 *   // Turn the robot's radar 180 degrees to the right
+	 *   turnRadarRight(180);
+	 *
+	 *   // Afterwards, turn the robot's radar 90 degrees to the left
+	 *   turnRadarRight(-90);
+	 * 
+ * + * @param degrees the amount of degrees to turn the robot's radar to the right. + * If {@code degrees} > 0 the robot's radar will turn right. + * If {@code degrees} < 0 the robot's radar will turn left. + * If {@code degrees} = 0 the robot's radar will not turn, but execute. + * @see #turnRadarLeft(double) + * @see #turnLeft(double) + * @see #turnRight(double) + * @see #turnGunLeft(double) + * @see #turnGunRight(double) + * @see #setAdjustRadarForRobotTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) + */ + public void turnRadarRight(double degrees) { + if (peer != null) { + ((IStandardRobotPeer) peer).turnRadar(Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * Returns the robot's current energy. + * + * @return the robot's current energy. + */ + public double getEnergy() { + if (peer != null) { + return peer.getEnergy(); + } + uninitializedException(); + return 0; // never called + } + + /** + * Returns a graphics context used for painting graphical items for the robot. + *

+ * This method is very useful for debugging your robot. + *

+ * Note that the robot will only be painted if the "Paint" is enabled on the + * robot's console window; otherwise the robot will never get painted (the + * reason being that all robots might have graphical items that must be + * painted, and then you might not be able to tell what graphical items that + * have been painted for your robot). + *

+ * Also note that the coordinate system for the graphical context where you + * paint items fits for the Robocode coordinate system where (0, 0) is at + * the bottom left corner of the battlefield, where X is towards right and Y + * is upwards. + * + * @return a graphics context used for painting graphical items for the robot. + * @see #onPaint(Graphics2D) + * @since 1.6.1 + */ + public Graphics2D getGraphics() { + if (peer != null) { + return peer.getGraphics(); + } + uninitializedException(); + return null; // never called + } + + /** + * Sets the debug property with the specified key to the specified value. + *

+ * This method is very useful when debugging or reviewing your robot as you + * will be able to see this property displayed in the robot console for your + * robots under the Debug Properties tab page. + * + * @param key the name/key of the debug property. + * @param value the new value of the debug property, where {@code null} or + * the empty string is used for removing this debug property. + * @since 1.6.2 + */ + public void setDebugProperty(String key, String value) { + if (peer != null) { + peer.setDebugProperty(key, value); + return; + } + uninitializedException(); + } + + /** + * {@inheritDoc} + */ + public void onPaint(Graphics2D g) {} + + /** + * {@inheritDoc} + */ + public void onKeyPressed(java.awt.event.KeyEvent e) {} + + /** + * {@inheritDoc} + */ + public void onKeyReleased(java.awt.event.KeyEvent e) {} + + /** + * {@inheritDoc} + */ + public void onKeyTyped(java.awt.event.KeyEvent e) {} + + /** + * {@inheritDoc} + */ + public void onMouseClicked(java.awt.event.MouseEvent e) {} + + /** + * {@inheritDoc} + */ + public void onMouseEntered(java.awt.event.MouseEvent e) {} + + /** + * {@inheritDoc} + */ + public void onMouseExited(java.awt.event.MouseEvent e) {} + + /** + * {@inheritDoc} + */ + public void onMousePressed(java.awt.event.MouseEvent e) {} + + /** + * {@inheritDoc} + */ + public void onMouseReleased(java.awt.event.MouseEvent e) {} + + /** + * {@inheritDoc} + */ + public void onMouseMoved(java.awt.event.MouseEvent e) {} + + /** + * {@inheritDoc} + */ + public void onMouseDragged(java.awt.event.MouseEvent e) {} + + /** + * {@inheritDoc} + */ + public void onMouseWheelMoved(java.awt.event.MouseWheelEvent e) {} + + /** + * {@inheritDoc} + */ + public void onStatus(StatusEvent e) {} +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobotDeathEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobotDeathEvent.java new file mode 100644 index 0000000..8159ac9 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobotDeathEvent.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * This event is sent to {@link Robot#onRobotDeath(RobotDeathEvent) onRobotDeath()} + * when another robot (not your robot) dies. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class RobotDeathEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 70; + + private final String robotName; + + /** + * Called by the game to create a new RobotDeathEvent. + * + * @param robotName the name of the robot that died + */ + public RobotDeathEvent(String robotName) { + super(); + this.robotName = robotName; + } + + /** + * Returns the name of the robot that died. + * + * @return the name of the robot that died + */ + public String getName() { + return robotName; + } + + /** + * @return the name of the robot that died + * @deprecated Use {@link #getName()} instead. + */ + @Deprecated + public String getRobotName() { + return robotName; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onRobotDeath(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.RobotDeathEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + RobotDeathEvent obj = (RobotDeathEvent) object; + + return RbSerializer.SIZEOF_TYPEINFO + serializer.sizeOf(obj.robotName); + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + RobotDeathEvent obj = (RobotDeathEvent) object; + + serializer.serialize(buffer, obj.robotName); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + String name = serializer.deserializeString(buffer); + + return new RobotDeathEvent(name); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobotStatus.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobotStatus.java new file mode 100644 index 0000000..849fd96 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RobotStatus.java @@ -0,0 +1,426 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.security.IHiddenStatusHelper; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; + +import java.io.Serializable; +import java.nio.ByteBuffer; + + +/** + * Contains the status of a robot for a specific time/turn returned by + * {@link StatusEvent#getStatus()}. + * + * @author Flemming N. Larsen (original) + * + * @since 1.5 + */ +public final class RobotStatus implements Serializable { + private static final long serialVersionUID = 1L; + + private final double energy; + private final double x; + private final double y; + private final double bodyHeading; + private final double gunHeading; + private final double radarHeading; + private final double velocity; + private final double bodyTurnRemaining; + private final double radarTurnRemaining; + private final double gunTurnRemaining; + private final double distanceRemaining; + private final double gunHeat; + private final int others; + private final int numSentries; + private final int roundNum; + private final int numRounds; + private final long time; + + /** + * Returns the robot's current energy. + * + * @return the robot's current energy + */ + public double getEnergy() { + return energy; + } + + /** + * Returns the X position of the robot. (0,0) is at the bottom left of the + * battlefield. + * + * @return the X position of the robot + * @see #getY() + */ + public double getX() { + return x; + } + + /** + * Returns the Y position of the robot. (0,0) is at the bottom left of the + * battlefield. + * + * @return the Y position of the robot + * @see #getX() + */ + public double getY() { + return y; + } + + /** + * Returns the direction that the robot's body is facing, in radians. + * The value returned will be between 0 and 2 * PI (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * PI / 2 means East, PI means South, and 3 * PI / 2 means West. + * + * @return the direction that the robot's body is facing, in radians. + */ + public double getHeadingRadians() { + return bodyHeading; + } + + /** + * Returns the direction that the robot's body is facing, in degrees. + * The value returned will be between 0 and 360 (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * 90 means East, 180 means South, and 270 means West. + * + * @return the direction that the robot's body is facing, in degrees. + */ + public double getHeading() { + return Math.toDegrees(bodyHeading); + } + + /** + * Returns the direction that the robot's gun is facing, in radians. + * The value returned will be between 0 and 2 * PI (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * PI / 2 means East, PI means South, and 3 * PI / 2 means West. + * + * @return the direction that the robot's gun is facing, in radians. + */ + public double getGunHeadingRadians() { + return gunHeading; + } + + /** + * Returns the direction that the robot's gun is facing, in degrees. + * The value returned will be between 0 and 360 (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * 90 means East, 180 means South, and 270 means West. + * + * @return the direction that the robot's gun is facing, in degrees. + */ + public double getGunHeading() { + return Math.toDegrees(gunHeading); + } + + /** + * Returns the direction that the robot's radar is facing, in radians. + * The value returned will be between 0 and 2 * PI (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * PI / 2 means East, PI means South, and 3 * PI / 2 means West. + * + * @return the direction that the robot's radar is facing, in radians. + */ + public double getRadarHeadingRadians() { + return radarHeading; + } + + /** + * Returns the direction that the robot's radar is facing, in degrees. + * The value returned will be between 0 and 360 (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * 90 means East, 180 means South, and 270 means West. + * + * @return the direction that the robot's radar is facing, in degrees. + */ + public double getRadarHeading() { + return Math.toDegrees(radarHeading); + } + + /** + * Returns the velocity of the robot measured in pixels/turn. + *

+ * The maximum velocity of a robot is defined by {@link Rules#MAX_VELOCITY} + * (8 pixels / turn). + * + * @return the velocity of the robot measured in pixels/turn + * @see Rules#MAX_VELOCITY + */ + public double getVelocity() { + return velocity; + } + + /** + * Returns the angle remaining in the robots's turn, in radians. + *

+ * This call returns both positive and negative values. Positive values + * means that the robot is currently turning to the right. Negative values + * means that the robot is currently turning to the left. + * + * @return the angle remaining in the robots's turn, in radians + */ + public double getTurnRemainingRadians() { + return bodyTurnRemaining; + } + + /** + * Returns the angle remaining in the robots's turn, in degrees. + *

+ * This call returns both positive and negative values. Positive values + * means that the robot is currently turning to the right. Negative values + * means that the robot is currently turning to the left. + * + * @return the angle remaining in the robots's turn, in degrees + */ + public double getTurnRemaining() { + return Math.toDegrees(bodyTurnRemaining); + } + + /** + * Returns the angle remaining in the radar's turn, in radians. + *

+ * This call returns both positive and negative values. Positive values + * means that the radar is currently turning to the right. Negative values + * means that the radar is currently turning to the left. + * + * @return the angle remaining in the radar's turn, in radians + */ + public double getRadarTurnRemainingRadians() { + return radarTurnRemaining; + } + + /** + * Returns the angle remaining in the radar's turn, in degrees. + *

+ * This call returns both positive and negative values. Positive values + * means that the radar is currently turning to the right. Negative values + * means that the radar is currently turning to the left. + * + * @return the angle remaining in the radar's turn, in degrees + */ + public double getRadarTurnRemaining() { + return Math.toDegrees(radarTurnRemaining); + } + + /** + * Returns the angle remaining in the gun's turn, in radians. + *

+ * This call returns both positive and negative values. Positive values + * means that the gun is currently turning to the right. Negative values + * means that the gun is currently turning to the left. + * + * @return the angle remaining in the gun's turn, in radians + */ + public double getGunTurnRemainingRadians() { + return gunTurnRemaining; + } + + /** + * Returns the angle remaining in the gun's turn, in degrees. + *

+ * This call returns both positive and negative values. Positive values + * means that the gun is currently turning to the right. Negative values + * means that the gun is currently turning to the left. + * + * @return the angle remaining in the gun's turn, in degrees + */ + public double getGunTurnRemaining() { + return Math.toDegrees(gunTurnRemaining); + } + + /** + * Returns the distance remaining in the robot's current move measured in + * pixels. + *

+ * This call returns both positive and negative values. Positive values + * means that the robot is currently moving forwards. Negative values means + * that the robot is currently moving backwards. + * + * @return the distance remaining in the robot's current move measured in + * pixels. + */ + public double getDistanceRemaining() { + return distanceRemaining; + } + + /** + * Returns the current heat of the gun. The gun cannot fire unless this is + * 0. (Calls to fire will succeed, but will not actually fire unless + * getGunHeat() == 0). + *

+ * The amount of gun heat generated when the gun is fired is + * 1 + (firePower / 5). Each turn the gun heat drops by the amount returned + * by {@link Robot#getGunCoolingRate()}, which is a battle setup. + *

+ * Note that all guns are "hot" at the start of each round, where the gun + * heat is 3. + * + * @return the current gun heat + * @see Robot#getGunCoolingRate() + * @see Robot#fire(double) + * @see Robot#fireBullet(double) + */ + public double getGunHeat() { + return gunHeat; + } + + /** + * Returns how many opponents that are left in the current round. + * + * @return how many opponents that are left in the current round. + * @see #getNumSentries() + * @since 1.6.2 + */ + public int getOthers() { + return others; + } + + /** + * Returns how many sentry robots that are left in the current round. + * + * @return how many sentry robots that are left in the current round. + * @see #getOthers() + * @since 1.9.1.0 + */ + public int getNumSentries() { + return numSentries; + } + + /** + * Returns the number of rounds in the current battle. + * + * @return the number of rounds in the current battle + * @see #getRoundNum() + * @since 1.6.2 + */ + public int getNumRounds() { + return numRounds; + } + + /** + * Returns the current round number (0 to {@link #getNumRounds()} - 1) of + * the battle. + * + * @return the current round number of the battle (zero indexed). + * @see #getNumRounds() + * @since 1.6.2 + */ + public int getRoundNum() { + return roundNum; + } + + /** + * Returns the game time of the round, where the time is equal to the current turn in the round. + * + * @return the game time/turn of the current round. + * @since 1.6.2 + */ + public long getTime() { + return time; + } + + private RobotStatus(double energy, double x, double y, double bodyHeading, double gunHeading, double radarHeading, + double velocity, double bodyTurnRemaining, double radarTurnRemaining, double gunTurnRemaining, + double distanceRemaining, double gunHeat, int others, int numSentries, int roundNum, int numRounds, long time) { + this.energy = energy; + this.x = x; + this.y = y; + this.bodyHeading = bodyHeading; + this.gunHeading = gunHeading; + this.radarHeading = radarHeading; + this.bodyTurnRemaining = bodyTurnRemaining; + this.velocity = velocity; + this.radarTurnRemaining = radarTurnRemaining; + this.gunTurnRemaining = gunTurnRemaining; + this.distanceRemaining = distanceRemaining; + this.gunHeat = gunHeat; + this.others = others; + this.numSentries = numSentries; + this.roundNum = roundNum; + this.numRounds = numRounds; + this.time = time; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper, IHiddenStatusHelper { + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 12 * RbSerializer.SIZEOF_DOUBLE + 4 * RbSerializer.SIZEOF_INT + + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + RobotStatus obj = (RobotStatus) object; + + serializer.serialize(buffer, obj.energy); + serializer.serialize(buffer, obj.x); + serializer.serialize(buffer, obj.y); + serializer.serialize(buffer, obj.bodyHeading); + serializer.serialize(buffer, obj.gunHeading); + serializer.serialize(buffer, obj.radarHeading); + serializer.serialize(buffer, obj.velocity); + serializer.serialize(buffer, obj.bodyTurnRemaining); + serializer.serialize(buffer, obj.radarTurnRemaining); + serializer.serialize(buffer, obj.gunTurnRemaining); + serializer.serialize(buffer, obj.distanceRemaining); + serializer.serialize(buffer, obj.gunHeat); + serializer.serialize(buffer, obj.others); + serializer.serialize(buffer, obj.numSentries); + serializer.serialize(buffer, obj.roundNum); + serializer.serialize(buffer, obj.numRounds); + serializer.serialize(buffer, obj.time); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + double energy = buffer.getDouble(); + double x = buffer.getDouble(); + double y = buffer.getDouble(); + double bodyHeading = buffer.getDouble(); + double gunHeading = buffer.getDouble(); + double radarHeading = buffer.getDouble(); + double velocity = buffer.getDouble(); + double bodyTurnRemaining = buffer.getDouble(); + double radarTurnRemaining = buffer.getDouble(); + double gunTurnRemaining = buffer.getDouble(); + double distanceRemaining = buffer.getDouble(); + double gunHeat = buffer.getDouble(); + int others = buffer.getInt(); + int numSentries = buffer.getInt(); + int roundNum = buffer.getInt(); + int numRounds = buffer.getInt(); + long time = buffer.getLong(); + + return new RobotStatus(energy, x, y, bodyHeading, gunHeading, radarHeading, velocity, bodyTurnRemaining, + radarTurnRemaining, gunTurnRemaining, distanceRemaining, gunHeat, others, numSentries, roundNum, numRounds, + time); + } + + public RobotStatus createStatus(double energy, double x, double y, double bodyHeading, double gunHeading, double radarHeading, double velocity, + double bodyTurnRemaining, double radarTurnRemaining, double gunTurnRemaining, double distanceRemaining, double gunHeat, int others, + int numSentries, int roundNum, int numRounds, long time) { + return new RobotStatus(energy, x, y, bodyHeading, gunHeading, radarHeading, velocity, bodyTurnRemaining, + radarTurnRemaining, gunTurnRemaining, distanceRemaining, gunHeat, others, numSentries, roundNum, numRounds, + time); + } + } + +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/RoundEndedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RoundEndedEvent.java new file mode 100644 index 0000000..e76fb05 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/RoundEndedEvent.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicEvents3; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A RoundEndedEvent is sent to {@link Robot#onRoundEnded(RoundEndedEvent) + * onRoundEnded()} when a round has ended. + * You can use the information contained in this event to determine which round that has ended. + * + * @see Robot#onRoundEnded(RoundEndedEvent) + * + * @author Flemming N. Larsen (original) + * + * @since 1.7.2 + */ +public final class RoundEndedEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 110; // System event -> cannot be changed! + + private final int round; + private final int turns; + private final int totalTurns; + + /** + * Called by the game to create a new RoundEndedEvent. + * + * @param round the round that has ended (zero-indexed). + * @param turns the number of turns that this round reached. + * @param totalTurns the total number of turns reached in the battle when this round ended. + */ + public RoundEndedEvent(int round, int turns, int totalTurns) { + this.round = round; + this.turns = turns; + this.totalTurns = totalTurns; + } + + /** + * Returns the round that ended (zero-indexed). + * + * @return the round that ended (zero-indexed). + */ + public int getRound() { + return round; + } + + /** + * Returns the number of turns that this round reached. + * + * @return the number of turns that this round reached. + */ + public int getTurns() { + return turns; + } + + /** + * Returns the total number of turns reached in the battle when this round ended. + * + * @return the total number of turns reached in the battle when this round ended. + */ + public int getTotalTurns() { + return totalTurns; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + public final int getPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (robot != null) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null && IBasicEvents3.class.isAssignableFrom(listener.getClass())) { + ((IBasicEvents3) listener).onRoundEnded(this); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + final boolean isCriticalEvent() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.RoundEndedEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + 3 * RbSerializer.SIZEOF_INT; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + RoundEndedEvent event = (RoundEndedEvent) object; + + serializer.serialize(buffer, event.round); + serializer.serialize(buffer, event.turns); + serializer.serialize(buffer, event.totalTurns); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int round = serializer.deserializeInt(buffer); + int turns = serializer.deserializeInt(buffer); + int totalTurns = serializer.deserializeInt(buffer); + + return new RoundEndedEvent(round, turns, totalTurns); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/Rules.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Rules.java new file mode 100644 index 0000000..96919fa --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/Rules.java @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import static java.lang.Math.abs; +import static java.lang.Math.max; + + +/** + * Constants and methods that defines the rules of Robocode. + * Constants are used for rules that will not change. + * Methods are provided for rules that can be changed between battles or which depends + * on some other factor. + * + * @author Luis Crespo (original) + * @author Flemming N. Larsen (original) + * + * @since 1.1.4 + */ +public final class Rules { + + // Hide the constructor in the Javadocs as it should not be used + private Rules() {} + + /** + * The acceleration of a robot, i.e. the increase of velocity when the + * robot moves forward, which is 1 pixel/turn. + */ + public static final double ACCELERATION = 1; + + /** + * The deceleration of a robot, i.e. the decrease of velocity when the + * robot moves backwards (or brakes), which is 2 pixels/turn. + */ + public static final double DECELERATION = 2; + + /** + * The maximum velocity of a robot, which is 8 pixels/turn. + */ + public static final double MAX_VELOCITY = 8; + + /** + * The radar scan radius, which is 1200 pixels. + * Robots which is more than 1200 pixels away cannot be seen on the radar. + */ + public static final double RADAR_SCAN_RADIUS = 1200; + + /** + * The minimum bullet power, i.e the amount of energy required for firing a + * bullet, which is 0.1 energy points. + */ + public static final double MIN_BULLET_POWER = 0.1; + + /** + * The maximum bullet power, i.e. the maximum amount of energy that can be + * transferred to a bullet when it is fired, which is 3 energy points. + */ + public static final double MAX_BULLET_POWER = 3; + + /** + * The maximum turning rate of the robot, in degrees, which is + * 10 degress/turn. + * Note, that the turn rate of the robot depends on it's velocity. + * + * @see #MAX_TURN_RATE_RADIANS + * @see #getTurnRate(double) + * @see #getTurnRateRadians(double) + */ + public static final double MAX_TURN_RATE = 10; + + /** + * The maximum turning rate of the robot measured in radians instead of + * degrees. + * + * @see #MAX_TURN_RATE + * @see #getTurnRate(double) + * @see #getTurnRateRadians(double) + */ + public static final double MAX_TURN_RATE_RADIANS = Math.toRadians(MAX_TURN_RATE); + + /** + * The turning rate of the gun measured in degrees, which is + * 20 degrees/turn. + * Note, that if setAdjustGunForRobotTurn(true) has been called, the gun + * turn is independent of the robot turn. + * In this case the gun moves relatively to the screen. If + * setAdjustGunForRobotTurn(false) has been called or + * setAdjustGunForRobotTurn() has not been called at all (this is the + * default), then the gun turn is dependent on the robot turn, and in this + * case the gun moves relatively to the robot body. + * + * @see #GUN_TURN_RATE_RADIANS + * @see Robot#setAdjustGunForRobotTurn(boolean) + */ + public static final double GUN_TURN_RATE = 20; + + /** + * The turning rate of the gun measured in radians instead of degrees. + * + * @see #GUN_TURN_RATE + */ + public static final double GUN_TURN_RATE_RADIANS = Math.toRadians(GUN_TURN_RATE); + + /** + * The turning rate of the radar measured in degrees, which is + * 45 degrees/turn. + * Note, that if setAdjustRadarForRobotTurn(true) and/or + * setAdjustRadarForGunTurn(true) has been called, the radar turn is + * independent of the robot and/or gun turn. If both methods has been set to + * true, the radar moves relatively to the screen. + * If setAdjustRadarForRobotTurn(false) and/or setAdjustRadarForGunTurn(false) + * has been called or not called at all (this is the default), then the + * radar turn is dependent on the robot and/or gun turn, and in this case + * the radar moves relatively to the gun and/or robot body. + * + * @see #RADAR_TURN_RATE_RADIANS + * @see Robot#setAdjustGunForRobotTurn(boolean) + * @see Robot#setAdjustRadarForGunTurn(boolean) + */ + public static final double RADAR_TURN_RATE = 45; + + /** + * The turning rate of the radar measured in radians instead of degrees. + * + * @see #RADAR_TURN_RATE + */ + public static final double RADAR_TURN_RATE_RADIANS = Math.toRadians(RADAR_TURN_RATE); + + /** + * The amount of damage taken when a robot hits or is hit by another robot, + * which is 0.6 energy points. + */ + public static final double ROBOT_HIT_DAMAGE = 0.6; + + /** + * The amount of bonus given when a robot moving forward hits an opponent + * robot (ramming), which is 1.2 energy points. + */ + public static final double ROBOT_HIT_BONUS = 1.2; + + /** + * Returns the turn rate of a robot given a specific velocity measured in + * degrees/turn. + * + * @param velocity the velocity of the robot. + * @return turn rate in degrees/turn. + * @see #getTurnRateRadians(double) + */ + public static double getTurnRate(double velocity) { + return MAX_TURN_RATE - 0.75 * abs(velocity); + } + + /** + * Returns the turn rate of a robot given a specific velocity measured in + * radians/turn. + * + * @param velocity the velocity of the robot. + * @return turn rate in radians/turn. + * @see #getTurnRate(double) + */ + public static double getTurnRateRadians(double velocity) { + return Math.toRadians(getTurnRate(velocity)); + } + + /** + * Returns the amount of damage taken when robot hits a wall with a + * specific velocity. + * + * @param velocity the velocity of the robot. + * @return wall hit damage in energy points. + */ + public static double getWallHitDamage(double velocity) { + return max(abs(velocity) / 2 - 1, 0); + } + + /** + * Returns the amount of damage of a bullet given a specific bullet power. + * + * @param bulletPower the energy power of the bullet. + * @return bullet damage in energy points. + */ + public static double getBulletDamage(double bulletPower) { + double damage = 4 * bulletPower; + + if (bulletPower > 1) { + damage += 2 * (bulletPower - 1); + } + return damage; + } + + /** + * Returns the amount of bonus given when a robot's bullet hits an opponent + * robot given a specific bullet power. + * + * @param bulletPower the energy power of the bullet. + * @return bullet hit bonus in energy points. + */ + public static double getBulletHitBonus(double bulletPower) { + return 3 * bulletPower; + } + + /** + * Returns the speed of a bullet given a specific bullet power measured in pixels/turn. + * + * @param bulletPower the energy power of the bullet. + * @return bullet speed in pixels/turn + */ + public static double getBulletSpeed(double bulletPower) { + bulletPower = Math.min(Math.max(bulletPower, MIN_BULLET_POWER), MAX_BULLET_POWER); + return 20 - 3 * bulletPower; + } + + /** + * Returns the heat produced by firing the gun given a specific bullet + * power. + * + * @param bulletPower the energy power of the bullet. + * @return gun heat + */ + public static double getGunHeat(double bulletPower) { + return 1 + (bulletPower / 5); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/ScannedRobotEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/ScannedRobotEvent.java new file mode 100644 index 0000000..761f55f --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/ScannedRobotEvent.java @@ -0,0 +1,314 @@ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +public class ScannedRobotEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 10; + + private final String name; + private final double energy; + private final double heading; + private final double bearing; + private final double distance; + private final double velocity; + private final boolean isSentryRobot; + + + public ScannedRobotEvent() { + this(null, 0, 0, 0, 0, 0, false); + } + + /** + * Called by the game to create a new ScannedRobotEvent. + * + * @param name the name of the scanned robot + * @param energy the energy of the scanned robot + * @param bearing the bearing of the scanned robot, in radians + * @param distance the distance from your robot to the scanned robot + * @param heading the heading of the scanned robot + * @param velocity the velocity of the scanned robot + * + * @deprecated Use {@link #ScannedRobotEvent(String, double, double, double, double, double, boolean)} instead. + */ + public ScannedRobotEvent(String name, double energy, double bearing, double distance, double heading, double velocity) { + this(name, energy, bearing, distance, heading, velocity, false); + } + + /** + * Called by the game to create a new ScannedRobotEvent. + * + * @param name the name of the scanned robot + * @param energy the energy of the scanned robot + * @param bearing the bearing of the scanned robot, in radians + * @param distance the distance from your robot to the scanned robot + * @param heading the heading of the scanned robot + * @param velocity the velocity of the scanned robot + * @param isSentryRobot flag specifying if the scanned robot is a sentry robot + * + * @since 1.9.0.0 + */ + public ScannedRobotEvent(String name, double energy, double bearing, double distance, double heading, double velocity, boolean isSentryRobot) { + super(); + this.name = name; + this.energy = energy; + this.bearing = bearing; + this.distance = distance; + this.heading = heading; + this.velocity = velocity; + this.isSentryRobot = isSentryRobot; + } + + + public double getBearing() { + return bearing * 180.0 / Math.PI; + } + + public double getBearingRadians() { + return bearing; + } + + /** + * Returns the distance to the robot (your center to his center). + * + * @return the distance to the robot. + */ + public double getDistance() { + return distance; + } + + + public double getEnergy() { + return energy; + } + + + public double getHeading() { + return heading * 180.0 / Math.PI; + } + + /** + * Returns the heading of the robot, in radians (0 <= getHeading() < 2 * PI) + * + * @return the heading of the robot, in radians + */ + public double getHeadingRadians() { + return heading; + } + + /** + * @return the energy of the robot + * @deprecated Use {@link #getEnergy()} instead. + */ + @Deprecated + public double getLife() { + return energy; + } + + /** + * Returns the name of the robot. + * + * @return the name of the robot + */ + public String getName() { + return name; + } + + /** + * @return the bearing to the robot you scanned, in degrees + * @deprecated Use {@link #getBearing()} instead. + */ + @Deprecated + public double getRobotBearing() { + return getBearing(); + } + + /** + * @return the robot bearing in degrees + * @deprecated Use {@link #getBearing()} instead. + */ + @Deprecated + public double getRobotBearingDegrees() { + return getBearing(); + } + + /** + * @return the bearing to the robot you scanned, in radians + * @deprecated Use {@link #getBearingRadians()} instead. + */ + @Deprecated + public double getRobotBearingRadians() { + return getBearingRadians(); + } + + /** + * @return the distance to the robot. + * @deprecated Use {@link #getDistance()} instead. + */ + @Deprecated + public double getRobotDistance() { + return getDistance(); + } + + /** + * @return the heading of the robot, in degrees + * @deprecated Use {@link #getHeading()} instead. + */ + @Deprecated + public double getRobotHeading() { + return getHeading(); + } + + /** + * @return the heading of the robot, in degrees + * @deprecated Use {@link #getHeading()} instead. + */ + @Deprecated + public double getRobotHeadingDegrees() { + return getHeading(); + } + + /** + * @return the heading of the robot, in radians + * @deprecated Use {@link #getHeadingRadians()} instead. + */ + @Deprecated + public double getRobotHeadingRadians() { + return getHeadingRadians(); + } + + /** + * @return the energy of the robot + * @deprecated Use {@link #getEnergy()} instead. + */ + @Deprecated + public double getRobotLife() { + return getEnergy(); + } + + /** + * @return the name of the robot + * @deprecated Use {@link #getName()} instead. + */ + @Deprecated + public String getRobotName() { + return getName(); + } + + /** + * @return the velocity of the robot + * @deprecated Use {@link #getVelocity()} instead. + */ + @Deprecated + public double getRobotVelocity() { + return getVelocity(); + } + + /** + * Returns the velocity of the robot. + * + * @return the velocity of the robot + */ + public double getVelocity() { + return velocity; + } + + /** + * Checks if the scanned robot is a sentry robot. + * @return {@code true} if the scanned robot is a sentry robot; {@code false} otherwise. + * + * @since 1.9.0.0 + */ + public boolean isSentryRobot() { + return isSentryRobot; + } + + /** + * {@inheritDoc} + */ + @Override + public final int compareTo(Event event) { + final int res = super.compareTo(event); + if (res != 0) { + return res; + } + // Compare the distance, if the events are ScannedRobotEvents + // The shorter distance to the robot, the higher priority + if (event instanceof ScannedRobotEvent) { + return (int) (this.getDistance() - ((ScannedRobotEvent) event).getDistance()); + } + // No difference found + return 0; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + if (listener != null) { + listener.onScannedRobot(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.ScannedRobotEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + ScannedRobotEvent obj = (ScannedRobotEvent) object; + return RbSerializer.SIZEOF_TYPEINFO + serializer.sizeOf(obj.name) + 5 * RbSerializer.SIZEOF_DOUBLE + + RbSerializer.SIZEOF_BOOL; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + ScannedRobotEvent obj = (ScannedRobotEvent) object; + serializer.serialize(buffer, obj.name); + serializer.serialize(buffer, obj.energy); + serializer.serialize(buffer, obj.heading); + serializer.serialize(buffer, obj.bearing); + serializer.serialize(buffer, obj.distance); + serializer.serialize(buffer, obj.velocity); + serializer.serialize(buffer, obj.isSentryRobot); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + String name = serializer.deserializeString(buffer); + double energy = buffer.getDouble(); + double heading = buffer.getDouble(); + double bearing = buffer.getDouble(); + double distance = buffer.getDouble(); + double velocity = buffer.getDouble(); + boolean isSentryRobot = serializer.deserializeBoolean(buffer); + + return new ScannedRobotEvent(name, energy, bearing, distance, heading, velocity, isSentryRobot); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/SkippedTurnEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/SkippedTurnEvent.java new file mode 100644 index 0000000..2e1d7ba --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/SkippedTurnEvent.java @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IAdvancedEvents; +import robocode.robotinterfaces.IAdvancedRobot; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * A SkippedTurnEvent is sent to {@link AdvancedRobot#onSkippedTurn(SkippedTurnEvent) + * onSkippedTurn()} when your robot is forced to skipping a turn. + * You must take an action every turn in order to participate in the game. + * For example, + *

+ *    try {
+ *        Thread.sleep(1000);
+ *    } catch (InterruptedException e) {
+ *        // Immediately reasserts the exception by interrupting the caller thread
+ *        // itself.
+ *        Thread.currentThread().interrupt();
+ *    }
+ * 
+ * will cause many SkippedTurnEvents, because you are not responding to the game. + * If you receive 30 SkippedTurnEvents, you will be removed from the round. + *

+ * Instead, you should do something such as: + *

+ *     for (int i = 0; i < 30; i++) {
+ *         doNothing(); // or perhaps scan();
+ *     }
+ * 
+ *

+ * This event may also be generated if you are simply doing too much processing + * between actions, that is using too much processing power for the calculations + * etc. in your robot. + * + * @see AdvancedRobot#onSkippedTurn(SkippedTurnEvent) + * @see SkippedTurnEvent + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class SkippedTurnEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 100; // System event -> cannot be changed!; + + private final long skippedTurn; + + /** + * Called by the game to create a new SkippedTurnEvent. + * + * @param skippedTurn the skipped turn + */ + public SkippedTurnEvent(long skippedTurn) { + super(); + this.skippedTurn = skippedTurn; + } + + /** + * Returns the turn that was skipped. + * + * @return the turn that was skipped. + * + * @since 1.7.2.0 + */ + public long getSkippedTurn() { + return skippedTurn; + } + + /** + * {@inheritDoc} + */ + @Override + public final int getPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + if (statics.isAdvancedRobot()) { + IAdvancedEvents listener = ((IAdvancedRobot) robot).getAdvancedEventListener(); + + if (listener != null) { + listener.onSkippedTurn(this); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + final boolean isCriticalEvent() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.SkippedTurnEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_LONG; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + SkippedTurnEvent obj = (SkippedTurnEvent) object; + + serializer.serialize(buffer, obj.skippedTurn); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + long skippedTurn = buffer.getLong(); + + return new SkippedTurnEvent(skippedTurn); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/StatusEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/StatusEvent.java new file mode 100644 index 0000000..3ef4c80 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/StatusEvent.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; + + +/** + * This event is sent to {@link Robot#onStatus(StatusEvent) onStatus()} every + * turn in a battle to provide the status of the robot. + * + * @author Flemming N. Larsen (original) + * + * @since 1.5 + */ +public final class StatusEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 99; + + private final RobotStatus status; + + /** + * This constructor is called internally from the game in order to create + * a new {@link RobotStatus}. + * + * @param status the current states + */ + public StatusEvent(RobotStatus status) { + super(); + + this.status = status; + } + + /** + * Returns the {@link RobotStatus} at the time defined by {@link Robot#getTime()}. + * + * @return the {@link RobotStatus} at the time defined by {@link Robot#getTime()}. + * @see #getTime() + */ + public RobotStatus getStatus() { + return status; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onStatus(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + throw new Error("Serialization of this type is not supported"); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/TeamRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/TeamRobot.java new file mode 100644 index 0000000..bd29ea7 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/TeamRobot.java @@ -0,0 +1,73 @@ +package robocode; + + +import robocode.robotinterfaces.ITeamEvents; +import robocode.robotinterfaces.ITeamRobot; +import robocode.robotinterfaces.peer.ITeamRobotPeer; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Vector; + + + +public class TeamRobot extends AdvancedRobot implements ITeamRobot, ITeamEvents { + + + public void broadcastMessage(Serializable message) throws IOException { + if (peer != null) { + ((ITeamRobotPeer) peer).broadcastMessage(message); + } else { + uninitializedException(); + } + } + + + public Vector getMessageEvents() { + if (peer != null) { + return new Vector(((ITeamRobotPeer) peer).getMessageEvents()); + } + uninitializedException(); + return null; // never called + } + + /** + * Do not call this method! + *

+ * {@inheritDoc} + */ + public final ITeamEvents getTeamEventListener() { + return this; // this robot is listening + } + + + public String[] getTeammates() { + if (peer != null) { + return ((ITeamRobotPeer) peer).getTeammates(); + } + uninitializedException(); + return null; + } + + + public boolean isTeammate(String name) { + if (peer != null) { + return ((ITeamRobotPeer) peer).isTeammate(name); + } + uninitializedException(); + return false; + } + + /** + * {@inheritDoc} + */ + public void onMessageReceived(MessageEvent event) {} + + public void sendMessage(String name, Serializable message) throws IOException { + if (peer != null) { + ((ITeamRobotPeer) peer).sendMessage(name, message); + } else { + uninitializedException(); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/TurnCompleteCondition.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/TurnCompleteCondition.java new file mode 100644 index 0000000..9e25dbb --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/TurnCompleteCondition.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * A prebuilt condition you can use that indicates your robot has finished + * turning. + * + * @see Condition + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Nathaniel Troutman (contributor) + */ +public class TurnCompleteCondition extends Condition { + private AdvancedRobot robot; + + /** + * Creates a new TurnCompleteCondition with default priority. + * The default priority is 80. + * + * @param robot your robot, which must be a {@link AdvancedRobot} + */ + public TurnCompleteCondition(AdvancedRobot robot) { + super(); + this.robot = robot; + } + + /** + * Creates a new TurnCompleteCondition with the specified priority. + * A condition priority is a value from 0 - 99. The higher value, the + * higher priority. The default priority is 80. + * + * @param robot your robot, which must be a {@link AdvancedRobot} + * @param priority the priority of this condition + * @see Condition#setPriority(int) + */ + public TurnCompleteCondition(AdvancedRobot robot, int priority) { + super(); + this.robot = robot; + this.priority = priority; + } + + /** + * Tests if the robot has finished turning. + * + * @return {@code true} if the robot has stopped turning; {@code false} + * otherwise + */ + @Override + public boolean test() { + return (robot.getTurnRemaining() == 0); + } + + /** + * Called by the system in order to clean up references to internal objects. + * + * @since 1.4.3 + */ + @Override + public void cleanup() { + robot = null; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/WinEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/WinEvent.java new file mode 100644 index 0000000..6d79462 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/WinEvent.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; + +import java.awt.*; +import java.nio.ByteBuffer; + + +/** + * This event is sent to {@link Robot#onWin(WinEvent) onWin()} when your robot + * wins the round in a battle. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public final class WinEvent extends Event { + private static final long serialVersionUID = 1L; + private final static int DEFAULT_PRIORITY = 100; // System event -> cannot be changed! + + /** + * Called by the game to create a new WinEvent. + */ + public WinEvent() { + super(); + } + + /** + * {@inheritDoc} + */ + @Override + public final int getPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final int getDefaultPriority() { + return DEFAULT_PRIORITY; + } + + /** + * {@inheritDoc} + */ + @Override + final void dispatch(IBasicRobot robot, IRobotStatics statics, Graphics2D graphics) { + IBasicEvents listener = robot.getBasicEventListener(); + + if (listener != null) { + listener.onWin(this); + } + } + + /** + * {@inheritDoc} + */ + @Override + final boolean isCriticalEvent() { + return true; + } + + /** + * {@inheritDoc} + */ + @Override + byte getSerializationType() { + return RbSerializer.WinEvent_TYPE; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) {} + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + return new WinEvent(); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/_AdvancedRadiansRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/_AdvancedRadiansRobot.java new file mode 100644 index 0000000..32dddbb --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/_AdvancedRadiansRobot.java @@ -0,0 +1,179 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import robocode.robotinterfaces.peer.IAdvancedRobotPeer; + + +/** + * This class is used by the system as a placeholder for all *Radians calls in + * {@link AdvancedRobot}. You may refer to this class for documentation only. + *

+ * You should create a {@link AdvancedRobot} instead. + *

+ * (The Radians methods themselves will continue work, however). + * + * @see Robot + * @see JuniorRobot + * @see AdvancedRobot + * @see TeamRobot + * @see RateControlRobot + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Pavel Savara (contributor) + */ +public class _AdvancedRadiansRobot extends _AdvancedRobot { + + _AdvancedRadiansRobot() {} + + public double getHeadingRadians() { + if (peer != null) { + return peer.getBodyHeading(); + } + uninitializedException(); + return 0; // never called + } + + public void setTurnLeftRadians(double radians) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnBody(-radians); + } else { + uninitializedException(); + } + } + + public void setTurnRightRadians(double radians) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnBody(radians); + } else { + uninitializedException(); + } + } + + public void turnLeftRadians(double radians) { + if (peer != null) { + peer.turnBody(-radians); + } else { + uninitializedException(); + } + } + + public void turnRightRadians(double radians) { + if (peer != null) { + peer.turnBody(radians); + } else { + uninitializedException(); + } + } + + public double getGunHeadingRadians() { + if (peer != null) { + return peer.getGunHeading(); + } + uninitializedException(); + return 0; // never called + } + + public double getRadarHeadingRadians() { + if (peer != null) { + return peer.getRadarHeading(); + } + uninitializedException(); + return 0; // never called + } + + public void setTurnGunLeftRadians(double radians) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnGun(-radians); + } else { + uninitializedException(); + } + } + + public void setTurnGunRightRadians(double radians) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnGun(radians); + } else { + uninitializedException(); + } + } + + public void setTurnRadarLeftRadians(double radians) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnRadar(-radians); + } else { + uninitializedException(); + } + } + + public void setTurnRadarRightRadians(double radians) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnRadar(radians); + } else { + uninitializedException(); + } + } + + public void turnGunLeftRadians(double radians) { + if (peer != null) { + peer.turnGun(-radians); + } else { + uninitializedException(); + } + } + + public void turnGunRightRadians(double radians) { + if (peer != null) { + peer.turnGun(radians); + } else { + uninitializedException(); + } + } + + public void turnRadarLeftRadians(double radians) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).turnRadar(-radians); + } else { + uninitializedException(); + } + } + + public void turnRadarRightRadians(double radians) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).turnRadar(radians); + } else { + uninitializedException(); + } + } + + public double getGunTurnRemainingRadians() { + if (peer != null) { + return peer.getGunTurnRemaining(); + } + uninitializedException(); + return 0; // never called + } + + public double getRadarTurnRemainingRadians() { + if (peer != null) { + return peer.getRadarTurnRemaining(); + } + uninitializedException(); + return 0; // never called + } + + public double getTurnRemainingRadians() { + if (peer != null) { + return peer.getBodyTurnRemaining(); + } + uninitializedException(); + return 0; // never called + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/_AdvancedRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/_AdvancedRobot.java new file mode 100644 index 0000000..0090040 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/_AdvancedRobot.java @@ -0,0 +1,273 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import robocode.robotinterfaces.peer.IAdvancedRobotPeer; + + +/** + * This class is used by the system, as well as being a placeholder for all deprecated + * (meaning, you should not use them) calls for {@link AdvancedRobot}. + *

+ * You should create a {@link AdvancedRobot} instead. + * + * @see Robot + * @see JuniorRobot + * @see AdvancedRobot + * @see TeamRobot + * @see RateControlRobot + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Pavel Savara (contributor) + */ +public class _AdvancedRobot extends Robot { + + _AdvancedRobot() {} + + /** + * @param degrees the amount of degrees to turn the robot's gun to the left. + * If {@code degrees} > 0 the robot's gun is set to turn left. + * If {@code degrees} < 0 the robot's gun is set to turn right. + * If {@code degrees} = 0 the robot's gun is set to stop turning. + * @deprecated Use {@link AdvancedRobot#setTurnGunLeft(double) + * setTurnGunLeft} instead. + */ + @Deprecated + public void setTurnGunLeftDegrees(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnGun(-Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * @param degrees the amount of degrees to turn the robot's gun to the right. + * If {@code degrees} > 0 the robot's gun is set to turn right. + * If {@code degrees} < 0 the robot's gun is set to turn left. + * If {@code degrees} = 0 the robot's gun is set to stop turning. + * @deprecated Use {@link AdvancedRobot#setTurnGunRight(double) + * setTurnGunRight} instead. + */ + @Deprecated + public void setTurnGunRightDegrees(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnGun(Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * @param degrees the amount of degrees to turn the robot's radar to the right. + * If {@code degrees} > 0 the robot's radar will turn right. + * If {@code degrees} < 0 the robot's radar will turn left. + * If {@code degrees} = 0 the robot's radar will not turn, but execute. + * @deprecated Use {@link Robot#turnRadarRight(double) turnRadarRight} + * instead. + */ + @Deprecated + public void turnRadarRightDegrees(double degrees) { + turnRadarRight(degrees); + } + + /** + * @param degrees the amount of degrees to turn the robot's body to the right. + * If {@code degrees} > 0 the robot is set to turn right. + * If {@code degrees} < 0 the robot is set to turn left. + * If {@code degrees} = 0 the robot is set to stop turning. + * @deprecated Use {@link AdvancedRobot#setTurnRight(double) + * setTurnRight(double)} instead. + */ + @Deprecated + public void setTurnRightDegrees(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnBody(Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * @param degrees the amount of degrees to turn the robot's radar to the left. + * If {@code degrees} > 0 the robot's radar is set to turn left. + * If {@code degrees} < 0 the robot's radar is set to turn right. + * If {@code degrees} = 0 the robot's radar is set to stop turning. + * @deprecated Use {@link AdvancedRobot#setTurnRadarLeft(double) + * setTurnRadarLeft(double)} instead. + */ + @Deprecated + public void setTurnRadarLeftDegrees(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnRadar(-Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * @param degrees the amount of degrees to turn the robot's body to the left. + * If {@code degrees} > 0 the robot is set to turn left. + * If {@code degrees} < 0 the robot is set to turn right. + * If {@code degrees} = 0 the robot is set to stop turning. + * @deprecated Use {@link AdvancedRobot#setTurnLeft(double) + * setTurnLeft(double)} instead. + */ + @Deprecated + public void setTurnLeftDegrees(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnBody(-Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * @return the direction that the robot's body is facing, in degrees. + * @deprecated Use {@link Robot#getHeading() getHeading()} instead. + */ + @Deprecated + public double getHeadingDegrees() { + return getHeading(); + } + + /** + * @param degrees the amount of degrees to turn the robot's body to the left. + * If {@code degrees} > 0 the robot will turn left. + * If {@code degrees} < 0 the robot will turn right. + * If {@code degrees} = 0 the robot will not turn, but execute. + * @deprecated Use {@link Robot#turnLeft(double) turnLeft(double)} instead. + */ + @Deprecated + public void turnLeftDegrees(double degrees) { + turnLeft(degrees); + } + + /** + * @param degrees the amount of degrees to turn the robot's body to the right. + * If {@code degrees} > 0 the robot will turn right. + * If {@code degrees} < 0 the robot will turn left. + * If {@code degrees} = 0 the robot will not turn, but execute. + * @deprecated Use {@link Robot#turnRight(double) turnRight(double)} instead. + */ + @Deprecated + public void turnRightDegrees(double degrees) { + turnRight(degrees); + } + + /** + * @deprecated Use {@link AdvancedRobot#execute() execute} instead. + */ + @Deprecated + public void endTurn() { + if (peer != null) { + peer.execute(); + } else { + uninitializedException(); + } + } + + /** + * @return the direction that the robot's gun is facing, in degrees. + * @deprecated Use {@link Robot#getGunHeading() getGunHeading()} instead. + */ + @Deprecated + public double getGunHeadingDegrees() { + return getGunHeading(); + } + + /** + * @return the direction that the robot's radar is facing, in degrees. + * @deprecated Use {@link Robot#getRadarHeading() getRadarHeading()} instead. + */ + @Deprecated + public double getRadarHeadingDegrees() { + return getRadarHeading(); + } + + /** + * @return allways {@code 0} as this method is no longer functional. + * @deprecated This method is no longer functional. + * Use {@link AdvancedRobot#onSkippedTurn(SkippedTurnEvent)} instead. + */ + @Deprecated + public int getWaitCount() { + if (peer != null) { + peer.getCall(); + } + return 0; + } + + /** + * @param degrees the amount of degrees to turn the robot's radar to the right. + * If {@code degrees} > 0 the robot's radar is set to turn right. + * If {@code degrees} < 0 the robot's radar is set to turn left. + * If {@code degrees} = 0 the robot's radar is set to stop turning. + * @deprecated Use {@link AdvancedRobot#setTurnRadarRight(double) + * setTurnRadarRight} instead. + */ + @Deprecated + public void setTurnRadarRightDegrees(double degrees) { + if (peer != null) { + ((IAdvancedRobotPeer) peer).setTurnRadar(Math.toRadians(degrees)); + } else { + uninitializedException(); + } + } + + /** + * @param degrees the amount of degrees to turn the robot's gun to the left. + * If {@code degrees} > 0 the robot's gun will turn left. + * If {@code degrees} < 0 the robot's gun will turn right. + * If {@code degrees} = 0 the robot's gun will not turn, but execute. + * @deprecated Use {@link Robot#turnGunLeft(double) turnGunLeft} instead. + */ + @Deprecated + public void turnGunLeftDegrees(double degrees) { + turnGunLeft(degrees); + } + + /** + * @param degrees the amount of degrees to turn the robot's gun to the right. + * If {@code degrees} > 0 the robot's gun will turn right. + * If {@code degrees} < 0 the robot's gun will turn left. + * If {@code degrees} = 0 the robot's gun will not turn, but execute. + * @deprecated Use {@link Robot#turnGunRight(double) turnGunRight} instead. + */ + @Deprecated + public void turnGunRightDegrees(double degrees) { + turnGunRight(degrees); + } + + /** + * @param degrees the amount of degrees to turn the robot's radar to the left. + * If {@code degrees} > 0 the robot's radar will turn left. + * If {@code degrees} < 0 the robot's radar will turn right. + * If {@code degrees} = 0 the robot's radar will not turn, but execute. + * @deprecated Use {@link Robot#turnRadarLeft(double) turnRadarLeft} instead. + */ + @Deprecated + public void turnRadarLeftDegrees(double degrees) { + turnRadarLeft(degrees); + } + + /** + * @return allways {@code 0} as this method is no longer functional. + * @deprecated This method is no longer functional. + * Use {@link AdvancedRobot#onSkippedTurn(SkippedTurnEvent)} instead. + */ + @Deprecated + public int getMaxWaitCount() { + if (peer != null) { + peer.getCall(); + } + return 0; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/_Robot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/_Robot.java new file mode 100644 index 0000000..3ff146c --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/_Robot.java @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * This class is used by the system, as well as being a placeholder for all deprecated + * (meaning, you should not use them) calls for {@link Robot}. + *

+ * You should create a {@link Robot} instead. + * + * @see Robot + * @see JuniorRobot + * @see AdvancedRobot + * @see TeamRobot + * @see RateControlRobot + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Pavel Savara (contributor) + */ +public abstract class _Robot extends _RobotBase { + private String robotImageName; + private String gunImageName; + private String radarImageName; + + _Robot() {} + + /** + * @return 5 - {@link robocode.Robot#getGunHeat() getGunHeat()}. + * @deprecated Use {@link Robot#getGunHeat() getGunHeat()} instead. + */ + @Deprecated + public double getGunCharge() { + if (peer != null) { + return 5 - peer.getGunHeat(); + } + uninitializedException(); + return 0; // never called + } + + /** + * @return the robot's current life/energy. + * @deprecated Use {@link Robot#getEnergy() getEnergy()} instead. + */ + @Deprecated + public double getLife() { + if (peer != null) { + return peer.getEnergy(); + } + uninitializedException(); + return 0; // never called + } + + /** + * @return the number of rounds in the current battle + * @deprecated Use {@link Robot#getNumRounds() getNumRounds()} instead. + */ + @Deprecated + public int getNumBattles() { + if (peer != null) { + return peer.getNumRounds(); + } + uninitializedException(); + return 0; // never called + } + + /** + * @return the current round number of the battle (zero indexed). + * @deprecated Use {@link Robot#getRoundNum() getRoundNum()} instead. + */ + @Deprecated + public int getBattleNum() { + if (peer != null) { + return peer.getRoundNum(); + } + uninitializedException(); + return 0; // never called + } + + /** + * This call has moved to {@link AdvancedRobot}, and will no longer function in + * the {@link Robot} class. + * + * @param interruptible {@code true} if the event handler should be + * interrupted if new events of the same priority occurs; {@code false} + * otherwise + */ + public void setInterruptible(boolean interruptible) {} + + /** + * @return the name of the gun image + * @deprecated This call is not used. + */ + @Deprecated + public String getGunImageName() { + return gunImageName; + } + + /** + * @param newGunImageName the name of the new gun image + * @deprecated This call is not used. + */ + @Deprecated + public void setGunImageName(String newGunImageName) { + gunImageName = newGunImageName; + } + + /** + * @param newRadarImageName the name of the new radar image + * @deprecated This call is not used. + */ + @Deprecated + public void setRadarImageName(String newRadarImageName) { + radarImageName = newRadarImageName; + } + + /** + * @param newRobotImageName the name of the new robot body image + * @deprecated This call is not used. + */ + @Deprecated + public void setRobotImageName(String newRobotImageName) { + robotImageName = newRobotImageName; + } + + /** + * @return the name of the radar image + * @deprecated This call is not used. + */ + @Deprecated + public String getRadarImageName() { + return radarImageName; + } + + /** + * @return the name of the robot image + * @deprecated This call is not used. + */ + @Deprecated + public String getRobotImageName() { + return robotImageName; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/_RobotBase.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/_RobotBase.java new file mode 100644 index 0000000..b760340 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/_RobotBase.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +import robocode.exception.RobotException; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.peer.IBasicRobotPeer; + + +/** + * This is the base class of all robots used by the system. + * You should not inherit your robot on this class. + *

+ * You should create a robot that is derived from the {@link Robot}, {@link AdvancedRobot}, + * {@link JuniorRobot}, {@link TeamRobot}, or {@link RateControlRobot} class instead. + * + * @see Robot + * @see JuniorRobot + * @see AdvancedRobot + * @see TeamRobot + * @see RateControlRobot + * + * @author Flemming N. Larsen (original) + * @author Pavel Savara (contributor) + * + * @since 1.4 + */ +public abstract class _RobotBase implements IBasicRobot, Runnable { + + // Internal for this package + _RobotBase() {} + + IBasicRobotPeer peer; + + /** + * The output stream your robot should use to print. + *

+ * You can view the print-outs by clicking the button for your robot in the + * right side of the battle window. + *

+ * Example: + *

+	 *   // Print out a line each time my robot hits another robot
+	 *   public void onHitRobot(HitRobotEvent e) {
+	 *       out.println("I hit a robot!  My energy: " + getEnergy() + " his energy: " + e.getEnergy());
+	 *   }
+	 * 
+ */ + public java.io.PrintStream out; + + /** + * Called by the system to 'clean up' after your robot. + * You may not override this method. + */ + @Override + protected final void finalize() throws Throwable { // This method must be final so it cannot be overridden! + super.finalize(); + } + + /** + * {@inheritDoc} + */ + public final void setOut(java.io.PrintStream out) { + this.out = out; + } + + /** + * {@inheritDoc} + */ + public final void setPeer(IBasicRobotPeer peer) { + this.peer = peer; + } + + /** + * Throws a RobotException. This method should be called when the robot's peer + * is uninitialized. + */ + static void uninitializedException() { + StackTraceElement[] trace = Thread.currentThread().getStackTrace(); + String methodName = trace[2].getMethodName(); + + throw new RobotException( + "You cannot call the " + methodName + + "() method before your run() method is called, or you are using a Robot object that the game doesn't know about."); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/annotation/SafeStatic.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/annotation/SafeStatic.java new file mode 100644 index 0000000..fdebf04 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/annotation/SafeStatic.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.annotation; + + +import java.lang.annotation.*; + + +/** + * Annotation used for marking a static field as being safe so that Robocode should + * not print out warnings at runtime when this annotation is being used. + * For example, Robocode will print out warnings if a static field to a robot is found. + * But not when the @SafeStatic is declared for the static field. + * + * @author Flemming N. Larsen (original) + * + * @since 1.7.2.1 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface SafeStatic {} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/annotation/package-info.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/annotation/package-info.java new file mode 100644 index 0000000..65daba2 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/annotation/package-info.java @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + +/** + * Contains annotations that can be used with Robocode. + */ +package robocode.annotation; diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/BattleSpecification.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/BattleSpecification.java new file mode 100644 index 0000000..ceba0fb --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/BattleSpecification.java @@ -0,0 +1,234 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control; + + +/** + * A BattleSpecification defines a battle configuration used by the {@link RobocodeEngine}. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class BattleSpecification implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + + private final int battlefieldWidth; + private final int battlefieldHeight; + private final int numRounds; + private final double gunCoolingRate; + private final long inactivityTime; + private final boolean hideEnemyNames; + private final int sentryBorderSize; + private final RobotSpecification[] robots; + private final RobotSetup[] initialSetups; + + /** + * Creates a new BattleSpecification with the given number of rounds, battlefield size, and robots. + * Inactivity time for the robots defaults to 450, and the gun cooling rate defaults to 0.1. + * + * @param numRounds is the number of rounds in this battle. + * @param battlefieldSize is the battlefield size. + * @param robots is the robots participating in this battle. + */ + public BattleSpecification(int numRounds, BattlefieldSpecification battlefieldSize, RobotSpecification[] robots) { + this(numRounds, 450, 0.1, battlefieldSize, robots); + } + + /** + * Creates a new BattleSpecification with the given settings. + * + * @param numRounds is the number of rounds in this battle. + * @param inactivityTime is the inactivity time allowed for the robots before they will loose energy. + * @param gunCoolingRate is the gun cooling rate for the robots. + * @param battlefieldSize is the battlefield size. + * @param robots is the robots participating in this battle. + */ + public BattleSpecification(int numRounds, long inactivityTime, double gunCoolingRate, BattlefieldSpecification battlefieldSize, RobotSpecification[] robots) { + this(numRounds, inactivityTime, gunCoolingRate, false, battlefieldSize, robots); + } + + /** + * Creates a new BattleSpecification with the given settings. + * + * @param numRounds is the number of rounds in this battle. + * @param inactivityTime is the inactivity time allowed for the robots before they will loose energy. + * @param gunCoolingRate is the gun cooling rate for the robots. + * @param hideEnemyNames flag specifying if enemy names are hidden from robots. + * @param battlefieldSize is the battlefield size. + * @param robots is the robots participating in this battle. + * + * @since 1.7.3 + */ + public BattleSpecification(int numRounds, long inactivityTime, double gunCoolingRate, boolean hideEnemyNames, BattlefieldSpecification battlefieldSize, RobotSpecification[] robots) { + this(battlefieldSize, numRounds, inactivityTime, gunCoolingRate, 100, hideEnemyNames, robots); + } + + /** + * Creates a new BattleSpecification with the given settings. + * + * @param battlefieldSize is the battlefield size. + * @param numRounds is the number of rounds in this battle. + * @param inactivityTime is the inactivity time allowed for the robots before they will loose energy. + * @param gunCoolingRate is the gun cooling rate for the robots. + * @param sentryBorderSize is the sentry border size for a {@link robocode.BorderSentry BorderSentry}. + * @param hideEnemyNames flag specifying if enemy names are hidden from robots. + * @param robots is the robots participating in this battle. + * + * @since 1.9.0.0 + */ + public BattleSpecification(BattlefieldSpecification battlefieldSize, int numRounds, long inactivityTime, double gunCoolingRate, int sentryBorderSize, boolean hideEnemyNames, RobotSpecification[] robots) { + this(battlefieldSize, numRounds, inactivityTime, gunCoolingRate, 100, hideEnemyNames, robots, null); + } + + /** + * Creates a new BattleSpecification with the given settings. + * + * @param battlefieldSize is the battlefield size. + * @param numRounds is the number of rounds in this battle. + * @param inactivityTime is the inactivity time allowed for the robots before they will loose energy. + * @param gunCoolingRate is the gun cooling rate for the robots. + * @param sentryBorderSize is the sentry border size for a {@link robocode.BorderSentry BorderSentry}. + * @param hideEnemyNames flag specifying if enemy names are hidden from robots. + * @param robots is the robots participating in this battle. + * @param initialSetup is the initial position and heading of the robots, where the indices matches the indices from the {@code robots} parameter. + * + * @since 1.9.2.0 + */ + public BattleSpecification(BattlefieldSpecification battlefieldSize, int numRounds, long inactivityTime, double gunCoolingRate, int sentryBorderSize, boolean hideEnemyNames, RobotSpecification[] robots, RobotSetup[] initialSetups) { + if (battlefieldSize == null) { + throw new IllegalArgumentException("battlefieldSize cannot be null"); + } + if (robots == null) { + throw new IllegalArgumentException("robots cannot be null"); + } + if (robots.length < 1) { + throw new IllegalArgumentException("robots.length must be > 0"); + } + if (initialSetups != null && initialSetups.length != robots.length) { + throw new IllegalArgumentException("initialSetups.length must be == robots.length"); + } + if (numRounds < 1) { + throw new IllegalArgumentException("numRounds must be >= 1"); + } + if (inactivityTime < 1) { + throw new IllegalArgumentException("inactivityTime must be >= 1"); + } + if (gunCoolingRate < 0.1) { + throw new IllegalArgumentException("inactivityTime must be >= 0.1"); + } + if (sentryBorderSize < 50) { + throw new IllegalArgumentException("sentryBorderSize must be >= 50"); + } + this.battlefieldWidth = battlefieldSize.getWidth(); + this.battlefieldHeight = battlefieldSize.getHeight(); + this.numRounds = numRounds; + this.inactivityTime = inactivityTime; + this.gunCoolingRate = gunCoolingRate; + this.sentryBorderSize = sentryBorderSize; + this.hideEnemyNames = hideEnemyNames; + this.robots = robots; + this.initialSetups = initialSetups; + } + + /** + * Returns the allowed inactivity time for the robots in this battle. + * + * @return the allowed inactivity time for the robots in this battle. + */ + public long getInactivityTime() { + return inactivityTime; + } + + /** + * Returns the gun cooling rate of the robots in this battle. + * + * @return the gun cooling rate of the robots in this battle. + */ + public double getGunCoolingRate() { + return gunCoolingRate; + } + + /** + * Returns the battlefield size for this battle. + * + * @return the battlefield size for this battle. + */ + public BattlefieldSpecification getBattlefield() { + return new BattlefieldSpecification(battlefieldWidth, battlefieldHeight); + } + + /** + * Returns the number of rounds in this battle. + * + * @return the number of rounds in this battle. + */ + public int getNumRounds() { + return numRounds; + } + + /** + * Returns the flag specifying if the enemy names must be hidden from events sent to robots. + * + * @return {@code true} if the enemy names must be hidden; {@code false} otherwise. + * + * @since 1.7.3 + */ + public boolean getHideEnemyNames() { + return hideEnemyNames; + } + + /** + * Returns the sentry border size for a {@link robocode.BorderSentry BorderSentry} that defines the how + * far a BorderSentry is allowed to move from the border edges measured in units.
+ * Hence, the sentry border size defines the width/range of the border area surrounding the battlefield that + * border sentry robots cannot leave (they must stay in the border area), but it also define the + * distance from the border edges where border sentry robots are allowed/able to make damage to robots entering this + * border area. + * + * @return the border size in units/pixels that border sentry robots are restricted to. + * + * @since 1.9.0.0 + */ + public int getSentryBorderSize() { + return sentryBorderSize; + } + + /** + * Returns the specifications of the robots participating in this battle. + * + * @return an array of {@link RobotSpecification} instances - one entry for each robot. + * + * @see #getInitialSetups() + */ + public RobotSpecification[] getRobots() { + if (robots == null) { + return null; + } + RobotSpecification[] robotsCopy = new RobotSpecification[robots.length]; + System.arraycopy(robots, 0, robotsCopy, 0, robots.length); + return robotsCopy; + } + + /** + * Returns the initial position and heading of each robot participating in this battle. + * + * @return an array of {@link RobotSetup} instances - one entry for each robot. + * The the indices of this array matches the array indices from the robot specifications (see {@link #getRobots()}). + * + * @see #getRobots() + */ + public RobotSetup[] getInitialSetups() { + if (initialSetups == null) { + return null; + } + RobotSetup[] setupsCopy = new RobotSetup[initialSetups.length]; + System.arraycopy(initialSetups, 0, setupsCopy, 0, initialSetups.length); + return setupsCopy; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/BattlefieldSpecification.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/BattlefieldSpecification.java new file mode 100644 index 0000000..abbc012 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/BattlefieldSpecification.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control; + + +/** + * Defines the size of a battlefield, which is a part of the {@link BattleSpecification}. + * + * @see BattleSpecification#BattleSpecification(int, BattlefieldSpecification, RobotSpecification[]) + * @see BattleSpecification#BattleSpecification(int, long, double, BattlefieldSpecification, RobotSpecification[]) + * @see BattleSpecification#getBattlefield() + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class BattlefieldSpecification implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + + private final int width; + private final int height; + + /** + * Creates a standard 800 x 600 battlefield. + */ + public BattlefieldSpecification() { + this(800, 600); + } + + /** + * Creates a battlefield of the specified width and height. + * + * @param width the width of the battlefield, where 400 <= width <= 5000. + * @param height the height of the battlefield, where 400 <= height <= 5000. + * @throws IllegalArgumentException if the width or height < 400 or > 5000. + */ + public BattlefieldSpecification(int width, int height) { + if (width < 400 || width > 5000) { + throw new IllegalArgumentException("width must be: 400 <= width <= 5000"); + } + if (height < 400 || height > 5000) { + throw new IllegalArgumentException("height must be: 400 <= height <= 5000"); + } + + this.width = width; + this.height = height; + } + + /** + * Returns the width of this battlefield. + * + * @return the width of this battlefield. + */ + public int getWidth() { + return width; + } + + /** + * Returns the height of this battlefield. + * + * @return the height of this battlefield. + */ + public int getHeight() { + return height; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/IRobocodeEngine.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/IRobocodeEngine.java new file mode 100644 index 0000000..9b85382 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/IRobocodeEngine.java @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control; + + +import robocode.control.events.IBattleListener; + + +/** + * Interface for the RobocodeEngine. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public interface IRobocodeEngine { + + /** + * Adds a battle listener that must receive events occurring in battles. + * + * @param listener the battle listener that must retrieve the event from + * the battles. + * @see #removeBattleListener(robocode.control.events.IBattleListener) + * @since 1.6.2 + */ + void addBattleListener(IBattleListener listener); + + /** + * Removes a battle listener that has previously been added to this object. + * + * @param listener the battle listener that must be removed. + * @see #addBattleListener(robocode.control.events.IBattleListener) + * @since 1.6.2 + */ + void removeBattleListener(IBattleListener listener); + + /** + * Closes the RobocodeEngine and releases any allocated resources it holds. + * You should call this when you have finished using the RobocodeEngine. + * This method automatically disposes the Robocode window if it open. + */ + void close(); + + /** + * Returns the installed version of Robocode controlled by this RobocodeEngine. + * + * @return the installed version of Robocode controlled by this RobocodeEngine. + */ + String getVersion(); + + /** + * Shows or hides the Robocode window. + * + * @param visible {@code true} if the Robocode window must be set visible; + * {@code false} otherwise. + */ + void setVisible(boolean visible); + + /** + * Returns all robots available from the local robot repository of Robocode. + * These robots must exists in the /robocode/robots directory, and must be + * compiled in advance, before these robot are returned with this method. + * + * @return an array of all available robots from the local robot repository. + * @see robocode.control.RobotSpecification + * @see #getLocalRepository(String) + */ + RobotSpecification[] getLocalRepository(); + + /** + * Returns a selection of robots available from the local robot repository + * of Robocode. These robots must exists in the /robocode/robots directory, + * and must be compiled in advance, before these robot are returned with this method. + *

+ * Notice: If a specified robot cannot be found in the repository, it will + * not be returned in the array of robots returned by this method. + * + * @param selectedRobotList a comma or space separated list of robots to + * return. The full class name must be used for + * specifying the individual robot, e.g. + * "sample.Corners, sample.Crazy". + * @return an array containing the available robots from the local robot + * repository based on the selected robots specified with the + * {@code selectedRobotList} parameter. + * @see robocode.control.RobotSpecification + * @see #getLocalRepository() + * @since 1.6.2 + */ + RobotSpecification[] getLocalRepository(String selectedRobotList); + + /** + * Runs the specified battle. + * + * @param battleSpecification the specification of the battle to run including the + * participation robots. + * @see #runBattle(robocode.control.BattleSpecification, boolean) + * @see robocode.control.BattleSpecification + * @see #getLocalRepository() + */ + void runBattle(BattleSpecification battleSpecification); + + /** + * Runs the specified battle. + * + * @param battleSpecification the specification of the battle to run including the + * participating robots. + * @param waitTillOver will block caller till end of battle if set + * @see #runBattle(robocode.control.BattleSpecification) + * @see robocode.control.BattleSpecification + * @see #getLocalRepository() + * @since 1.6.2 + */ + void runBattle(BattleSpecification battleSpecification, boolean waitTillOver); + + /** + * Runs the specified battle. + * + * @param battleSpecification the specification of the battle to run including the + * participating robots. + * @param initialPositions a comma or space separated list like: x1,y1,heading1, + * x2,y2,heading2, which are the coordinates and heading of robot #1 and #2. + * So e.g. 0,0,180, 50,80,270 means that robot #1 has position (0,0) and + * heading 180, and robot #2 has position (50,80) and heading 270. + * @param waitTillOver will block caller till end of battle if set + * @see #runBattle(BattleSpecification) + * @see BattleSpecification + * @see #getLocalRepository() + * @since 1.7.1.2 + */ + void runBattle(BattleSpecification battleSpecification, String initialPositions, boolean waitTillOver); + + /** + * Will block caller until current battle is over. + * @see #runBattle(robocode.control.BattleSpecification) + * @see #runBattle(robocode.control.BattleSpecification, boolean) + * @since 1.6.2 + */ + void waitTillBattleOver(); + + /** + * Aborts the current battle if it is running. + * + * @see #runBattle(robocode.control.BattleSpecification) + */ + void abortCurrentBattle(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RandomFactory.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RandomFactory.java new file mode 100644 index 0000000..28833f0 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RandomFactory.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control; + + +import static net.sf.robocode.io.Logger.logError; +import static net.sf.robocode.io.Logger.logWarning; + +import java.lang.reflect.Field; +import java.util.Random; + + +/** + * The RandomFactory is used for controlling the generation of random numbers, + * and supports generating random numbers that are deterministic, which is + * useful for testing purposes. + * + * @author Pavel Savara (original) + * + * @since 1.6.1 + */ +public class RandomFactory { + private static Random randomNumberGenerator; + + private static boolean warningNotSupportedLogged; + private static boolean isDeterministic; + + static { + randomNumberGenerator = new Random(); + } + + public boolean isDeterministic() { + return isDeterministic; + } + + /** + * Returns the random number generator used for generating a stream of + * random numbers. + * + * @return a {@link java.util.Random} instance. + * @see java.util.Random + */ + public static Random getRandom() { + if (randomNumberGenerator == null) { + try { + Math.random(); + final Field field = Math.class.getDeclaredField("randomNumberGenerator"); + final boolean savedFieldAccessible = field.isAccessible(); + + field.setAccessible(true); + randomNumberGenerator = (Random) field.get(null); + field.setAccessible(savedFieldAccessible); + } catch (NoSuchFieldException e) { + logWarningNotSupported(); + randomNumberGenerator = new Random(); + } catch (IllegalAccessException e) { + logError(e); + randomNumberGenerator = new Random(); + } + } + return randomNumberGenerator; + } + + /** + * Sets the random number generator instance used for generating a + * stream of random numbers. + * + * @param random a {@link java.util.Random} instance. + * @see java.util.Random + */ + public static void setRandom(Random random) { + randomNumberGenerator = random; + try { + Math.random(); + final Field field = Math.class.getDeclaredField("randomNumberGenerator"); + final boolean savedFieldAccessible = field.isAccessible(); + + field.setAccessible(true); + field.set(null, randomNumberGenerator); + field.setAccessible(savedFieldAccessible); + } catch (NoSuchFieldException e) { + logWarningNotSupported(); + } catch (IllegalAccessException e) { + logError(e); + } + + // TODO ZAMO using Robot classloader inject seed also for all instances being created by robots + } + + /** + * Resets the random number generator instance to be deterministic when + * generating random numbers. + * + * @param seed the seed to use for the new deterministic random generator. + */ + public static void resetDeterministic(long seed) { + setRandom(new Random(seed)); + isDeterministic = true; + } + + /** + * Logs a warning that the deterministic random feature is not supported by the JVM. + */ + private static void logWarningNotSupported() { + if (!(warningNotSupportedLogged || System.getProperty("RANDOMSEED", "none").equals("none"))) { + logWarning( + "The deterministic random generator feature is not supported by this JVM:\n" + + System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.name") + " " + + System.getProperty("java.vm.version")); + + warningNotSupportedLogged = true; + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobocodeEngine.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobocodeEngine.java new file mode 100644 index 0000000..9166b33 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobocodeEngine.java @@ -0,0 +1,364 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control; + + +import net.sf.robocode.battle.IBattleManagerBase; +import net.sf.robocode.core.ContainerBase; +import net.sf.robocode.gui.IWindowManagerBase; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.manager.IVersionManagerBase; +import net.sf.robocode.repository.IRepositoryManagerBase; +import net.sf.robocode.security.HiddenAccess; +import robocode.control.events.*; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + + +/** + * The RobocodeEngine is the interface provided for external applications + * in order to let these applications run battles within the Robocode application, + * and to get the results from these battles. + *

+ * This class in the main entry class of the {@code robocode.control} package. + *

+ * The RobocodeEngine is used by e.g. RoboRumble@Home client, which is integrated in + * Robocode. In addition, the RobocodeEngine is also used by the test units for + * testing the Robocode application itself. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + * @author Nathaniel Troutman (contributor) + * @author Joachim Hofer (contributor) + * @author Pavel Savara (contributor) + */ +public class RobocodeEngine implements IRobocodeEngine { + + private BattleObserver battleObserver; + private BattleSpecification battleSpecification; + private List listeners = new ArrayList(); + + /** + * Creates a new RobocodeEngine for controlling Robocode. + * In order for this constructor to work, the current working directory must be the + * home directory directory of Robocode, e.g. C:\Robocode + * + * @see #RobocodeEngine(File) + * @see #close() + * @since 1.6.2 + */ + public RobocodeEngine() { + init(null, (IBattleListener) null); + } + + /** + * Creates a new RobocodeEngine for controlling Robocode. + * + * @param robocodeHome the home directory of Robocode, e.g. C:\Robocode. + * @see #RobocodeEngine() + * @see #close() + * @since 1.6.2 + */ + public RobocodeEngine(File robocodeHome) { + init(robocodeHome, (IBattleListener) null); + } + + /** + * @deprecated Since 1.6.2. Use {@link #RobocodeEngine(File)} and + * {@link #addBattleListener(IBattleListener) addBattleListener()} instead. + *

+ * Creates a new RobocodeEngine for controlling Robocode. + * + * @param robocodeHome the root directory of Robocode, e.g. C:\Robocode. + * @param listener the listener that must receive the callbacks from this + * RobocodeEngine. + * @see #RobocodeEngine() + * @see #RobocodeEngine(File) + * @see #close() + */ + @Deprecated + public RobocodeEngine(File robocodeHome, RobocodeListener listener) { + init(robocodeHome, listener); + } + + /** + * @deprecated Since 1.6.2. Use {@link #RobocodeEngine()} and + * {@link #addBattleListener(IBattleListener) addBattleListener()} instead. + *

+ * Creates a new RobocodeEngine for controlling Robocode. The JAR file of + * Robocode is used to determine the root directory of Robocode. + * + * @param listener the listener that must receive the callbacks from this + * RobocodeEngine. + * @see #RobocodeEngine() + * @see #RobocodeEngine(File) + * @see #close() + */ + @Deprecated + public RobocodeEngine(RobocodeListener listener) { + init(null, listener); + } + + public RobocodeEngine(IBattleListener listener) { + init(null, listener); + } + + /** + * {@inheritDoc} + */ + @Override + protected void finalize() throws Throwable { + try { + // Make sure close() is called to prevent memory leaks + close(); + } finally { + super.finalize(); + } + } + + @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener + private void init(File robocodeHome, RobocodeListener listener) { + if (listener != null) { + battleObserver = new BattleObserver(); + battleObserver.listener = listener; + } + HiddenAccess.initContainerForRobotEngine(robocodeHome, battleObserver); + } + + private void init(File robocodeHome, IBattleListener listener) { + HiddenAccess.initContainerForRobotEngine(robocodeHome, listener); + } + + /** + * {@inheritDoc} + */ + public void addBattleListener(IBattleListener listener) { + listeners.add(listener); + ContainerBase.getComponent(IBattleManagerBase.class).addListener(listener); + } + + /** + * {@inheritDoc} + */ + public void removeBattleListener(IBattleListener listener) { + listeners.remove(listener); + ContainerBase.getComponent(IBattleManagerBase.class).removeListener(listener); + } + + /** + * {@inheritDoc} + */ + public void close() { + setVisible(false); + if (battleObserver != null) { + ContainerBase.getComponent(IBattleManagerBase.class).removeListener(battleObserver); + } + for (IBattleListener listener : listeners) { + ContainerBase.getComponent(IBattleManagerBase.class).removeListener(listener); + } + listeners.clear(); + HiddenAccess.cleanup(); + } + + /** + * {@inheritDoc} + */ + public String getVersion() { + return ContainerBase.getComponent(IVersionManagerBase.class).getVersion(); + } + + /** + * Returns the current working directory. + * + * @return a File for the current working directory. + * + * @since 1.7.1 + */ + public static File getCurrentWorkingDir() { + return FileUtil.getCwd(); + } + + /** + * Returns the directory containing the robots. + * + * @return a File for the robot directory containing all robots. + * + * @since 1.7.1 + */ + public static File getRobotsDir() { + return FileUtil.getRobotsDir(); + } + + /** + * {@inheritDoc} + */ + public void setVisible(boolean visible) { + IWindowManagerBase windowManager = ContainerBase.getComponent(IWindowManagerBase.class); + if (windowManager != null) { + windowManager.setVisibleForRobotEngine(visible); + } else { + Logger.logError( + "setVisible: No window manager was found.\n" + + "Perhaps you are missing the robocode.ui-1.x.x.x-jar file or the GUI has been disabled?"); + } + } + + /** + * {@inheritDoc} + */ + public RobotSpecification[] getLocalRepository() { + final IRepositoryManagerBase repository = ContainerBase.getComponent(IRepositoryManagerBase.class); + + repository.refresh(); // Bug fix [2972932] + return repository.getSpecifications(); + } + + /** + * {@inheritDoc} + */ + public RobotSpecification[] getLocalRepository(String selectedRobots) { + final IRepositoryManagerBase repository = ContainerBase.getComponent(IRepositoryManagerBase.class); + + repository.refresh(); // Bug fix [2972932] + return repository.loadSelectedRobots(selectedRobots); + } + + /** + * {@inheritDoc} + */ + public void runBattle(BattleSpecification battleSpecification) { + runBattle(battleSpecification, null, false); + } + + /** + * {@inheritDoc} + */ + public void runBattle(BattleSpecification battleSpecification, boolean waitTillOver) { + runBattle(battleSpecification, null, waitTillOver); + } + + /** + * {@inheritDoc} + */ + public void runBattle(BattleSpecification battleSpecification, String initialPositions, boolean waitTillOver) { + this.battleSpecification = battleSpecification; + ContainerBase.getComponent(IBattleManagerBase.class).startNewBattle(battleSpecification, initialPositions, + waitTillOver, false); + } + + /** + * {@inheritDoc} + */ + public void waitTillBattleOver() { + ContainerBase.getComponent(IBattleManagerBase.class).waitTillOver(); + } + + /** + * {@inheritDoc} + */ + public void abortCurrentBattle() { + ContainerBase.getComponent(IBattleManagerBase.class).stop(true); + } + + /** + * Prints out all running threads to standard system out. + * + * @since 1.6.2 + */ + public static void printRunningThreads() { + ThreadGroup currentGroup = Thread.currentThread().getThreadGroup(); + + if (currentGroup == null) { + return; + } + + while (currentGroup.getParent() != null) { + currentGroup = currentGroup.getParent(); + } + + ThreadGroup groups[] = new ThreadGroup[256]; + Thread threads[] = new Thread[256]; + + int numGroups = currentGroup.enumerate(groups, true); + + for (int i = 0; i < numGroups; i++) { + currentGroup = groups[i]; + if (currentGroup.isDaemon()) { + Logger.realOut.print(" "); + } else { + Logger.realOut.print("* "); + } + Logger.realOut.println("In group: " + currentGroup.getName()); + int numThreads = currentGroup.enumerate(threads); + + for (int j = 0; j < numThreads; j++) { + if (threads[j].isDaemon()) { + Logger.realOut.print(" "); + } else { + Logger.realOut.print("* "); + } + Logger.realOut.println(threads[j].getName()); + } + Logger.realOut.println("---------------"); + } + } + + /** + * Enables or disables messages and warnings logged to {@link System#out}. + * + * @param enable true if log messages must be enabled; false if log messages must be disabled. + * @see #setLogErrorsEnabled(boolean) + * @since 1.8.0.0 + */ + public static void setLogMessagesEnabled(boolean enable) { + System.setProperty("logMessages", "" + enable); + } + + /** + * Enables or disables errors logged to {@link System#err}. + * + * @param enable true if log errors must be enabled; false if log errors must be disabled. + * @see #setLogMessagesEnabled(boolean) + * @since 1.8.0.0 + */ + public static void setLogErrorsEnabled(boolean enable) { + System.setProperty("logErrors", "" + enable); + } + + /** + * Registered only if listener in not null. + */ + private class BattleObserver extends BattleAdaptor { + @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener + private RobocodeListener listener; + + @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener + @Override + public void onBattleFinished(BattleFinishedEvent event) { + if (event.isAborted()) { + listener.battleAborted(battleSpecification); + } + } + + @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener + @Override + public void onBattleCompleted(BattleCompletedEvent event) { + listener.battleComplete(battleSpecification, RobotResults.convertResults(event.getSortedResults())); + } + + @SuppressWarnings("deprecation") // We must still support deprecated RobocodeListener + @Override + public void onBattleMessage(BattleMessageEvent event) { + listener.battleMessage(event.getMessage()); + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobocodeListener.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobocodeListener.java new file mode 100644 index 0000000..8b6e5d3 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobocodeListener.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control; + + +import robocode.control.events.IBattleListener; + + +/** + * @deprecated Since 1.6.2. Use the {@link IBattleListener} instead. + *

+ * A listener interface for receiving callbacks from the {@link RobocodeEngine}. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * + * @see IBattleListener + */ +@Deprecated +public interface RobocodeListener { + + /** + * @deprecated Since 1.6.2. Use the + * {@link IBattleListener#onBattleCompleted(robocode.control.events.BattleCompletedEvent) + * IBattleListener.onBattleCompleted()} instead. + *

+ * This method is called when a battle completes successfully. + * + * @param battle information about the battle that completed + * @param results an array containing the results for the individual robot + */ + @Deprecated + void battleComplete(BattleSpecification battle, RobotResults[] results); + + /** + * @deprecated Since 1.6.2. Use the + * {@link IBattleListener#onBattleFinished(robocode.control.events.BattleFinishedEvent) + * IBattleListener.onBattleFinished()} instead. + *

+ * This method is called when a battle has been aborted. + * + * @param battle information about the battle that was aborted + */ + @Deprecated + void battleAborted(BattleSpecification battle); + + /** + * @deprecated Since 1.6.2. Use the + * {@link IBattleListener#onBattleMessage(robocode.control.events.BattleMessageEvent) + * IBattleListener.onBattleMessage()} instead. + *

+ * This method is called when the game logs messages that is normally + * written out to the console. + * + * @param message the message logged by the game + */ + @Deprecated + void battleMessage(String message); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotResults.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotResults.java new file mode 100644 index 0000000..2d315cf --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotResults.java @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control; + + +import robocode.BattleResults; + + +/** + * Contains the battle results for an individual robot + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobotResults extends BattleResults { + + private static final long serialVersionUID = 2L; + + private final RobotSpecification robot; + + /** + * Constructs a new RobotResults. + * + * @param robot is the robot these results are for + * @param teamLeaderName is the team name + * @param rank is the rank of the robot in the battle + * @param score is the total score for the robot in the battle + * @param survival is the survival score for the robot in the battle + * @param lastSurvivorBonus is the last survivor bonus for the robot in the battle + * @param bulletDamage is the bullet damage score for the robot in the battle + * @param bulletDamageBonus is the bullet damage bonus for the robot in the battle + * @param ramDamage is the ramming damage for the robot in the battle + * @param ramDamageBonus is the ramming damage bonus for the robot in the battle + * @param firsts is the number of rounds this robot placed first + * @param seconds is the number of rounds this robot placed second + * @param thirds is the number of rounds this robot placed third + */ + public RobotResults( + RobotSpecification robot, + String teamLeaderName, + int rank, + double score, + double survival, + double lastSurvivorBonus, + double bulletDamage, + double bulletDamageBonus, + double ramDamage, + double ramDamageBonus, + int firsts, + int seconds, + int thirds + ) { + super(teamLeaderName, rank, score, survival, lastSurvivorBonus, bulletDamage, bulletDamageBonus, ramDamage, + ramDamageBonus, firsts, seconds, thirds); + this.robot = robot; + } + + /** + * Constructs new RobotResults based on a {@link RobotSpecification} and {@link robocode.BattleResults + * BattleResults}. + * + * @param robot the robot these results are for + * @param results the battle results for the robot + */ + public RobotResults( + RobotSpecification robot, + BattleResults results) { + super(results.getTeamLeaderName(), results.getRank(), results.getScore(), results.getSurvival(), + results.getLastSurvivorBonus(), results.getBulletDamage(), results.getBulletDamageBonus(), + results.getRamDamage(), results.getRamDamageBonus(), results.getFirsts(), results.getSeconds(), + results.getThirds()); + this.robot = robot; + } + + /** + * Returns the robot these results are meant for. + * + * @return the robot these results are meant for. + */ + public RobotSpecification getRobot() { + return robot; + } + + /** + * Converts an array of {@link BattleResults} into an array of {@link RobotResults}. + * + * @param results an array of BattleResults to convert. + * @return an array of RobotResults converted from BattleResults. + * @since 1.6.2 + */ + public static RobotResults[] convertResults(BattleResults[] results) { + RobotResults[] resultsConv = new RobotResults[results.length]; + + for (int i = 0; i < results.length; i++) { + resultsConv[i] = (RobotResults) results[i]; + } + return resultsConv; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + + temp = Double.doubleToLongBits(bulletDamage); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(bulletDamageBonus); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + firsts; + temp = Double.doubleToLongBits(lastSurvivorBonus); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(ramDamage); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(ramDamageBonus); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + rank; + temp = Double.doubleToLongBits(score); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + seconds; + temp = Double.doubleToLongBits(survival); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + ((teamLeaderName == null) ? 0 : teamLeaderName.hashCode()); + result = prime * result + thirds; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + RobotResults other = (RobotResults) obj; + + if (Double.doubleToLongBits(bulletDamage) != Double.doubleToLongBits(other.bulletDamage)) { + return false; + } + if (Double.doubleToLongBits(bulletDamageBonus) != Double.doubleToLongBits(other.bulletDamageBonus)) { + return false; + } + if (firsts != other.firsts) { + return false; + } + if (Double.doubleToLongBits(lastSurvivorBonus) != Double.doubleToLongBits(other.lastSurvivorBonus)) { + return false; + } + if (Double.doubleToLongBits(ramDamage) != Double.doubleToLongBits(other.ramDamage)) { + return false; + } + if (Double.doubleToLongBits(ramDamageBonus) != Double.doubleToLongBits(other.ramDamageBonus)) { + return false; + } + if (rank != other.rank) { + return false; + } + if (Double.doubleToLongBits(score) != Double.doubleToLongBits(other.score)) { + return false; + } + if (seconds != other.seconds) { + return false; + } + if (Double.doubleToLongBits(survival) != Double.doubleToLongBits(other.survival)) { + return false; + } + if (teamLeaderName == null) { + if (other.teamLeaderName != null) { + return false; + } + } else if (!teamLeaderName.equals(other.teamLeaderName)) { + return false; + } + if (thirds != other.thirds) { + return false; + } + return true; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotSetup.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotSetup.java new file mode 100644 index 0000000..05c7b81 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotSetup.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control; + + +/** + * Contains the initial position and heading for a robot. + * + * @author Flemming N. Larsen (original) + * + * @since 1.9.2.0 + */ +public class RobotSetup implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + + private final Double x; + private final Double y; + private final Double heading; + + /** + * Constructs a new RobotSetup. + * + * @param x is the x coordinate, where {@code null} means random. + * @param y is the y coordinate, where {@code null} means random. + * @param heading is the heading in degrees of the body, gun, and radar, where {@code null} means random. + */ + public RobotSetup(Double x, Double y, Double heading) { + this.x = x; + this.y = y; + this.heading = heading; + } + + /** + * Returns the x coordinate. + * @return the x coordinate, where {@code null} means unspecified (random). + */ + public Double getX() { + return x; + } + + /** + * Returns the y coordinate. + * @return the y coordinate, where {@code null} means unspecified (random). + */ + public Double getY() { + return y; + } + + /** + * Returns the body, gun, and radar heading (in degrees). + * @return the heading (in degrees), where {@code null} means unspecified (random). + */ + public Double getHeading() { + return heading; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotSpecification.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotSpecification.java new file mode 100644 index 0000000..77aa4a9 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/RobotSpecification.java @@ -0,0 +1,178 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control; + + +import java.io.File; + +import net.sf.robocode.security.IHiddenSpecificationHelper; + + +/** + * Defines the properties of a robot, which is returned from + * {@link RobocodeEngine#getLocalRepository()}. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobotSpecification implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + + private final Object fileSpecification; + private final String name; + private final String author; + private final String webpage; + private final String version; + private final String robocodeVersion; + private final String jarFile; + private final String fullClassName; + private final String description; + private String teamId; + + private RobotSpecification(Object fileSpecification, String name, String author, String webpage, String version, String robocodeVersion, String jarFile, String fullClassName, String description) { + this.fileSpecification = fileSpecification; + this.name = name; + this.author = author; + this.webpage = webpage; + this.version = version; + this.robocodeVersion = robocodeVersion; + this.jarFile = jarFile; + this.fullClassName = fullClassName; + this.description = description; + } + + /** + * Returns the name of this robot or team. + * + * @return the name of this robot or team. + * @see #getVersion() + * @see #getNameAndVersion() + */ + public String getName() { + return name; + } + + /** + * Returns the version of this robot or team. + * + * @return the version of this robot or team. + * @see #getName() + * @see #getNameAndVersion() + */ + public String getVersion() { + return version; + } + + /** + * Returns the name and version of this robot or team. + * + * @return the name and version of this robot or team. + * @see #getName() + * @see #getVersion() + * @since 1.3 + */ + public String getNameAndVersion() { + String nameAndVersion = getName(); + String version = getVersion(); + + if (version != null && version.trim().length() > 0) { + nameAndVersion += ' ' + version.trim(); + } + return nameAndVersion; + } + + /** + * Returns the full class name of this robot or team. + * + * @return the full class name of this robot or team. + */ + public String getClassName() { + return fullClassName; + } + + /** + * Returns the JAR file containing this robot or team, or {@code null} if it + * does not come from a JAR file (could be class files instead). + * + * @return the JAR file containing this robot or team, or {@code null} if it + * does not come from a JAR file (could be class files instead). + */ + public File getJarFile() { + return new File(jarFile); + } + + /** + * Returns the description provided by the author of this robot or team. + * + * @return the description provided by the author of this robot or team. + */ + public String getDescription() { + return description; + } + + /** + * Returns the version of Robocode this robot or team was build with. + * + * @return the version of Robocode this robot or team was build with. + */ + public String getRobocodeVersion() { + return robocodeVersion; + } + + /** + * Returns the link to the web page for this robot or team. + * + * @return the link to the web page for this robot or team. + */ + public String getWebpage() { + return webpage; + } + + /** + * Returns the name of the author of this robot or team. + * + * @return the name of the author of this robot or team. + */ + public String getAuthorName() { + return author; + } + + /** + * Returns id of the team in current battle. + * + * @return id of the team in current battle. + */ + public String getTeamId() { + return teamId != null ? teamId : getNameAndVersion(); + } + + static IHiddenSpecificationHelper createHiddenHelper() { + return new HiddenHelper(); + } + + private static class HiddenHelper implements IHiddenSpecificationHelper { + + public RobotSpecification createSpecification(Object fileSpecification, String name, String author, String webpage, String version, String robocodeVersion, String jarFile, String fullClassName, String description) { + return new RobotSpecification(fileSpecification, name, author, webpage, version, robocodeVersion, jarFile, + fullClassName, description); + } + + public Object getFileSpecification(RobotSpecification specification) { + return specification.fileSpecification; + } + + public void setTeamName(RobotSpecification specification, String teamName) { + specification.teamId = teamName; + } + + public String getTeamName(RobotSpecification specification) { + return specification.teamId; + } + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleAdaptor.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleAdaptor.java new file mode 100644 index 0000000..0588e0d --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleAdaptor.java @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * An abstract adapter class for receiving battle events by implementing the {@link IBattleListener}. + * The methods in this class are empty. This class exists as convenience for creating listener objects. + *

+ * This is handy class to use when implementing the IBattleListener. + * It saves you from implementing empty handlers for battle events you are not interested in handling. + *

+ * Example: + *

+ *   private class BattleObserver extends BattleAdaptor {
+ *       boolean isReplay;
+ *
+ *       public void onBattleStarted(BattleStartedEvent event) {
+ *           isReplay = event.isReplay();
+ *       }
+ *
+ *       public void onBattleCompleted(BattleCompletedEvent event) {
+ *       if (!isReplay) {
+ *           printResultsData(event);
+ *       }
+ *   }
+ * 
+ * + * @see IBattleListener + * + * @author Flemming N. Larsen (original) + * + * @since 1.6.2 + */ +public abstract class BattleAdaptor implements IBattleListener { + + /** + * Creates a BattleAdaptor. + */ + public BattleAdaptor() {} + + /** + * {@inheritDoc} + */ + public void onBattleStarted(final BattleStartedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onBattleFinished(final BattleFinishedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onBattleCompleted(final BattleCompletedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onBattlePaused(final BattlePausedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onBattleResumed(final BattleResumedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onRoundStarted(final RoundStartedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onRoundEnded(final RoundEndedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onTurnStarted(final TurnStartedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onTurnEnded(final TurnEndedEvent event) {} + + /** + * {@inheritDoc} + */ + public void onBattleMessage(final BattleMessageEvent event) {} + + /** + * {@inheritDoc} + */ + public void onBattleError(final BattleErrorEvent event) {} +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleCompletedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleCompletedEvent.java new file mode 100644 index 0000000..e21a614 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleCompletedEvent.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +import robocode.BattleResults; +import robocode.BattleRules; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + +/** + * A BattleCompletedEvent is sent to {@link IBattleListener#onBattleCompleted(BattleCompletedEvent) + * onBattleCompleted()} when the battle is completed successfully and results are available. This event + * will not occur if the battle is terminated or aborted by the user before the battle is completed. + * + * @see IBattleListener + * @see IBattleListener#onBattleCompleted(BattleCompletedEvent) + * @see BattleStartedEvent + * @see BattleFinishedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class BattleCompletedEvent extends BattleEvent { + private final BattleRules battleRules; + private final BattleResults[] results; + + /** + * Called by the game to create a new BattleCompletedEvent. + * Please don't use this constructor as it might change. + * + * @param battleRules the rules that was used in the battle. + * @param results the indexed results of the battle. These are unsorted, but using robot indexes. + */ + public BattleCompletedEvent(BattleRules battleRules, BattleResults[] results) { + super(); + this.battleRules = battleRules; + this.results = results; + } + + /** + * Returns the rules used in the battle. + * + * @return the rules used in the battle. + */ + public BattleRules getBattleRules() { + return battleRules; + } + + /** + * Returns the battle results sorted on score. + * Note that the robot index cannot be used to determine the score with the sorted results. + * + * @return an array of sorted BattleResults, where the results with the bigger score are placed first in the list. + * @see #getIndexedResults() + */ + public BattleResults[] getSortedResults() { + List copy = new ArrayList(Arrays.asList(results)); + + Collections.sort(copy); + Collections.reverse(copy); + return copy.toArray(new BattleResults[copy.size()]); + } + + /** + * Returns the battle results that can be used to determine the score for the individual robot based + * on the robot index. + * + * @return an array of indexed BattleResults, where each index matches an index of a specific robot. + * @see #getSortedResults() + */ + public BattleResults[] getIndexedResults() { + BattleResults[] copy = new BattleResults[results.length]; + + System.arraycopy(results, 0, copy, 0, results.length); + return copy; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleErrorEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleErrorEvent.java new file mode 100644 index 0000000..bce294a --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleErrorEvent.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * A BattleErrorEvent is sent to {@link IBattleListener#onBattleError(BattleErrorEvent) + * onBattleError()} when an error message is sent from the game in the during the battle. + * + * @see IBattleListener + * @see BattleMessageEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class BattleErrorEvent extends BattleEvent { + private final String error; + + /** + * Called by the game to create a new BattleErrorEvent. + * Please don't use this constructor as it might change. + * + * @param error the error message from the game. + */ + public BattleErrorEvent(String error) { + super(); + this.error = error; + } + + /** + * Returns the error message. + * + * @return the error message that was sent from the game during the battle. + */ + public String getError() { + return error; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleEvent.java new file mode 100644 index 0000000..68fc7eb --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleEvent.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * This is the base class of all battle events. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public abstract class BattleEvent { + + /** + * Creates a new BattleEvent. + */ + public BattleEvent() { + super(); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleFinishedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleFinishedEvent.java new file mode 100644 index 0000000..d9e3985 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleFinishedEvent.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * A BattleFinishedEvent is sent to {@link IBattleListener#onBattleFinished(BattleFinishedEvent) + * onBattleFinished()} when the battle is finished. This event is always sent as the last battle event, + * both when the battle is completed successfully, terminated due to an error, or aborted by the user. + * Hence, this events is well-suited for cleanup after the battle. + * + * @see IBattleListener + * @see BattleStartedEvent + * @see BattleCompletedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class BattleFinishedEvent extends BattleEvent { + private final boolean isAborted; + + /** + * Called by the game to create a new BattleFinishedEvent. + * Please don't use this constructor as it might change. + * + * @param isAborted a flag specifying if the battle was aborted: + * {@code true} if the battle was aborted; {@code false} otherwise. + */ + public BattleFinishedEvent(boolean isAborted) { + super(); + this.isAborted = isAborted; + } + + /** + * Checks if the battle was aborted. + * + * @return {@code true} if the battle was aborted; {@code false} otherwise. + */ + public boolean isAborted() { + return isAborted; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleMessageEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleMessageEvent.java new file mode 100644 index 0000000..58d7e34 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleMessageEvent.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * A BattleMessageEvent is sent to {@link IBattleListener#onBattleMessage(BattleMessageEvent) + * onBattleMessage()} when an informal message is sent from the game in the during the battle. + * + * @see IBattleListener + * @see BattleErrorEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class BattleMessageEvent extends BattleEvent { + private final String message; + + /** + * Called by the game to create a new BattleMessageEvent. + * Please don't use this constructor as it might change. + * + * @param message the informal message from the game. + */ + public BattleMessageEvent(String message) { + super(); + this.message = message; + } + + /** + * Returns the informal message. + * + * @return the informal message that was sent from the game during the battle. + */ + public String getMessage() { + return message; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattlePausedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattlePausedEvent.java new file mode 100644 index 0000000..deefdaf --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattlePausedEvent.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * A BattlePausedEvent is sent to {@link IBattleListener#onBattlePaused(BattlePausedEvent) + * onBattlePaused()} when a battle has been paused. + * + * @see IBattleListener + * @see BattleResumedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class BattlePausedEvent extends BattleEvent { + + /** + * Called by the game to create a new BattlePausedEvent. + * Please don't use this constructor as it might change. + */ + public BattlePausedEvent() { + super(); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleResumedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleResumedEvent.java new file mode 100644 index 0000000..2ca10a7 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleResumedEvent.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * A BattleResumedEvent is sent to {@link IBattleListener#onBattleResumed(BattleResumedEvent) + * onBattleResumed()} when a battle has been resumed (after having been paused). + * + * @see IBattleListener + * @see BattlePausedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class BattleResumedEvent extends BattleEvent { + + /** + * Called by the game to create a new BattleResumedEvent. + * Please don't use this constructor as it might change. + */ + public BattleResumedEvent() { + super(); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleStartedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleStartedEvent.java new file mode 100644 index 0000000..a7ca33b --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/BattleStartedEvent.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +import robocode.BattleRules; + + +/** + * A BattleStartedEvent is sent to {@link IBattleListener#onBattleStarted(BattleStartedEvent) + * onBattleStarted()} when a new battle is started. + * + * @see IBattleListener + * @see BattleCompletedEvent + * @see BattleFinishedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class BattleStartedEvent extends BattleEvent { + private final BattleRules battleRules; + private final boolean isReplay; + private final int robotsCount; + + /** + * Called by the game to create a new BattleStartedEvent. + * Please don't use this constructor as it might change. + * + * @param battleRules the rules that will be used in the battle. + * @param robotsCount the number of robots participating in the battle. + * @param isReplay a flag specifying if this battle is a replay or real battle: + * {@code true} if the battle is a replay; {@code false} otherwise. + */ + public BattleStartedEvent(BattleRules battleRules, int robotsCount, boolean isReplay) { + super(); + this.battleRules = battleRules; + this.isReplay = isReplay; + this.robotsCount = robotsCount; + } + + /** + * Returns the rules that will be used in the battle. + * + * @return the rules that will be used in the battle. + */ + public BattleRules getBattleRules() { + return battleRules; + } + + /** + * Returns the number of robots participating in the battle. + * + * @return the number of robots participating in the battle. + */ + public int getRobotsCount() { + return robotsCount; + } + + /** + * Checks if this battle is a replay or a new battle. + * + * @return {@code true} if the battle is a replay; {@code false} otherwise. + */ + public boolean isReplay() { + return isReplay; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/IBattleListener.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/IBattleListener.java new file mode 100644 index 0000000..dd19597 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/IBattleListener.java @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * The listener interface for receiving "interesting" battle events from the game, e.g. when a battle, + * round or turn is started or ended. + *

+ * When implementing this battle listener you should implement the {@link BattleAdaptor} in order to + * only implement the event handler methods you are interested in. + * + * @see BattleAdaptor + * + * @author Flemming N. Larsen (original) + * + * @since 1.6.2 + */ +public interface IBattleListener { + + /** + * This method is called when a new battle has started. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see BattleStartedEvent + * @see #onBattleCompleted(BattleCompletedEvent) + * @see #onBattleFinished(BattleFinishedEvent) + * + * @param event the event details. + */ + void onBattleStarted(final BattleStartedEvent event); + + /** + * This method is called when the battle has finished. This event is always sent as the last battle event, + * both when the battle is completed successfully, terminated due to an error, or aborted by the user. + * Hence, this events is well-suited for cleanup after the battle. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see BattleFinishedEvent + * @see #onBattleStarted(BattleStartedEvent) + * @see #onBattleCompleted(BattleCompletedEvent) + * + * @param event the event details. + */ + void onBattleFinished(final BattleFinishedEvent event); + + /** + * This method is called when the battle has completed successfully and results are available. + * This event will not occur if the battle is terminated or aborted by the user before the battle is completed. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see BattleCompletedEvent + * @see #onBattleStarted(BattleStartedEvent) + * @see #onBattleFinished(BattleFinishedEvent) + * + * @param event the event details. + */ + void onBattleCompleted(final BattleCompletedEvent event); + + /** + * This method is called when the battle has been paused, either by the user or the game. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see BattlePausedEvent + * @see #onBattleResumed(BattleResumedEvent) + * + * @param event the event details. + */ + void onBattlePaused(final BattlePausedEvent event); + + /** + * This method is called when the battle has been resumed (after having been paused). + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see BattleResumedEvent + * @see #onBattlePaused(BattlePausedEvent) + * + * @param event the event details. + */ + void onBattleResumed(final BattleResumedEvent event); + + /** + * This method is called when a new round in a battle has started. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see RoundEndedEvent + * @see #onRoundEnded(RoundEndedEvent) + * + * @param event the event details. + */ + void onRoundStarted(final RoundStartedEvent event); + + /** + * This method is called when the current round of a battle has ended. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see RoundEndedEvent + * @see #onRoundStarted(RoundStartedEvent) + * + * @param event the event details. + */ + void onRoundEnded(final RoundEndedEvent event); + + /** + * This method is called when a new turn in a battle round has started. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see TurnStartedEvent + * @see #onTurnEnded(TurnEndedEvent) + * + * @param event the event details. + */ + void onTurnStarted(final TurnStartedEvent event); + + /** + * This method is called when the current turn in a battle round is ended. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see TurnEndedEvent + * @see #onTurnStarted(TurnStartedEvent) + * + * @param event the event details. + */ + void onTurnEnded(final TurnEndedEvent event); + + /** + * This method is called when the game has sent a new information message. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see BattleMessageEvent + * @see #onBattleError(BattleErrorEvent) + * + * @param event the event details. + */ + void onBattleMessage(final BattleMessageEvent event); + + /** + * This method is called when the game has sent an error message. + *

+ * You must override this method in order to get informed about this event and receive the event details. + * + * @see BattleErrorEvent + * @see #onBattleMessage(BattleMessageEvent) + * + * @param event the event details. + */ + void onBattleError(final BattleErrorEvent event); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/RoundEndedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/RoundEndedEvent.java new file mode 100644 index 0000000..90a43fd --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/RoundEndedEvent.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * A RoundEndedEvent is sent to {@link IBattleListener#onRoundEnded(RoundEndedEvent) + * onRoundEnded()} when the current round of a battle has ended. + * + * @see IBattleListener + * @see RoundStartedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class RoundEndedEvent extends BattleEvent { + private final int round; + private final int turns; + private final int totalTurns; + + /** + * Called by the game to create a new RoundEndedEvent. + * Please don't use this constructor as it might change. + * + * @param round the round number that was ended (zero indexed). + * @param turns the number of turns that this round reached. + * @param totalTurns the total number of turns reached in the battle when this round ended. + */ + public RoundEndedEvent(int round, int turns, int totalTurns) { + super(); + this.round = round; + this.turns = turns; + this.totalTurns = totalTurns; + } + + /** + * Returns the round number that has ended. + * + * @return the round number that has ended, which is zero indexed. + */ + public int getRound() { + return round; + } + + /** + * Returns the number of turns that this round reached. + * + * @return the number of turns that this round reached. + * + * @see #getTotalTurns() + */ + public int getTurns() { + return turns; + } + + /** + * Returns the total number of turns reached in the battle when this round ended. + * + * @return the total number of turns reached in the battle when this round ended. + * + * @see #getTurns() + * + * @since 1.7.2 + */ + public int getTotalTurns() { + return totalTurns; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/RoundStartedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/RoundStartedEvent.java new file mode 100644 index 0000000..41ad245 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/RoundStartedEvent.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +import robocode.control.snapshot.ITurnSnapshot; + + +/** + * A RoundStartedEvent is sent to {@link IBattleListener#onRoundStarted(RoundStartedEvent) + * onRoundStarted()} when a new round in a battle is started. + * + * @see IBattleListener + * @see RoundEndedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class RoundStartedEvent extends BattleEvent { + private final ITurnSnapshot startSnapshot; + private final int round; + + /** + * Called by the game to create a new RoundStartedEvent. + * Please don't use this constructor as it might change. + * + * @param startSnapshot the start snapshot of the participating robots, initial starting positions etc. + * @param round the round number (zero indexed). + */ + public RoundStartedEvent(ITurnSnapshot startSnapshot, int round) { + super(); + this.startSnapshot = startSnapshot; + this.round = round; + } + + /** + * Returns the start snapshot of the participating robots, initial starting positions etc. + * + * @return a {@link robocode.control.snapshot.ITurnSnapshot} that serves as the start snapshot of + * the round. + */ + public ITurnSnapshot getStartSnapshot() { + return startSnapshot; + } + + /** + * Returns the round number. + * + * @return the round number, which is zero indexed. + */ + public int getRound() { + return round; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/TurnEndedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/TurnEndedEvent.java new file mode 100644 index 0000000..eb4c906 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/TurnEndedEvent.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +import robocode.control.snapshot.ITurnSnapshot; + + +/** + * A TurnEndedEvent is sent to {@link IBattleListener#onTurnEnded(TurnEndedEvent) + * onTurnEnded()} when the current turn in a battle round is ended. + * + * @see IBattleListener + * @see TurnStartedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class TurnEndedEvent extends BattleEvent { + private final ITurnSnapshot turnSnapshot; + + /** + * Called by the game to create a new TurnEndedEvent. + * Please don't use this constructor as it might change. + * + * @param turnSnapshot a snapshot of the turn that has ended. + */ + public TurnEndedEvent(ITurnSnapshot turnSnapshot) { + super(); + this.turnSnapshot = turnSnapshot; + } + + /** + * Returns a snapshot of the turn that has ended. + * + * @return a snapshot of the turn that has ended. + */ + public ITurnSnapshot getTurnSnapshot() { + return turnSnapshot; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/TurnStartedEvent.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/TurnStartedEvent.java new file mode 100644 index 0000000..534b252 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/TurnStartedEvent.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.events; + + +/** + * A TurnStartedEvent is sent to {@link IBattleListener#onTurnStarted(TurnStartedEvent) + * onTurnStarted()} when a new turn in a battle round is started. + * + * @see IBattleListener + * @see TurnEndedEvent + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public class TurnStartedEvent extends BattleEvent { + + /** + * Called by the game to create a new TurnStartedEvent. + * Please don't use this constructor as it might change. + */ + public TurnStartedEvent() { + super(); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/package-info.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/package-info.java new file mode 100644 index 0000000..ecd91d9 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/events/package-info.java @@ -0,0 +1,13 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + +/** + * Battle events that occurs during a game, and which are used for the + * robocode.control.IBattleListener class. + */ +package robocode.control.events; diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/package-info.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/package-info.java new file mode 100644 index 0000000..09b1006 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/package-info.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + +/** + * The Robocode Control API is used for controlling the Robocode + * application from another external application. Basically, it is possible + * to run battles between selected robots and retrieve the results. However, + * it is also possible to get detailed information as snapshots during the + * battles regarding e.g. the positions and headings of the individual robots + * and bullets at a specific time during a battle. + *

+ * The main entry class is the Robocode.Control.RobocodeEngine class, which + * must be instantiated by the application controlling Robocode. With the + * RobocodeEngine, a battle specification must be provided in order to run a + * battle. The battle specification specify the size of the battlefield, and + * which rules that must be used. In addition, the participant robots must be + * selected, which must exist in the robot directory of Robocode in + * advantage. + * + *

Example

+ *

+ * Here is a simple application that runs a battle in Robocode for 5 rounds + * on the default battlefield of 800x600 pixels. The robots selected for the + * battle are sample.RamFire and sample.Corners. + * + *

+ * import robocode.control.*;
+ * import robocode.control.events.*;
+ * 
+ * //
+ * // Application that demonstrates how to run two sample robots in Robocode using the
+ * // RobocodeEngine from the robocode.control package.
+ * //
+ * // @author Flemming N. Larsen
+ * //
+ * public class BattleRunner {
+ * 
+ *     public static void main(String[] args) {
+ * 
+ *         // Disable log messages from Robocode
+ *         RobocodeEngine.setLogMessagesEnabled(false);
+ *
+ *         // Create the RobocodeEngine
+ *         //   RobocodeEngine engine = new RobocodeEngine(); // Run from current working directory
+ *         RobocodeEngine engine = new RobocodeEngine(new java.io.File("C:/Robocode")); // Run from C:/Robocode
+ * 
+ *         // Add our own battle listener to the RobocodeEngine 
+ *         engine.addBattleListener(new BattleObserver());
+ * 
+ *         // Show the Robocode battle view
+ *         engine.setVisible(true);
+ * 
+ *         // Setup the battle specification
+ * 
+ *         int numberOfRounds = 5;
+ *         BattlefieldSpecification battlefield = new BattlefieldSpecification(800, 600); // 800x600
+ *         RobotSpecification[] selectedRobots = engine.getLocalRepository("sample.RamFire,sample.Corners");
+ * 
+ *         BattleSpecification battleSpec = new BattleSpecification(numberOfRounds, battlefield, selectedRobots);
+ * 
+ *         // Run our specified battle and let it run till it is over
+ *         engine.runBattle(battleSpec, true); // waits till the battle finishes
+ * 
+ *         // Cleanup our RobocodeEngine
+ *         engine.close();
+ * 
+ *         // Make sure that the Java VM is shut down properly
+ *         System.exit(0);
+ *     }
+ * }
+ * 
+ * //
+ * // Our private battle listener for handling the battle event we are interested in.
+ * //
+ * class BattleObserver extends BattleAdaptor {
+ * 
+ *     // Called when the battle is completed successfully with battle results
+ *     public void onBattleCompleted(BattleCompletedEvent e) {
+ *         System.out.println("-- Battle has completed --");
+ *         
+ *         // Print out the sorted results with the robot names
+ *         System.out.println("Battle results:");
+ *         for (robocode.BattleResults result : e.getSortedResults()) {
+ *             System.out.println("  " + result.getTeamLeaderName() + ": " + result.getScore());
+ *         }
+ *     }
+ * 
+ *     // Called when the game sends out an information message during the battle
+ *     public void onBattleMessage(BattleMessageEvent e) {
+ *         System.out.println("Msg> " + e.getMessage());
+ *     }
+ * 
+ *     // Called when the game sends out an error message during the battle
+ *     public void onBattleError(BattleErrorEvent e) {
+ *         System.out.println("Err> " + e.getError());
+ *     }
+ * }
+ * 
+ */ +package robocode.control; diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/BulletState.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/BulletState.java new file mode 100644 index 0000000..3443573 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/BulletState.java @@ -0,0 +1,101 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.snapshot; + + +/** + * Defines a bullet state, which can be: just fired, moving somewhere, hitting a victim, + * hitting another bullet, hitting the wall, exploded, or inactive. + * + * @author Flemming N. Larsen (original) + * + * @since 1.6.2 + */ +public enum BulletState { + + /** The bullet has just been fired this turn and hence just been created. This state only last one turn. */ + FIRED(0), + + /** The bullet is now moving across the battlefield, but has not hit anything yet. */ + MOVING(1), + + /** The bullet has hit a robot victim. */ + HIT_VICTIM(2), + + /** The bullet has hit another bullet. */ + HIT_BULLET(3), + + /** The bullet has hit the wall, i.e. one of the four borders of the battlefield. */ + HIT_WALL(4), + + /** The bullet currently represents a robot explosion, i.e. a robot death. */ + EXPLODED(5), + + /** The bullet is currently inactive. Hence, it is not active or visible on the battlefield. */ + INACTIVE(6); + + private final int value; + + private BulletState(int value) { + this.value = value; + } + + /** + * Returns the state as an integer value. + * + * @return an integer value representing this state. + * + * @see #toState(int) + */ + public int getValue() { + return value; + } + + /** + * Returns a BulletState based on an integer value that represents a BulletState. + * + * @param value the integer value that represents a specific BulletState. + * @return a BulletState that corresponds to the specific integer value. + * + * @see #getValue() + * + * @throws IllegalArgumentException if the specified value does not correspond + * to a BulletState and hence is invalid. + */ + public static BulletState toState(int value) { + switch (value) { + case 0: + return FIRED; + + case 1: + return MOVING; + + case 2: + return HIT_VICTIM; + + case 3: + return HIT_BULLET; + + case 4: + return HIT_WALL; + + case 5: + return EXPLODED; + + case 6: + return INACTIVE; + + default: + throw new IllegalArgumentException("unknown value"); + } + } + + public boolean isActive() { + return this == FIRED || this == MOVING; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IBulletSnapshot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IBulletSnapshot.java new file mode 100644 index 0000000..874ddd6 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IBulletSnapshot.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.snapshot; + + +/** + * Interface of a bullet snapshot at a specific time in a battle. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public interface IBulletSnapshot { + + /** + * Returns the bullet state. + * + * @return the bullet state. + */ + BulletState getState(); + + /** + * Returns the bullet power. + * + * @return the bullet power. + */ + double getPower(); + + /** + * Returns the X position of the bullet. + * + * @return the X position of the bullet. + */ + double getX(); + + /** + * Returns the Y position of the bullet. + * + * @return the Y position of the bullet. + */ + double getY(); + + /** + * Returns the X painting position of the bullet. + * Note that this is not necessarily equal to the X position of the bullet, even though + * it will be in most cases. The painting position of the bullet is needed as the bullet + * will "stick" to its victim when it has been hit, but only visually. + * + * @return the X painting position of the bullet. + */ + double getPaintX(); + + /** + * Returns the Y painting position of the bullet. + * Note that this is not necessarily equal to the Y position of the bullet, even though + * it will be in most cases. The painting position of the bullet is needed as the bullet + * will "stick" to its victim when it has been hit, but only visually. + * + * @return the Y painting position of the bullet. + */ + double getPaintY(); + + /** + * Returns the color of the bullet. + * + * @return an ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + * + * @see java.awt.Color#getRGB() + */ + int getColor(); + + /** + * Returns the current frame number to display, i.e. when the bullet explodes. + * + * @return the current frame number. + * + * @see #isExplosion() + * @see #getExplosionImageIndex() + */ + int getFrame(); + + /** + * Checks if the bullet has become an explosion, i.e. when it a robot or bullet has been hit. + * + * @return {@code true} if the bullet is an explosion; {@code false} otherwise. + * + * @see #getFrame() + * @see #getExplosionImageIndex() + */ + boolean isExplosion(); + + /** + * Returns the explosion image index, which is different depending on the type of explosion. + * E.g. if it is a small explosion on a robot that has been hit by this bullet, + * or a big explosion when a robot dies. + * + * @return the explosion image index. + * + * @see #isExplosion() + * @see #getExplosionImageIndex() + */ + int getExplosionImageIndex(); + + /** + * Returns the ID of the bullet used for identifying the bullet in a collection of bullets. + * + * @return the ID of the bullet. + */ + int getBulletId(); + + /** + * @return heading of the bullet + */ + double getHeading(); + + /** + * @return contestantIndex of the victim, or -1 if still in air + */ + int getVictimIndex(); + + /** + * @return contestantIndex of the owner + */ + int getOwnerIndex(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IDebugProperty.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IDebugProperty.java new file mode 100644 index 0000000..ed0a6fa --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IDebugProperty.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.snapshot; + + +/** + * Interface of a debug property, which is a key-value pair. + * + * @author Pavel Savara (original) + * + * @since 1.6.2 + */ +public interface IDebugProperty { + + /** + * Returns the key of the property. + * + * @return the key of the property. + */ + String getKey(); + + /** + * Returns the value of the property. + * + * @return the value of the property. + */ + String getValue(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IRobotSnapshot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IRobotSnapshot.java new file mode 100644 index 0000000..a10ff4a --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IRobotSnapshot.java @@ -0,0 +1,242 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.snapshot; + + +/** + * Interface of a robot snapshot at a specific time in a battle. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public interface IRobotSnapshot { + + /** + * Returns the name of the robot. + * + * @return the name of the robot. + */ + String getName(); + + /** + * Returns the short name of the robot. + * + * @return the short name of the robot. + */ + String getShortName(); + + /** + * Returns the very short name of the robot. + * + * @return the very short name of the robot. + */ + String getVeryShortName(); + + /** + * Returns the name of the team, which can be the name of a robot if the contestant is not a team, but a robot. + * + * @return the name of the team. + */ + String getTeamName(); + + /** + * Returns the index of the robot, which is unique for the specific robot and constant during a battle. + * + * @return the robot index. + * + * @since 1.7.4 + * + * @see #getTeamIndex() + */ + int getRobotIndex(); + + /** + * Returns the index of the team that this robot is a member of, which is unique for the specific team and constant + * during a battle. + * + * @return the team index or -1 if the robot is not a member of a team. + * + * @since 1.7.4 + * + * @see #getRobotIndex() + */ + int getTeamIndex(); + + /** + * Returns the contestant index, which is unique for each robot or team participating in a battle. + * Note: If a team of robots is participating in a battle, this method will return the team index (see + * {@link #getTeamIndex()}); otherwise the robot index (see {@link #getRobotIndex()}) is used instead. + * This method is used for the battle results as scores are calculated for either a team of robots or individual + * robot. + * + * @return the contestant index of the robot or team. + * + * @see #getRobotIndex() + * @see #getTeamIndex() + */ + int getContestantIndex(); + + /** + * Returns the robot state. + * + * @return the robot state. + */ + RobotState getState(); + + /** + * Returns the energy level of the robot. + * + * @return the energy level of the robot. + */ + double getEnergy(); + + /** + * Returns the velocity of the robot. + * + * @return the velocity of the robot. + */ + double getVelocity(); + + /** + * Returns the body heading of the robot in radians. + * + * @return the body heading of the robot in radians. + */ + double getBodyHeading(); + + /** + * Returns the gun heading of the robot in radians. + * + * @return the gun heading of the robot in radians. + */ + double getGunHeading(); + + /** + * Returns the radar heading of the robot in radians. + * + * @return the radar heading of the robot in radians. + */ + double getRadarHeading(); + + /** + * Returns the gun heat of the robot. + * + * @return the gun heat of the robot. + */ + double getGunHeat(); + + /** + * Returns the X position of the robot. + * + * @return the X position of the robot. + */ + double getX(); + + /** + * Returns the Y position of the robot. + * + * @return the Y position of the robot. + */ + double getY(); + + /** + * Returns the color of the body. + * + * @return an ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + * + * @see java.awt.Color#getRGB() + */ + int getBodyColor(); + + /** + * Returns the color of the gun. + * + * @return an ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + * + * @see java.awt.Color#getRGB() + */ + int getGunColor(); + + /** + * Returns the color of the radar. + * + * @return an ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + * + * @see java.awt.Color#getRGB() + */ + int getRadarColor(); + + /** + * Returns the color of the scan arc. + * + * @return an ARGB color value. (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are blue) + * + * @see java.awt.Color#getRGB() + */ + int getScanColor(); + + /** + * Checks if this robot is a {@link robocode.Droid Droid}. + * + * @return {@code true} if this robot is a Droid; {@code false} otherwise. + */ + boolean isDroid(); + + /** + * Checks if this robot is a {@link robocode.BorderSentry BorderSentry}. + * + * @return {@code true} if this robot is a BorderSentry; {@code false} otherwise. + * + * @since 1.9.0.0 + */ + boolean isSentryRobot(); + + /** + * Checks if this robot is a {@link robocode.robotinterfaces.IPaintRobot IPaintRobot} or is invoking getGraphics() + * + * @return {@code true} if this robot is a painting; {@code false} otherwise. + */ + boolean isPaintRobot(); + + /** + * Checks if painting is enabled for this robot. + * + * @return {@code true} if painting is enabled for this robot; {@code false} otherwise. + */ + boolean isPaintEnabled(); + + /** + * Checks if RobocodeSG painting (the point (0,0) is in the upper left corner) is enabled for this robot. + * + * @return {@code true} if RobocodeSG painting is enabled for this robot; {@code false} otherwise. + */ + boolean isSGPaintEnabled(); + + /** + * Returns a snapshot of debug properties. + * + * @return a snapshot of debug properties. + */ + IDebugProperty[] getDebugProperties(); + + /** + * Returns a snapshot of the output print stream for this robot. + * + * @return a string containing the snapshot of the output print stream. + */ + String getOutputStreamSnapshot(); + + /** + * Returns a snapshot of the current score for this robot. + * + * @return a snapshot of the current score for this robot. + */ + IScoreSnapshot getScoreSnapshot(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IScoreSnapshot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IScoreSnapshot.java new file mode 100644 index 0000000..00ca3a4 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/IScoreSnapshot.java @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.snapshot; + + +/** + * Interface of a score snapshot at a specific time in a battle. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public interface IScoreSnapshot extends Comparable { + + /** + * Returns the name of the contestant, i.e. a robot or team. + * + * @return the name of the contestant, i.e. a robot or team. + */ + String getName(); + + /** + * Returns the total score. + * + * @return the total score. + */ + double getTotalScore(); + + /** + * Returns the total survival score. + * + * @return the total survival score. + */ + double getTotalSurvivalScore(); + + /** + * Returns the total last survivor score. + * + * @return the total last survivor score. + */ + double getTotalLastSurvivorBonus(); + + /** + * Returns the total bullet damage score. + * + * @return the total bullet damage score. + */ + double getTotalBulletDamageScore(); + + /** + * Returns the total bullet kill bonus. + * + * @return the total bullet kill bonus. + */ + double getTotalBulletKillBonus(); + + /** + * Returns the total ramming damage score. + * + * @return the total ramming damage score. + */ + double getTotalRammingDamageScore(); + + /** + * Returns the total ramming kill bonus. + * + * @return the total ramming kill bonus. + */ + double getTotalRammingKillBonus(); + + /** + * Returns the total number of first places. + * + * @return the total number of first places. + */ + int getTotalFirsts(); + + /** + * Returns the total number of second places. + * + * @return the total number of second places. + */ + int getTotalSeconds(); + + /** + * Returns the total number of third places. + * + * @return the total number of third places. + */ + int getTotalThirds(); + + /** + * Returns the current score. + * + * @return the current score. + */ + double getCurrentScore(); + + /** + * Returns the current survival score. + * + * @return the current survival score. + */ + double getCurrentSurvivalScore(); + + /** + * Returns the current survival bonus. + * + * @return the current survival bonus. + */ + double getCurrentSurvivalBonus(); + + /** + * Returns the current bullet damage score. + * + * @return the current bullet damage score. + */ + double getCurrentBulletDamageScore(); + + /** + * Returns the current bullet kill bonus. + * + * @return the current bullet kill bonus. + */ + double getCurrentBulletKillBonus(); + + /** + * Returns the current ramming damage score. + * + * @return the current ramming damage score. + */ + double getCurrentRammingDamageScore(); + + /** + * Returns the current ramming kill bonus. + * + * @return the current ramming kill bonus. + */ + double getCurrentRammingKillBonus(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/ITurnSnapshot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/ITurnSnapshot.java new file mode 100644 index 0000000..abe369c --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/ITurnSnapshot.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.snapshot; + + +/** + * Interface of a battle turn snapshot at a specific time in a battle. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.2 + */ +public interface ITurnSnapshot { + + /** + * Returns a list of snapshots for the robots participating in the battle. + * + * @return a list of snapshots for the robots participating in the battle. + */ + IRobotSnapshot[] getRobots(); + + /** + * Returns a list of snapshots for the bullets that are currently on the battlefield. + * + * @return a list of snapshots for the bullets that are currently on the battlefield. + */ + IBulletSnapshot[] getBullets(); + + /** + * Returns the current TPS (turns per second) rate. + * + * @return the current TPS (turns per second) rate. + */ + int getTPS(); + + /** + * Returns the current round of the battle. + * + * @return the current round of the battle. + */ + int getRound(); + + /** + * Returns the current turn in the battle round. + * + * @return the current turn in the battle round. + */ + int getTurn(); + + /** + * Returns an array of sorted scores grouped by teams, ordered by position. + * Note that the team index cannot be used to determine the score with the sorted scores. + * + * @return an array of sorted IScoreSnapshots, where the bigger scores are placed first in the list. + * + * @see #getIndexedTeamScores() + */ + IScoreSnapshot[] getSortedTeamScores(); + + /** + * Returns an array of indexed scores grouped by teams that can be used to determine the score + * for the individual team based on the team index. + * + * @return an array of indexed IScoreSnapshots, where each index matches an index of a specific team. + * + * @see #getSortedTeamScores() + */ + IScoreSnapshot[] getIndexedTeamScores(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/RobotState.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/RobotState.java new file mode 100644 index 0000000..887cf69 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/RobotState.java @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.control.snapshot; + + +/** + * Defines a robot state, which can be: active on the battlefield, hitting a wall or robot this turn, or dead. + * + * @author Flemming N. Larsen (original) + * + * @since 1.6.2 + */ +public enum RobotState { + + /** The robot is active on the battlefield and has not hit the wall or a robot at this turn. */ + ACTIVE(0), + + /** The robot has hit a wall, i.e. one of the four borders, at this turn. This state only last one turn. */ + HIT_WALL(1), + + /** The robot has hit another robot at this turn. This state only last one turn. */ + HIT_ROBOT(2), + + /** The robot is dead. */ + DEAD(3); + + private final int value; + + private RobotState(int value) { + this.value = value; + } + + /** + * Returns the state as an integer value. + * + * @return an integer value representing this state. + * + * @see #toState(int) + */ + public int getValue() { + return value; + } + + /** + * Returns a RobotState based on an integer value that represents a RobotState. + * + * @param value the integer value that represents a specific RobotState. + * @return a RobotState that corresponds to the specific integer value. + * + * @see #getValue() + * + * @throws IllegalArgumentException if the specified value does not correspond + * to a RobotState and hence is invalid. + */ + public static RobotState toState(int value) { + switch (value) { + case 0: + return ACTIVE; + + case 1: + return HIT_WALL; + + case 2: + return HIT_ROBOT; + + case 3: + return DEAD; + + default: + throw new IllegalArgumentException("unknown value"); + } + } + + /** + * Checks if the robot is alive. + * + * @return {@code true} if the robot is alive; {@code false} otherwise. + * + * @see #isDead() + */ + public boolean isAlive() { + return this != DEAD; + } + + /** + * Checks if the robot is dead. + * + * @return {@code true} if the robot is dead; {@code false} otherwise. + * + * @see #isAlive() + */ + public boolean isDead() { + return this == DEAD; + } + + /** + * Checks if the robot has hit another robot. + * + * @return {@code true} if the robot has hit a robot; {@code false} otherwise. + * + * @see #isHitWall() + */ + public boolean isHitRobot() { + return this == HIT_ROBOT; + } + + /** + * Checks if the robot has hit the wall, i.e. one of the four borders. + * + * @return {@code true} if the robot has hit the wall; {@code false} otherwise. + * + * @see #isHitRobot() + */ + public boolean isHitWall() { + return this == HIT_WALL; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/package-info.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/package-info.java new file mode 100644 index 0000000..ea5ebb5 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/control/snapshot/package-info.java @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + +/** + * Snapshots of the battle turns, robots, bullets, scores etc. + */ +package robocode.control.snapshot; diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/AbortedException.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/AbortedException.java new file mode 100644 index 0000000..3531ca8 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/AbortedException.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.exception; + + +/** + * @author Pavel Savara (original) + * + * @since 1.6.1 + */ +public class AbortedException extends Error { // Must be an Error! + // From viewpoint of the Robot, an Error is a JVM error: + // Robot died, their CPU exploded, the JVM for the robot's brain has an error. + private static final long serialVersionUID = 1L; + + public AbortedException() { + super(); + } + + public AbortedException(String message) { + super(message); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/DeathException.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/DeathException.java new file mode 100644 index 0000000..5f18f0e --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/DeathException.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.exception; + + +/** + * @author Mathew A. Nelson (original) + */ +public class DeathException extends Error { // Must be an Error! + // From viewpoint of the Robot, an Error is a JVM error: + // Robot died, their CPU exploded, the JVM for the robot's brain has an error. + private static final long serialVersionUID = 1L; + + public DeathException() { + super(); + } + + public DeathException(String message) { + super(message); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/DisabledException.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/DisabledException.java new file mode 100644 index 0000000..24435f1 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/DisabledException.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.exception; + + +/** + * @author Mathew A. Nelson (original) + */ +public class DisabledException extends Error { // Must be an Error! + private static final long serialVersionUID = 1L; + + public DisabledException() { + super(); + } + + public DisabledException(String s) { + super(s); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/EventInterruptedException.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/EventInterruptedException.java new file mode 100644 index 0000000..0d7ccd0 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/EventInterruptedException.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.exception; + + +/** + * @author Mathew A. Nelson (original) + */ +public class EventInterruptedException extends Error { // Must be an Error! + private static final long serialVersionUID = 1L; + + private int priority = Integer.MIN_VALUE; + + public EventInterruptedException(int priority) { + this.priority = priority; + } + + public int getPriority() { + return priority; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/RobotException.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/RobotException.java new file mode 100644 index 0000000..93e331f --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/RobotException.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.exception; + + +/** + * @author Mathew A. Nelson (original) + */ +public class RobotException extends Error { // Must be an Error! + private static final long serialVersionUID = 1L; + + public RobotException() { + super(); + } + + public RobotException(String s) { + super(s); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/WinException.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/WinException.java new file mode 100644 index 0000000..478f165 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/WinException.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.exception; + + +/** + * @author Mathew A. Nelson (original) + */ +public class WinException extends Error { // Must be an Error! + private static final long serialVersionUID = 1L; + + public WinException() { + super(); + } + + public WinException(String s) { + super(s); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/package-info.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/package-info.java new file mode 100644 index 0000000..cc56bbd --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/exception/package-info.java @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + +/** + * Contains exceptions that occur inside a robot thrown by the game. + */ +package robocode.exception; diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/package-info.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/package-info.java new file mode 100644 index 0000000..deb1c88 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/package-info.java @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + +/** + * Robot API used for writing robots for Robocode. + */ +package robocode; diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/EllipseGL.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/EllipseGL.java new file mode 100644 index 0000000..550f5fd --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/EllipseGL.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robocodeGL; + + +import java.awt.Color; + +import gl4java.GLFunc; + + +/** + * Dummy class that stub out RobocodeGL 0.1.4 functionality. + * + * Original author is David Alves for RobocodeGL. + */ +public class EllipseGL extends RenderElement { + + public EllipseGL() {} + + public EllipseGL(double x, double y, double width, double height) {} + + public EllipseGL(double x, double y, double width, double height, Color color, double lineWidth) {} + + public void setFrame(double x, double y, double width, double height) {} + + public void setLineWidth(double lineWidth) {} + + public void setFilled(boolean filled) {} + + public void setColor(Color c) {} + + public void setLocation(double x, double y) {} + + public void setSize(double width, double height) {} + + public void draw(GLFunc gl) {} + + public float getStringX() { + return 0f; + } + + public float getStringY() { + return 0f; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/LabelGL.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/LabelGL.java new file mode 100644 index 0000000..09d4ad5 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/LabelGL.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robocodeGL; + + +/** + * Dummy class that stub out RobocodeGL 0.1.4 functionality. + * + * Original author is David Alves for RobocodeGL. + */ +public class LabelGL { + + public LabelGL(String s) {} + + public synchronized void setString(String s) {} + + public synchronized String toString() { + return ""; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/LineGL.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/LineGL.java new file mode 100644 index 0000000..217cf72 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/LineGL.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robocodeGL; + + +import java.awt.Color; + +import gl4java.GLFunc; + + +/** + * Dummy class that stub out RobocodeGL 0.1.4 functionality. + * + * Original author is David Alves for RobocodeGL. + */ +public class LineGL extends RenderElement { + + public LineGL() {} + + public LineGL(double x1, double y1, double x2, double y2) {} + + public void setLine(double x1, double y1, double x2, double y2) {} + + public void setWidth(double lineWidth) {} + + public void setColor(Color c) {} + + public void draw(GLFunc gl) {} + + public float getStringX() { + return 0f; + } + + public float getStringY() { + return 0f; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/PointGL.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/PointGL.java new file mode 100644 index 0000000..d7a543a --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/PointGL.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robocodeGL; + + +import gl4java.GLFunc; +import java.awt.Color; + + +/** + * Dummy class that stub out RobocodeGL 0.1.4 functionality. + * + * Original author is David Alves for RobocodeGL. + */ +public class PointGL extends RenderElement { + + public void setSize(float size) {} + + public synchronized void setPosition(double x, double y) {} + + public void setColor(Color c) {} + + public float getStringX() { + return 0f; + } + + public float getStringY() { + return 0f; + } + + public void draw(GLFunc gl) {} +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/RectangleGL.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/RectangleGL.java new file mode 100644 index 0000000..8def061 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/RectangleGL.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robocodeGL; + + +import gl4java.GLFunc; +import java.awt.Color; + + +/** + * Dummy class that stub out RobocodeGL 0.1.4 functionality. + * + * Original author is David Alves for RobocodeGL. + */ +public class RectangleGL extends RenderElement { + + public RectangleGL() {} + + public RectangleGL(double x, double y, double width, double height) {} + + public RectangleGL(double x, double y, double width, double height, Color c, double lineWidth) {} + + public void setBounds(double x, double y, double width, double height) {} + + public void setLineWidth(double lineWidth) {} + + public void setColor(Color color) {} + + public void setFilled(boolean filled) {} + + public void setLocation(double x, double y) {} + + public void setSize(double width, double height) {} + + public void draw(GLFunc gl) {} + + public float getStringX() { + return 0f; + } + + public float getStringY() { + return 0f; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/RenderElement.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/RenderElement.java new file mode 100644 index 0000000..17be2d8 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/RenderElement.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robocodeGL; + + +import gl4java.GLFont; +import gl4java.GLFunc; + + +/** + * Dummy class that stub out RobocodeGL 0.1.4 functionality. + * + * Original author is David Alves for RobocodeGL. + */ +public abstract class RenderElement { + + public static void init(GLFont glf) {} + + public RenderElement() {} + + public synchronized void addLabel(LabelGL l) {} + + public synchronized void removeLabel(LabelGL l) {} + + public synchronized void remove() {} + + public synchronized boolean isRemoved() { + return false; + } + + public synchronized void drawStrings(GLFunc gl) {} + + public abstract void draw(GLFunc gl); + + public float getStringX() { + return 0f; + } + + public float getStringY() { + return 0f; + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/system/GLRenderer.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/system/GLRenderer.java new file mode 100644 index 0000000..30be5ee --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robocodeGL/system/GLRenderer.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robocodeGL.system; + + +import robocode.robocodeGL.RenderElement; + + +/** + * Dummy class that stub out RobocodeGL 0.1.4 functionality. + * + * Original author is David Alves for RobocodeGL. + */ +public class GLRenderer { + + public static GLRenderer getInstance() { + return new GLRenderer(); + } + + public void addRenderElement(RenderElement e) {} +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IAdvancedEvents.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IAdvancedEvents.java new file mode 100644 index 0000000..2ee2574 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IAdvancedEvents.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +import robocode.CustomEvent; +import robocode.SkippedTurnEvent; + + +/** + * An event interface for receiving advanced robot events with an + * {@link IAdvancedRobot}. + * + * @see IAdvancedRobot + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IAdvancedEvents { + + /** + * This method is called if the robot is using too much time between + * actions. When this event occur, the robot's turn is skipped, meaning that + * it cannot take action anymore in this turn. + *

+ * If you receive 30 skipped turn event, your robot will be removed from the + * round and loose the round. + *

+ * You will only receive this event after taking an action. So a robot in an + * infinite loop will not receive any events, and will simply be stopped. + *

+ * No correctly working, reasonable robot should ever receive this event + * unless it is using too many CPU cycles. + * + * @param event the skipped turn event set by the game + * @see robocode.SkippedTurnEvent + * @see robocode.Event + */ + void onSkippedTurn(SkippedTurnEvent event); + + /** + * This method is called when a custom condition is met. + *

+ * See the sample robots for examples of use, e.g. the {@code sample.Target} + * robot. + * + * @param event the custom event that occurred + * @see robocode.AdvancedRobot#addCustomEvent + * @see robocode.CustomEvent + * @see robocode.Event + */ + void onCustomEvent(CustomEvent event); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IAdvancedRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IAdvancedRobot.java new file mode 100644 index 0000000..39c6c90 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IAdvancedRobot.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +/** + * A robot interface for creating a more advanced type of robot like + * {@link robocode.AdvancedRobot} that is able to handle advanced robot events. + * An advanced robot allows non-blocking calls, custom events, get notifications + * about skipped turns, and also allow writes to the file system. + * + * @see robocode.AdvancedRobot + * @see IBasicRobot + * @see IJuniorRobot + * @see IInteractiveRobot + * @see ITeamRobot + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IAdvancedRobot extends IBasicRobot { + + /** + * This method is called by the game to notify this robot about advanced + * robot event. Hence, this method must be implemented so it returns your + * {@link IAdvancedEvents} listener. + * + * @return listener to advanced events or {@code null} if this robot should + * not receive the notifications. + * @since 1.6 + */ + IAdvancedEvents getAdvancedEventListener(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents.java new file mode 100644 index 0000000..3e9a2ce --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents.java @@ -0,0 +1,278 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +import robocode.*; + + +/** + * An event interface for receiving basic robot events with an + * {@link IBasicRobot}. + * + * @see IBasicRobot + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IBasicEvents { + + /** + * This method is called every turn in a battle round in order to provide + * the robot status as a complete snapshot of the robot's current state at + * that specific time. + *

+ * The main benefit of this method is that you'll automatically receive all + * current data values of the robot like e.g. the x and y coordinate, + * heading, gun heat etc., which are grouped into the exact same time/turn. + *

+ * This is the only way to map the robots data values to a specific time. + * For example, it is not possible to determine the exact time of the + * robot's heading by calling first calling {@link Robot#getTime()} and then + * {@link Robot#getHeading()} afterwards, as the time might change + * after between the {@link Robot#getTime()} and {@link Robot#getHeading()} + * call. + * + * @param event the event containing the robot status at the time it occurred. + * @see StatusEvent + * @see Event + * @since 1.5 + */ + void onStatus(StatusEvent event); + + /** + * This method is called when one of your bullets hits another robot. + * You should override it in your robot if you want to be informed of this + * event. + *

+ * Example: + *

+	 *   public void onBulletHit(BulletHitEvent event) {
+	 *       out.println("I hit " + event.getName() + "!");
+	 *   }
+	 * 
+ * + * @param event the bullet-hit event set by the game + * @see BulletHitEvent + * @see Event + */ + void onBulletHit(BulletHitEvent event); + + /** + * This method is called when one of your bullets hits another bullet. + * You should override it in your robot if you want to be informed of this + * event. + *

+ * Example: + *

+	 *   public void onBulletHitBullet(BulletHitBulletEvent event) {
+	 *       out.println("I hit a bullet fired by " + event.getBullet().getName() + "!");
+	 *   }
+	 * 
+ * + * @param event the bullet-hit-bullet event set by the game + * @see BulletHitBulletEvent + * @see Event + */ + void onBulletHitBullet(BulletHitBulletEvent event); + + /** + * This method is called when one of your bullets misses, i.e. hits a wall. + * You should override it in your robot if you want to be informed of this + * event. + *

+ * Example: + *

+	 *   public void onBulletMissed(BulletMissedEvent event) {
+	 *       out.println("Drat, I missed.");
+	 *   }
+	 * 
+ * + * @param event the bullet-missed event set by the game + * @see BulletMissedEvent + * @see Event + */ + void onBulletMissed(BulletMissedEvent event); + + /** + * This method is called if your robot dies. + *

+ * You should override it in your robot if you want to be informed of this + * event. Actions will have no effect if called from this section. The + * intent is to allow you to perform calculations or print something out + * when the robot is killed. + * + * @param event the death event set by the game + * @see DeathEvent + * @see WinEvent + * @see RoundEndedEvent + * @see BattleEndedEvent + * @see Event + */ + public void onDeath(DeathEvent event); + + /** + * This method is called when your robot is hit by a bullet. + * You should override it in your robot if you want to be informed of this + * event. + *

+ * Example: + *

+	 *   void onHitByBullet(HitByBulletEvent event) {
+	 *       out.println(event.getRobotName() + " hit me!");
+	 *   }
+	 * 
+ * + * @param event the hit-by-bullet event set by the game + * @see HitByBulletEvent + * @see Event + */ + void onHitByBullet(HitByBulletEvent event); + + /** + * This method is called when your robot collides with another robot. + * You should override it in your robot if you want to be informed of this + * event. + *

+ * Example: + *

+	 *   void onHitRobot(HitRobotEvent event) {
+	 *       if (event.getBearing() > -90 && event.getBearing() <= 90) {
+	 *           back(100);
+	 *       } else {
+	 *           ahead(100);
+	 *       }
+	 *   }
+	 * 

+ * -- or perhaps, for a more advanced robot -- + *

+ * public void onHitRobot(HitRobotEvent event) { + * if (event.getBearing() > -90 && event.getBearing() <= 90) { + * setBack(100); + * } else { + * setAhead(100); + * } + * } + *

+ *

+ * The angle is relative to your robot's facing. So 0 is straight ahead of + * you. + *

+ * This event can be generated if another robot hits you, in which case + * {@link HitRobotEvent#isMyFault() event.isMyFault()} will return + * {@code false}. In this case, you will not be automatically stopped by the + * game -- but if you continue moving toward the robot you will hit it (and + * generate another event). If you are moving away, then you won't hit it. + * + * @param event the hit-robot event set by the game + * @see HitRobotEvent + * @see Event + */ + void onHitRobot(HitRobotEvent event); + + /** + * This method is called when your robot collides with a wall. + * You should override it in your robot if you want to be informed of this + * event. + *

+ * The wall at the top of the screen is 0 degrees, right is 90 degrees, + * bottom is 180 degrees, left is 270 degrees. But this event is relative to + * your heading, so: The bearing is such that {@link Robot#turnRight(double) + * turnRight} {@link HitWallEvent#getBearing() (event.getBearing())} will + * point you perpendicular to the wall. + *

+ * Example: + *

+	 *   void onHitWall(HitWallEvent event) {
+	 *       out.println("Ouch, I hit a wall bearing " + event.getBearing() + " degrees.");
+	 *   }
+	 * 
+ * + * @param event the hit-wall event set by the game + * @see HitWallEvent + * @see Event + */ + void onHitWall(HitWallEvent event); + + /** + * This method is called when your robot sees another robot, i.e. when the + * robot's radar scan "hits" another robot. + * You should override it in your robot if you want to be informed of this + * event. (Almost all robots should override this!) + *

+ * This event is automatically called if there is a robot in range of your + * radar. + *

+ * Note that the robot's radar can only see robot within the range defined + * by {@link Rules#RADAR_SCAN_RADIUS} (1200 pixels). + *

+ * Also not that the bearing of the scanned robot is relative to your + * robot's heading. + *

+ * Example: + *

+	 *   void onScannedRobot(ScannedRobotEvent event) {
+	 *       // Assuming radar and gun are aligned...
+	 *       if (event.getDistance() < 100) {
+	 *           fire(3);
+	 *       } else {
+	 *           fire(1);
+	 *       }
+	 *   }
+	 * 
+ *

+ * Note:
+ * The game assists Robots in firing, as follows: + *

    + *
  • If the gun and radar are aligned (and were aligned last turn), + *
  • and the event is current, + *
  • and you call fire() before taking any other actions, {@link + * Robot#fire(double) fire()} will fire directly at the robot. + *
+ *

+ * In essence, this means that if you can see a robot, and it doesn't move, + * then fire will hit it. + *

+ * AdvancedRobots will NOT be assisted in this manner, and are expected to + * examine the event to determine if {@link Robot#fire(double) fire()} would + * hit. (i.e. you are spinning your gun around, but by the time you get the + * event, your gun is 5 degrees past the robot). + * + * @param event the scanned-robot event set by the game + * @see ScannedRobotEvent + * @see Event + * @see Rules#RADAR_SCAN_RADIUS + */ + void onScannedRobot(ScannedRobotEvent event); + + /** + * This method is called when another robot dies. + * You should override it in your robot if you want to be informed of this + * event. + * + * @param event The robot-death event set by the game + * @see RobotDeathEvent + * @see Event + */ + void onRobotDeath(RobotDeathEvent event); + + /** + * This method is called if your robot wins a battle. + *

+ * Your robot could perform a victory dance here! :-) + * + * @param event the win event set by the game + * @see DeathEvent + * @see RoundEndedEvent + * @see BattleEndedEvent + * @see Event + */ + void onWin(WinEvent event); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents2.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents2.java new file mode 100644 index 0000000..e737569 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents2.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +import robocode.BattleEndedEvent; +import robocode.RoundEndedEvent; + + +/** + * First extended version of the {@link IBasicEvents} interface. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +public interface IBasicEvents2 extends IBasicEvents { + + /** + * This method is called after the end of the battle, even when the battle is aborted. + * You should override it in your robot if you want to be informed of this event. + *

+ * Example: + *

+	 *   public void onBattleEnded(BattleEndedEvent event) {
+	 *       out.println("The battle has ended");
+	 *   }
+	 * 
+ * + * @param event the BattleEndedEvent set by the game + * @see BattleEndedEvent + * @see IBasicEvents3#onRoundEnded(RoundEndedEvent) + * @see robocode.WinEvent + * @see robocode.DeathEvent + * @see robocode.Event + * + * @since 1.6.1 + */ + void onBattleEnded(BattleEndedEvent event); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents3.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents3.java new file mode 100644 index 0000000..6396c1e --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicEvents3.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +import robocode.BattleEndedEvent; +import robocode.RoundEndedEvent; + + +/** + * Second extended version of the {@link IBasicEvents} interface. + * + * @author Flemming N. Larsen (original) + * + * @since 1.7.2 + */ +public interface IBasicEvents3 extends IBasicEvents2 { + + /** + * This method is called after the end of a round. + * You should override it in your robot if you want to be informed of this event. + *

+ * Example: + *

+	 *   public void onRoundEnded(RoundEndedEvent event) {
+	 *       out.println("The round has ended");
+	 *   }
+	 * 
+ * + * @param event the RoundEndedEvent event set by the game + * @see RoundEndedEvent + * @see #onBattleEnded(BattleEndedEvent) + * @see robocode.WinEvent + * @see robocode.DeathEvent + * @see robocode.Event + * + * @since 1.7.2 + */ + void onRoundEnded(RoundEndedEvent event); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicRobot.java new file mode 100644 index 0000000..d61ddfb --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IBasicRobot.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +import robocode.robotinterfaces.peer.IBasicRobotPeer; + + +/** + * A robot interface for creating a basic type of robot like {@link robocode.Robot} + * that is able to receive common robot events, but not interactive events as + * with the {@link robocode.Robot} class. + * A basic robot allows blocking calls only and cannot handle custom events nor + * writes to the file system like an advanced robot. + * + * @see robocode.Robot + * @see IJuniorRobot + * @see IInteractiveRobot + * @see IAdvancedRobot + * @see ITeamRobot + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IBasicRobot { + + /** + * This method is called by the game to invoke the + * {@link java.lang.Runnable#run() run()} method of your robot, where the program + * of your robot is implemented. + * + * @return a runnable implementation + * @see java.lang.Runnable#run() + * @since 1.6 + */ + Runnable getRobotRunnable(); + + /** + * This method is called by the game to notify this robot about basic + * robot event. Hence, this method must be implemented so it returns your + * {@link IBasicEvents} listener. + * + * @return listener to basic events or {@code null} if this robot should + * not receive the notifications. + * @since 1.6 + */ + IBasicEvents getBasicEventListener(); + + /** + * Do not call this method! Your robot will simply stop interacting with + * the game. + *

+ * This method is called by the game. A robot peer is the object that deals + * with game mechanics and rules, and makes sure your robot abides by them. + * + * @param peer the robot peer supplied by the game + */ + void setPeer(IBasicRobotPeer peer); + + /** + * Do not call this method! + *

+ * This method is called by the game when setting the output stream for your + * robot. + * + * @param out the new output print stream for this robot + * @since 1.6 + */ + void setOut(java.io.PrintStream out); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IInteractiveEvents.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IInteractiveEvents.java new file mode 100644 index 0000000..f249dc9 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IInteractiveEvents.java @@ -0,0 +1,223 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; + + +/** + * An event interface for receiving interactive events with an + * {@link IInteractiveRobot}. + * + * @see IInteractiveRobot + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IInteractiveEvents { + + /** + * This method is called when a key has been pressed. + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * key events. + * + * @param event holds details about current event + * @see java.awt.event.KeyListener#keyPressed(KeyEvent) + * @see #onKeyReleased(KeyEvent) + * @see #onKeyTyped(KeyEvent) + * @since 1.3.4 + */ + void onKeyPressed(KeyEvent event); + + /** + * This method is called when a key has been released. + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * key events. + * + * @param event holds details about current event + * @see java.awt.event.KeyListener#keyReleased(KeyEvent) + * @see #onKeyPressed(KeyEvent) + * @see #onKeyTyped(KeyEvent) + * @since 1.3.4 + */ + void onKeyReleased(KeyEvent event); + + /** + * This method is called when a key has been typed (pressed and released). + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * key events. + * + * @param event holds details about current event + * @see java.awt.event.KeyListener#keyTyped(KeyEvent) + * @see #onKeyPressed(KeyEvent) + * @see #onKeyReleased(KeyEvent) + * @since 1.3.4 + */ + void onKeyTyped(KeyEvent event); + + /** + * This method is called when a mouse button has been clicked (pressed and + * released). + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * mouse events. + * + * @param event holds details about current event + * @see java.awt.event.MouseListener#mouseClicked(MouseEvent) + * @see #onMouseMoved(MouseEvent) + * @see #onMousePressed(MouseEvent) + * @see #onMouseReleased(MouseEvent) + * @see #onMouseEntered(MouseEvent) + * @see #onMouseExited(MouseEvent) + * @see #onMouseDragged(MouseEvent) + * @see #onMouseWheelMoved(MouseWheelEvent) + * @since 1.3.4 + */ + void onMouseClicked(MouseEvent event); + + /** + * This method is called when the mouse has entered the battle view. + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * mouse events. + * + * @param event holds details about current event + * @see java.awt.event.MouseListener#mouseEntered(MouseEvent) + * @see #onMouseMoved(MouseEvent) + * @see #onMousePressed(MouseEvent) + * @see #onMouseReleased(MouseEvent) + * @see #onMouseClicked(MouseEvent) + * @see #onMouseExited(MouseEvent) + * @see #onMouseDragged(MouseEvent) + * @see #onMouseWheelMoved(MouseWheelEvent) + * @since 1.3.4 + */ + void onMouseEntered(MouseEvent event); + + /** + * This method is called when the mouse has exited the battle view. + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * mouse events. + * + * @param event holds details about current event + * @see java.awt.event.MouseListener#mouseExited(MouseEvent) + * @see #onMouseMoved(MouseEvent) + * @see #onMousePressed(MouseEvent) + * @see #onMouseReleased(MouseEvent) + * @see #onMouseClicked(MouseEvent) + * @see #onMouseEntered(MouseEvent) + * @see #onMouseDragged(MouseEvent) + * @see #onMouseWheelMoved(MouseWheelEvent) + * @since 1.3.4 + */ + void onMouseExited(MouseEvent event); + + /** + * This method is called when a mouse button has been pressed. + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * mouse events. + * + * @param event holds details about current event + * @see java.awt.event.MouseListener#mousePressed(MouseEvent) + * @see #onMouseMoved(MouseEvent) + * @see #onMouseReleased(MouseEvent) + * @see #onMouseClicked(MouseEvent) + * @see #onMouseEntered(MouseEvent) + * @see #onMouseExited(MouseEvent) + * @see #onMouseDragged(MouseEvent) + * @see #onMouseWheelMoved(MouseWheelEvent) + * @since 1.3.4 + */ + void onMousePressed(MouseEvent event); + + /** + * This method is called when a mouse button has been released. + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * mouse events. + * + * @param event holds details about current event + * @see java.awt.event.MouseListener#mouseReleased(MouseEvent) + * @see #onMouseMoved(MouseEvent) + * @see #onMousePressed(MouseEvent) + * @see #onMouseClicked(MouseEvent) + * @see #onMouseEntered(MouseEvent) + * @see #onMouseExited(MouseEvent) + * @see #onMouseDragged(MouseEvent) + * @see #onMouseWheelMoved(MouseWheelEvent) + * @since 1.3.4 + */ + void onMouseReleased(MouseEvent event); + + /** + * This method is called when the mouse has been moved. + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * mouse events. + * + * @param event holds details about current event + * @see java.awt.event.MouseMotionListener#mouseMoved(MouseEvent) + * @see #onMousePressed(MouseEvent) + * @see #onMouseReleased(MouseEvent) + * @see #onMouseClicked(MouseEvent) + * @see #onMouseEntered(MouseEvent) + * @see #onMouseExited(MouseEvent) + * @see #onMouseDragged(MouseEvent) + * @see #onMouseWheelMoved(MouseWheelEvent) + * @since 1.3.4 + */ + void onMouseMoved(MouseEvent event); + + /** + * This method is called when a mouse button has been pressed and then + * dragged. + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * mouse events. + * + * @param event holds details about current event + * @see java.awt.event.MouseMotionListener#mouseDragged(MouseEvent) + * @see #onMouseMoved(MouseEvent) + * @see #onMousePressed(MouseEvent) + * @see #onMouseReleased(MouseEvent) + * @see #onMouseClicked(MouseEvent) + * @see #onMouseEntered(MouseEvent) + * @see #onMouseExited(MouseEvent) + * @see #onMouseWheelMoved(MouseWheelEvent) + * @since 1.3.4 + */ + void onMouseDragged(MouseEvent event); + + /** + * This method is called when the mouse wheel has been rotated. + *

+ * See the {@code sample.Interactive} robot for an example of how to use + * mouse events. + * + * @param event holds details about current event + * @see java.awt.event.MouseWheelListener#mouseWheelMoved(MouseWheelEvent) + * @see #onMouseMoved(MouseEvent) + * @see #onMousePressed(MouseEvent) + * @see #onMouseReleased(MouseEvent) + * @see #onMouseClicked(MouseEvent) + * @see #onMouseEntered(MouseEvent) + * @see #onMouseExited(MouseEvent) + * @see #onMouseDragged(MouseEvent) + */ + void onMouseWheelMoved(MouseWheelEvent event); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IInteractiveRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IInteractiveRobot.java new file mode 100644 index 0000000..3ed501b --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IInteractiveRobot.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +/** + * A robot interface for creating an interactive type of robot like + * {@link robocode.Robot} and {@link robocode.AdvancedRobot} that is able to + * receive interactive events from the keyboard or mouse. + * If a robot is directly inherited from this class it will behave as similar to + * a {@link IBasicRobot}. If you need it to behave similar to a + * {@link IAdvancedRobot} or {@link ITeamRobot}, you should inherit from these + * interfaces instead, as these are inherited from this interface. + * + * @see robocode.Robot + * @see robocode.AdvancedRobot + * @see IBasicRobot + * @see IJuniorRobot + * @see IAdvancedRobot + * @see ITeamRobot + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (javadoc) + * + * @since 1.6 + */ +public interface IInteractiveRobot extends IBasicRobot { + + /** + * This method is called by the game to notify this robot about interactive + * events, i.e. keyboard and mouse events. Hence, this method must be + * implemented so it returns your {@link IInteractiveEvents} listener. + * + * @return listener to interactive events or {@code null} if this robot + * should not receive the notifications. + * @since 1.6 + */ + IInteractiveEvents getInteractiveEventListener(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IJuniorRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IJuniorRobot.java new file mode 100644 index 0000000..892b8c7 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IJuniorRobot.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +/** + * A robot interface for creating the most primitive robot type, which is a + * {@link robocode.JuniorRobot}. A junior robot is simpler than the + * {@link robocode.Robot} class. + *

+ * A junior robot has a simplified model, in purpose of teaching programming + * skills to inexperienced in programming students. + * The simplified robot model will keep player from overwhelming of Robocode's + * rules, programming syntax and programming concept. + *

+ * Instead of using getters and setters, public fields are provided for + * receiving information like the last scanned robot, the coordinate of the + * robot etc. + *

+ * All methods on a junior robot are blocking calls, i.e. they do not return + * before their action has been completed and will at least take one turn to + * execute. + * + * @see robocode.JuniorRobot + * @see IBasicRobot + * @see IAdvancedRobot + * @see IInteractiveRobot + * @see ITeamRobot + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IJuniorRobot extends IBasicRobot {} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IPaintEvents.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IPaintEvents.java new file mode 100644 index 0000000..2df2662 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IPaintEvents.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +import java.awt.*; + + +/** + * An event interface for receiving paint events with an + * {@link robocode.robotinterfaces.IPaintRobot}. + * + * @see robocode.robotinterfaces.IPaintRobot + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IPaintEvents { + + /** + * This method is called every time the robot is painted. You should + * override this method if you want to draw items for your robot on the + * battle field, e.g. targets, virtual bullets etc. + *

+ * This method is very useful for debugging your robot. + *

+ * Note that the robot will only be painted if the "Paint" is enabled on the + * robot's console window; otherwise the robot will never get painted (the + * reason being that all robots might have graphical items that must be + * painted, and then you might not be able to tell what graphical items that + * have been painted for your robot). + *

+ * Also note that the coordinate system for the graphical context where you + * paint items fits for the Robocode coordinate system where (0, 0) is at + * the bottom left corner of the battlefield, where X is towards right and Y + * is upwards. + * + * @param g the graphics context to use for painting graphical items for the + * robot. + * + * @see java.awt.Graphics2D + * + * @since 1.1 + */ + void onPaint(Graphics2D g); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IPaintRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IPaintRobot.java new file mode 100644 index 0000000..03c5db1 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/IPaintRobot.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +/** + * A robot interface that makes it possible for a robot to receive paint events. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IPaintRobot extends IBasicRobot { + + /** + * This method is called by the game to notify this robot about painting + * events. Hence, this method must be implemented so it returns your + * {@link IPaintEvents} listener. + * + * @return listener to paint events or {@code null} if this robot should + * not receive the notifications. + * @since 1.6 + */ + IPaintEvents getPaintEventListener(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/ITeamEvents.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/ITeamEvents.java new file mode 100644 index 0000000..bf2ff3a --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/ITeamEvents.java @@ -0,0 +1,27 @@ +package robocode.robotinterfaces; + + +import robocode.MessageEvent; + + + +public interface ITeamEvents { + + /** + * This method is called when your robot receives a message from a teammate. + * You should override it in your robot if you want to be informed of this + * event. + *

+ * Example: + *

+	 *   public void onMessageReceived(MessageEvent event) {
+	 *       out.println(event.getSender() + " sent me: " + event.getMessage());
+	 *   }
+	 * 
+ * + * @param event the message event sent by the game + * @see robocode.MessageEvent + * @see robocode.Event + */ + void onMessageReceived(MessageEvent event); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/ITeamRobot.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/ITeamRobot.java new file mode 100644 index 0000000..e1ebf8f --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/ITeamRobot.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces; + + +/** + * A robot interface for creating a team robot like {@link robocode.TeamRobot} + * that is able to receive team events. + * A team robot is an advanced type of robot that supports sending messages + * between teammates that participates in a team. + * + * @see robocode.TeamRobot + * @see IBasicRobot + * @see IJuniorRobot + * @see IInteractiveRobot + * @see IAdvancedRobot + * @see ITeamRobot + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface ITeamRobot extends IAdvancedRobot { + + /** + * This method is called by the game to notify this robot about team events. + * Hence, this method must be implemented so it returns your + * {@link ITeamEvents} listener. + * + * @return listener to team events or {@code null} if this robot should + * not receive the notifications. + */ + ITeamEvents getTeamEventListener(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/package-info.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/package-info.java new file mode 100644 index 0000000..9d4aa43 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/package-info.java @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + +/** + * Robot Interfaces used for creating new robot types, e.g. with other programming languages. + */ +package robocode.robotinterfaces; diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IAdvancedRobotPeer.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IAdvancedRobotPeer.java new file mode 100644 index 0000000..1dcb879 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IAdvancedRobotPeer.java @@ -0,0 +1,751 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces.peer; + + +import robocode.*; + +import java.io.File; +import java.util.List; + + +/** + * The advanced robot peer for advanced robot types like + * {@link robocode.AdvancedRobot} and {@link robocode.TeamRobot}. + *

+ * A robot peer is the object that deals with game mechanics and rules, and + * makes sure your robot abides by them. + * + * @see IBasicRobotPeer + * @see IStandardRobotPeer + * @see ITeamRobotPeer + * @see IJuniorRobotPeer + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IAdvancedRobotPeer extends IStandardRobotPeer { + + /** + * Checks if the gun is set to adjust for the robot turning, i.e. to turn + * independent from the robot's body turn. + *

+ * This call returns {@code true} if the gun is set to turn independent of + * the turn of the robot's body. Otherwise, {@code false} is returned, + * meaning that the gun is set to turn with the robot's body turn. + * + * @return {@code true} if the gun is set to turn independent of the robot + * turning; {@code false} if the gun is set to turn with the robot + * turning + * @see #setAdjustGunForBodyTurn(boolean) setAdjustGunForBodyTurn(boolean) + * @see #isAdjustRadarForBodyTurn() + * @see #isAdjustRadarForGunTurn() + */ + boolean isAdjustGunForBodyTurn(); + + /** + * Checks if the radar is set to adjust for the robot turning, i.e. to turn + * independent from the robot's body turn. + *

+ * This call returns {@code true} if the radar is set to turn independent of + * the turn of the robot. Otherwise, {@code false} is returned, meaning that + * the radar is set to turn with the robot's turn. + * + * @return {@code true} if the radar is set to turn independent of the robot + * turning; {@code false} if the radar is set to turn with the robot + * turning + * @see #setAdjustRadarForBodyTurn(boolean) setAdjustRadarForBodyTurn(boolean) + * @see #isAdjustGunForBodyTurn() + * @see #isAdjustRadarForGunTurn() + */ + boolean isAdjustRadarForGunTurn(); + + /** + * Checks if the radar is set to adjust for the gun turning, i.e. to turn + * independent from the gun's turn. + *

+ * This call returns {@code true} if the radar is set to turn independent of + * the turn of the gun. Otherwise, {@code false} is returned, meaning that + * the radar is set to turn with the gun's turn. + * + * @return {@code true} if the radar is set to turn independent of the gun + * turning; {@code false} if the radar is set to turn with the gun + * turning + * @see #setAdjustRadarForGunTurn(boolean) setAdjustRadarForGunTurn(boolean) + * @see #isAdjustGunForBodyTurn() + * @see #isAdjustRadarForBodyTurn() + */ + boolean isAdjustRadarForBodyTurn(); + + /** + * This call is identical to {@link IStandardRobotPeer#stop(boolean) + * stop(boolean)}, but returns immediately, and will not execute until you + * call {@link IBasicRobotPeer#execute() execute()} or take an action that executes. + *

+ * If there is already movement saved from a previous stop, you can + * overwrite it by calling {@code setStop(true)}. + * + * @param overwrite {@code true} if the movement saved from a previous stop + * should be overwritten; {@code false} otherwise. + * @see IStandardRobotPeer#stop(boolean) stop(boolean) + * @see IStandardRobotPeer#resume() resume() + * @see #setResume() + * @see IBasicRobotPeer#execute() execute() + */ + void setStop(boolean overwrite); + + /** + * Sets the robot to resume the movement stopped by + * {@link IStandardRobotPeer#stop(boolean) stop(boolean)} or + * {@link #setStop(boolean)}, if any. + *

+ * This call returns immediately, and will not execute until you call + * {@link IBasicRobotPeer#execute() execute()} or take an action that executes. + * + * @see IStandardRobotPeer#resume() resume() + * @see IStandardRobotPeer#stop(boolean) stop(boolean) + * @see #setStop(boolean) + * @see IBasicRobotPeer#execute() execute() + */ + void setResume(); + + /** + * Sets the robot to move forward or backward by distance measured in pixels + * when the next execution takes place. + *

+ * This call returns immediately, and will not execute until you call + * {@link IBasicRobotPeer#execute() execute()} or take an action that executes. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot is set to move forward, and negative + * values means that the robot is set to move backward. If 0 is given as + * input, the robot will stop its movement, but will have to decelerate + * till it stands still, and will thus not be able to stop its movement + * immediately, but eventually. + *

+ * Example: + *

+	 *   // Set the robot to move 50 pixels forward
+	 *   setMove(50);
+	 *
+	 *   // Set the robot to move 100 pixels backward
+	 *   // (overrides the previous order)
+	 *   setMove(-100);
+	 *
+	 *   ...
+	 *   // Executes the last setMove()
+	 *   execute();
+	 * 
+ * + * @param distance the distance to move measured in pixels. + * If {@code distance} > 0 the robot is set to move forward. + * If {@code distance} < 0 the robot is set to move backward. + * If {@code distance} = 0 the robot is set to stop its movement. + * @see IBasicRobotPeer#move(double) move(double) + * @see #setMaxVelocity(double) + * @see #setTurnBody(double) + * @see #setTurnGun(double) + * @see #setTurnRadar(double) + */ + void setMove(double distance); + + /** + * Sets the robot's body to turn right or left by radians when the next + * execution takes place. + *

+ * This call returns immediately, and will not execute until you call + * {@link IBasicRobotPeer#execute() execute()} or take an action that + * executes. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot's body is set to turn right, and + * negative values means that the robot's body is set to turn left. + * If 0 is given as input, the robot's body will stop turning. + *

+ * Example: + *

+	 *   // Set the robot's body to turn 180 degrees to the right
+	 *   setTurnBody(Math.PI);
+	 *
+	 *   // Set the robot's body to turn 90 degrees to the left instead of right
+	 *   // (overrides the previous order)
+	 *   setTurnBody(-Math.PI / 2);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnBody()
+	 *   execute();
+	 * 
+ * + * @param radians the amount of radians to turn the robot's body. + * If {@code radians} > 0 the robot's body is set to turn right. + * If {@code radians} < 0 the robot's body is set to turn left. + * If {@code radians} = 0 the robot's body is set to stop turning. + * @see IBasicRobotPeer#turnBody(double) turnBody(double) + * @see #setTurnGun(double) + * @see #setTurnRadar(double) + * @see #setMaxTurnRate(double) + * @see #setMove(double) + */ + void setTurnBody(double radians); + + /** + * Sets the robot's gun to turn right or left by radians when the next + * execution takes place. + *

+ * This call returns immediately, and will not execute until you call + * {@link IBasicRobotPeer#execute() execute()} or take an action that + * executes. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot's gun is set to turn right, and + * negative values means that the robot's gun is set to turn left. + * If 0 is given as input, the robot's gun will stop turning. + *

+ * Example: + *

+	 *   // Set the robot's gun to turn 180 degrees to the right
+	 *   setTurnGun(Math.PI);
+	 *
+	 *   // Set the robot's gun to turn 90 degrees to the left instead of right
+	 *   // (overrides the previous order)
+	 *   setTurnGun(-Math.PI / 2);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnFun()
+	 *   execute();
+	 * 
+ * + * @param radians the amount of radians to turn the robot's gun. + * If {@code radians} > 0 the robot's gun is set to turn right. + * If {@code radians} < 0 the robot's gun is set to turn left. + * If {@code radians} = 0 the robot's gun is set to stop turning. + * @see IBasicRobotPeer#turnGun(double) turnGun(double) + * @see #setTurnBody(double) + * @see #setTurnRadar(double) + * @see #setMove(double) + */ + void setTurnGun(double radians); + + /** + * Sets the robot's radar to turn right or left by radians when the next + * execution takes place. + *

+ * This call returns immediately, and will not execute until you call + * {@link IBasicRobotPeer#execute() execute()} or take an action that + * executes. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot's radar is set to turn right, and + * negative values means that the robot's radar is set to turn left. + * If 0 is given as input, the robot's radar will stop turning. + *

+ * Example: + *

+	 *   // Set the robot's radar to turn 180 degrees to the right
+	 *   setTurnRadar(Math.PI);
+	 *
+	 *   // Set the robot's radar to turn 90 degrees to the left instead of right
+	 *   // (overrides the previous order)
+	 *   setTurnRadar(-Math.PI / 2);
+	 *
+	 *   ...
+	 *   // Executes the last setTurnRadar()
+	 *   execute();
+	 * 
+ * + * @param radians the amount of radians to turn the robot's radar. + * If {@code radians} > 0 the robot's radar is set to turn right. + * If {@code radians} < 0 the robot's radar is set to turn left. + * If {@code radians} = 0 the robot's radar is set to stop turning. + * @see IStandardRobotPeer#turnRadar(double) turnRadar(double) + * @see #setTurnBody(double) + * @see #setTurnGun(double) + * @see #setMove(double) + */ + void setTurnRadar(double radians); + + /** + * Sets the maximum turn rate of the robot measured in degrees if the robot + * should turn slower than {@link Rules#MAX_TURN_RATE} (10 degress/turn). + * + * @param newMaxTurnRate the new maximum turn rate of the robot measured in + * degrees. Valid values are 0 - {@link Rules#MAX_TURN_RATE} + * @see IBasicRobotPeer#turnBody(double) turnBody(double) + * @see #setTurnBody(double) + * @see #setMaxVelocity(double) + */ + void setMaxTurnRate(double newMaxTurnRate); + + /** + * Sets the maximum velocity of the robot measured in pixels/turn if the + * robot should move slower than {@link Rules#MAX_VELOCITY} (8 pixels/turn). + * + * @param newMaxVelocity the new maximum turn rate of the robot measured in + * pixels/turn. Valid values are 0 - {@link Rules#MAX_VELOCITY} + * @see IBasicRobotPeer#move(double) move(double) + * @see #setMove(double) + * @see #setMaxTurnRate(double) + */ + void setMaxVelocity(double newMaxVelocity); + + /** + * Does not return until a condition is met, i.e. when a + * {@link Condition#test()} returns {@code true}. + *

+ * This call executes immediately. + *

+ * See the {@code sample.Crazy} robot for how this method can be used. + * + * @param condition the condition that must be met before this call returns + * @see Condition + * @see Condition#test() + */ + void waitFor(Condition condition); + + /** + * Call this during an event handler to allow new events of the same + * priority to restart the event handler. + *

+ *

Example: + *

+	 *   public void onScannedRobot(ScannedRobotEvent e) {
+	 *       fire(1);
+	 *       setInterruptible(true);
+	 *       move(100);  // If you see a robot while moving ahead,
+	 *                   // this handler will start from the top
+	 *                   // Without setInterruptible(true), we wouldn't
+	 *                   // receive scan events at all!
+	 *       // We'll only get here if we don't see a robot during the move.
+	 *       getOut().println("Ok, I can't see anyone");
+	 *   }
+	 * 
+ * + * @param interruptible {@code true} if the event handler should be + * interrupted if new events of the same priority occurs; {@code false} + * otherwise + * @see #setEventPriority(String, int) + * @see robocode.robotinterfaces.IBasicEvents#onScannedRobot(ScannedRobotEvent) + * onScannedRobot(ScannedRobotEvent) + */ + void setInterruptible(boolean interruptible); + + /** + * Sets the priority of a class of events. + *

+ * Events are sent to the onXXX handlers in order of priority. + * Higher priority events can interrupt lower priority events. + * For events with the same priority, newer events are always sent first. + * Valid priorities are 0 - 99, where 100 is reserved and 80 is the default + * priority. + *

+ * Example: + *

+	 *   setEventPriority("RobotDeathEvent", 15);
+	 * 
+ *

+ * The default priorities are, from highest to lowest: + *

+	 *   {@link RoundEndedEvent}:      100 (reserved)
+	 *   {@link BattleEndedEvent}:     100 (reserved)
+	 *   {@link WinEvent}:             100 (reserved)
+	 *   {@link SkippedTurnEvent}:     100 (reserved)
+	 *   {@link StatusEvent}:           99
+	 *   Key and mouse events:  98
+	 *   {@link CustomEvent}:           80 (default value)
+	 *   {@link MessageEvent}:          75
+	 *   {@link RobotDeathEvent}:       70
+	 *   {@link BulletMissedEvent}:     60
+	 *   {@link BulletHitBulletEvent}:  55
+	 *   {@link BulletHitEvent}:        50
+	 *   {@link HitByBulletEvent}:      40
+	 *   {@link HitWallEvent}:          30
+	 *   {@link HitRobotEvent}:         20
+	 *   {@link ScannedRobotEvent}:     10
+	 *   {@link PaintEvent}:             5
+	 *   {@link DeathEvent}:            -1 (reserved)
+	 * 
+ *

+ * Note that you cannot change the priority for events with the special + * priority value -1 or 100 (reserved) as these event are system events. + * Also note that you cannot change the priority of CustomEvent. + * Instead you must change the priority of the condition(s) for your custom + * event(s). + * + * @param eventClass the name of the event class (string) to set the + * priority for + * @param priority the new priority for that event class + * @see #getEventPriority(String) + * @see #setInterruptible(boolean) + * @since 1.5, the priority of DeathEvent was changed from 100 to -1 in + * order to let robots process pending events on its event queue before + * it dies. When the robot dies, it will not be able to process events. + */ + void setEventPriority(String eventClass, int priority); + + /** + * Returns the current priority of a class of events. + * An event priority is a value from 0 - 99. The higher value, the higher + * priority. + *

+ * Example: + *

+	 *   int myHitRobotPriority = getEventPriority("HitRobotEvent");
+	 * 
+ *

+ * The default priorities are, from highest to lowest: + *

+	 *   {@link RoundEndedEvent}:      100 (reserved)
+	 *   {@link BattleEndedEvent}:     100 (reserved)
+	 *   {@link WinEvent}:             100 (reserved)
+	 *   {@link SkippedTurnEvent}:     100 (reserved)
+	 *   {@link StatusEvent}:           99
+	 *   Key and mouse events:  98
+	 *   {@link CustomEvent}:           80 (default value)
+	 *   {@link MessageEvent}:          75
+	 *   {@link RobotDeathEvent}:       70
+	 *   {@link BulletMissedEvent}:     60
+	 *   {@link BulletHitBulletEvent}:  55
+	 *   {@link BulletHitEvent}:        50
+	 *   {@link HitByBulletEvent}:      40
+	 *   {@link HitWallEvent}:          30
+	 *   {@link HitRobotEvent}:         20
+	 *   {@link ScannedRobotEvent}:     10
+	 *   {@link PaintEvent}:             5
+	 *   {@link DeathEvent}:            -1 (reserved)
+	 * 
+ * + * @param eventClass the name of the event class (string) + * @return the current priority of a class of events + * @see #setEventPriority(String, int) + */ + int getEventPriority(String eventClass); + + /** + * Registers a custom event to be called when a condition is met. + * When you are finished with your condition or just want to remove it you + * must call {@link #removeCustomEvent(Condition)}. + *

+ * Example: + *

+	 *   // Create the condition for our custom event
+	 *   Condition triggerHitCondition = new Condition("triggerhit") {
+	 *       public boolean test() {
+	 *           return (getEnergy() <= trigger);
+	 *       };
+	 *   }
+	 *
+	 *   // Add our custom event based on our condition
+	 *   addCustomEvent(triggerHitCondition);
+	 * 
+ * + * @param condition the condition that must be met. + * @throws NullPointerException if the condition parameter has been set to + * {@code null}. + * @see Condition + * @see #removeCustomEvent(Condition) + */ + void addCustomEvent(Condition condition); + + /** + * Removes a custom event that was previously added by calling + * {@link #addCustomEvent(Condition)}. + *

+ * Example: + *

+	 *   // Create the condition for our custom event
+	 *   Condition triggerHitCondition = new Condition("triggerhit") {
+	 *       public boolean test() {
+	 *           return (getEnergy() <= trigger);
+	 *       };
+	 *   }
+	 *
+	 *   // Add our custom event based on our condition
+	 *   addCustomEvent(triggerHitCondition);
+	 *   ...
+	 *   do something with your robot
+	 *   ...
+	 *   // Remove the custom event based on our condition
+	 *   removeCustomEvent(triggerHitCondition);
+	 * 
+ * + * @param condition the condition that was previous added and that must be + * removed now. + * @throws NullPointerException if the condition parameter has been set to + * {@code null}. + * @see Condition + * @see #addCustomEvent(Condition) + */ + void removeCustomEvent(Condition condition); + + /** + * Clears out any pending events in the robot's event queue immediately. + * + * @see #getAllEvents() + */ + void clearAllEvents(); + + /** + * Returns a vector containing all events currently in the robot's queue. + * You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (Event event : getAllEvents()) {
+	 *       if (event instanceof HitRobotEvent) {
+	 *           // do something with the event
+	 *       } else if (event instanceof HitByBulletEvent) {
+	 *           // do something with the event
+	 *       }
+	 *   }
+	 * 
+ * + * @return a vector containing all events currently in the robot's queue + * @see Event + * @see #clearAllEvents() + * @see #getStatusEvents() + * @see #getScannedRobotEvents() + * @see #getBulletHitEvents() + * @see #getBulletMissedEvents() + * @see #getBulletHitBulletEvents() + * @see #getRobotDeathEvents() + */ + java.util.List getAllEvents(); + + /** + * Returns a vector containing all StatusEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (StatusEvent event : getStatusEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all StatusEvents currently in the robot's + * queue + * @see robocode.robotinterfaces.IBasicEvents#onStatus(StatusEvent) + * onStatus(StatusEvent) + * @see StatusEvent + * @see #getAllEvents() + * @since 1.6.1 + */ + List getStatusEvents(); + + /** + * Returns a vector containing all BulletMissedEvents currently in the + * robot's queue. You might, for example, call this while processing another + * event. + *

+ * Example: + *

+	 *   for (BulletMissedEvent event : getBulletMissedEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all BulletMissedEvents currently in the + * robot's queue + * @see robocode.robotinterfaces.IBasicEvents#onBulletMissed(BulletMissedEvent) + * onBulletMissed(BulletMissedEvent) + * @see BulletMissedEvent + * @see #getAllEvents() + */ + List getBulletMissedEvents(); + + /** + * Returns a vector containing all BulletHitBulletEvents currently in the + * robot's queue. You might, for example, call this while processing another + * event. + *

+ * Example: + *

+	 *   for (BulletHitBulletEvent event : getBulletHitBulletEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all BulletHitBulletEvents currently in the + * robot's queue + * @see robocode.robotinterfaces.IBasicEvents#onBulletHitBullet(BulletHitBulletEvent) + * onBulletHitBullet(BulletHitBulletEvent) + * @see BulletHitBulletEvent + * @see #getAllEvents() + */ + List getBulletHitBulletEvents(); + + /** + * Returns a vector containing all BulletHitEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (BulletHitEvent event: getBulletHitEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all BulletHitEvents currently in the robot's + * queue + * @see robocode.robotinterfaces.IBasicEvents#onBulletHit(BulletHitEvent) + * onBulletHit(BulletHitEvent) + * @see BulletHitEvent + * @see #getAllEvents() + */ + List getBulletHitEvents(); + + /** + * Returns a vector containing all HitByBulletEvents currently in the + * robot's queue. You might, for example, call this while processing + * another event. + *

+ * Example: + *

+	 *   for (HitByBulletEvent event : getHitByBulletEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all HitByBulletEvents currently in the + * robot's queue + * @see robocode.robotinterfaces.IBasicEvents#onHitByBullet(HitByBulletEvent) + * onHitByBullet(HitByBulletEvent) + * @see HitByBulletEvent + * @see #getAllEvents() + */ + List getHitByBulletEvents(); + + /** + * Returns a vector containing all HitRobotEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (HitRobotEvent event : getHitRobotEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all HitRobotEvents currently in the robot's + * queue + * @see robocode.robotinterfaces.IBasicEvents#onHitRobot(HitRobotEvent) + * onHitRobot(HitRobotEvent) + * @see HitRobotEvent + * @see #getAllEvents() + */ + List getHitRobotEvents(); + + /** + * Returns a vector containing all HitWallEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (HitWallEvent event : getHitWallEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all HitWallEvents currently in the robot's + * queue + * @see robocode.robotinterfaces.IBasicEvents#onHitWall(HitWallEvent) + * onHitWall(HitWallEvent) + * @see HitWallEvent + * @see #getAllEvents() + */ + List getHitWallEvents(); + + /** + * Returns a vector containing all RobotDeathEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (RobotDeathEvent event : getRobotDeathEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all RobotDeathEvents currently in the robot's + * queue + * @see robocode.robotinterfaces.IBasicEvents#onRobotDeath(RobotDeathEvent) + * onRobotDeath(RobotDeathEvent) + * @see RobotDeathEvent + * @see #getAllEvents() + */ + List getRobotDeathEvents(); + + /** + * Returns a vector containing all ScannedRobotEvents currently in the + * robot's queue. You might, for example, call this while processing another + * event. + *

+ * Example: + *

+	 *   for (ScannedRobotEvent event : getScannedRobotEvents()) {
+	 *       // do something with the event
+	 *   }
+	 * 
+ * + * @return a vector containing all ScannedRobotEvents currently in the + * robot's queue + * @see robocode.robotinterfaces.IBasicEvents#onScannedRobot(ScannedRobotEvent) + * onScannedRobot(ScannedRobotEvent) + * @see ScannedRobotEvent + * @see #getAllEvents() + */ + List getScannedRobotEvents(); + + /** + * Returns a file representing a data directory for the robot, which can be + * written to using {@link RobocodeFileOutputStream} or + * {@link RobocodeFileWriter}. + *

+ * The system will automatically create the directory for you, so you do not + * need to create it by yourself. + * + * @return a file representing the data directory for your robot + * @see #getDataFile(String) + * @see RobocodeFileOutputStream + * @see RobocodeFileWriter + */ + File getDataDirectory(); + + /** + * Returns a file in your data directory that you can write to using + * {@link RobocodeFileOutputStream} or {@link RobocodeFileWriter}. + *

+ * The system will automatically create the directory for you, so you do not + * need to create it by yourself. + *

+ * Please notice that the max. size of your data file is set to 200000 + * (~195 KB). + *

+ * See the {@code sample.SittingDuck} to see an example of how to use this + * method. + * + * @param filename the file name of the data file for your robot + * @return a file representing the data file for your robot + * @see #getDataDirectory() + * @see RobocodeFileOutputStream + * @see RobocodeFileWriter + */ + File getDataFile(String filename); + + /** + * Returns the data quota available in your data directory, i.e. the amount + * of bytes left in the data directory for the robot. + * + * @return the amount of bytes left in the robot's data directory + * @see #getDataDirectory() + * @see #getDataFile(String) + */ + long getDataQuotaAvailable(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IBasicRobotPeer.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IBasicRobotPeer.java new file mode 100644 index 0000000..103945f --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IBasicRobotPeer.java @@ -0,0 +1,738 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces.peer; + + +import robocode.*; +import robocode.robotinterfaces.IBasicEvents; + +import java.awt.*; + + +/** + * The basic robot peer for all robot types.

+ * + * NOTE: This is private interface. You should build any external component (or robot) + * based on it's current methods because it will change in the future.

+ * + * A robot peer is the object that deals with game mechanics and rules, and + * makes sure your robot abides by them. + * + * @see IStandardRobotPeer + * @see IAdvancedRobotPeer + * @see ITeamRobotPeer + * @see IJuniorRobotPeer + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IBasicRobotPeer { + + /** + * Returns the robot's name. + * + * @return the robot's name. + */ + String getName(); + + /** + * Returns the game time of the current round, where the time is equal to + * the current turn in the round. + *

+ * A battle consists of multiple rounds. + *

+ * Time is reset to 0 at the beginning of every round. + * + * @return the game time/turn of the current round. + */ + long getTime(); + + /** + * Returns the robot's current energy. + * + * @return the robot's current energy. + */ + double getEnergy(); + + /** + * Returns the X position of the robot. (0,0) is at the bottom left of the + * battlefield. + * + * @return the X position of the robot. + * @see #getY() + */ + double getX(); + + /** + * Returns the Y position of the robot. (0,0) is at the bottom left of the + * battlefield. + * + * @return the Y position of the robot. + * @see #getX() + */ + double getY(); + + /** + * Returns the velocity of the robot measured in pixels/turn. + *

+ * The maximum velocity of a robot is defined by + * {@link Rules#MAX_VELOCITY} (8 pixels / turn). + * + * @return the velocity of the robot measured in pixels/turn. + * @see Rules#MAX_VELOCITY + */ + double getVelocity(); + + /** + * Returns the direction that the robot's body is facing, in radians. + * The value returned will be between 0 and 2 * PI (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * PI / 2 means East, PI means South, and 3 * PI / 2 means West. + * + * @return the direction that the robot's body is facing, in radians. + * @see #getGunHeading() + * @see #getRadarHeading() + */ + double getBodyHeading(); + + /** + * Returns the direction that the robot's gun is facing, in radians. + * The value returned will be between 0 and 2 * PI (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * PI / 2 means East, PI means South, and 3 * PI / 2 means West. + * + * @return the direction that the robot's gun is facing, in radians. + * @see #getBodyHeading() + * @see #getRadarHeading() + */ + double getGunHeading(); + + /** + * Returns the direction that the robot's radar is facing, in radians. + * The value returned will be between 0 and 2 * PI (is excluded). + *

+ * Note that the heading in Robocode is like a compass, where 0 means North, + * PI / 2 means East, PI means South, and 3 * PI / 2 means West. + * + * @return the direction that the robot's radar is facing, in radians. + * @see #getBodyHeading() + * @see #getGunHeading() + */ + double getRadarHeading(); + + /** + * Returns the current heat of the gun. The gun cannot fire unless this is + * 0. (Calls to fire will succeed, but will not actually fire unless + * getGunHeat() == 0). + *

+ * The amount of gun heat generated when the gun is fired is + * 1 + (firePower / 5). Each turn the gun heat drops by the amount returned + * by {@link #getGunCoolingRate()}, which is a battle setup. + *

+ * Note that all guns are "hot" at the start of each round, where the gun + * heat is 3. + * + * @return the current gun heat + * @see #getGunCoolingRate() + * @see #setFire(double) + */ + double getGunHeat(); + + /** + * Returns the width of the current battlefield measured in pixels. + * + * @return the width of the current battlefield measured in pixels. + */ + double getBattleFieldWidth(); + + /** + * Returns the height of the current battlefield measured in pixels. + * + * @return the height of the current battlefield measured in pixels. + */ + double getBattleFieldHeight(); + + /** + * Returns how many opponents that are left in the current round. + * + * @return how many opponents that are left in the current round. + * @see #getNumSentries() + */ + int getOthers(); + + /** + * Returns how many sentry robots that are left in the current round. + * + * @return how many sentry robots that are left in the current round. + * @see #getOthers() + * @since 1.9.1.0 + */ + int getNumSentries(); + + /** + * Returns the number of rounds in the current battle. + * + * @return the number of rounds in the current battle. + * @see #getRoundNum() + */ + int getNumRounds(); + + /** + * Returns the number of the current round (0 to {@link #getNumRounds()} - 1) + * in the battle. + * + * @return the number of the current round in the battle (zero indexed). + * @see #getNumRounds() + */ + int getRoundNum(); + + /** + * Returns the sentry border size for a {@link robocode.BorderSentry BorderSentry} that defines the how + * far a BorderSentry is allowed to move from the border edges measured in units.
+ * Hence, the sentry border size defines the width/range of the border area surrounding the battlefield that + * BorderSentrys cannot leave (sentry robots robots must stay in the border area), but it also define the + * distance from the border edges where BorderSentrys are allowed/able to make damage to robots entering this + * border area. + * + * @return the border size in units/pixels. + * + * @since 1.9.0.0 + */ + int getSentryBorderSize(); + + /** + * Returns the rate at which the gun will cool down, i.e. the amount of heat + * the gun heat will drop per turn. + *

+ * The gun cooling rate is default 0.1 / turn, but can be changed by the + * battle setup. So don't count on the cooling rate being 0.1! + * + * @return the gun cooling rate + * @see #getGunHeat() + * @see #setFire(double) + */ + double getGunCoolingRate(); + + /** + * Returns the distance remaining in the robot's current move measured in + * pixels. + *

+ * This call returns both positive and negative values. Positive values + * means that the robot is currently moving forwards. Negative values means + * that the robot is currently moving backwards. If the returned value is 0, + * the robot currently stands still. + * + * @return the distance remaining in the robot's current move measured in + * pixels. + * @see #getBodyTurnRemaining() + * @see #getGunTurnRemaining() + * @see #getRadarTurnRemaining() + */ + double getDistanceRemaining(); + + /** + * Returns the angle remaining in the robot's turn, in radians. + *

+ * This call returns both positive and negative values. Positive values + * means that the robot is currently turning to the right. Negative values + * means that the robot is currently turning to the left. + * + * @return the angle remaining in the robot's turn, in radians + * @see #getDistanceRemaining() + * @see #getGunTurnRemaining() + * @see #getRadarTurnRemaining() + */ + double getBodyTurnRemaining(); + + /** + * Returns the angle remaining in the gun's turn, in radians. + *

+ * This call returns both positive and negative values. Positive values + * means that the gun is currently turning to the right. Negative values + * means that the gun is currently turning to the left. + * + * @return the angle remaining in the gun's turn, in radians + * @see #getDistanceRemaining() + * @see #getBodyTurnRemaining() + * @see #getRadarTurnRemaining() + */ + double getGunTurnRemaining(); + + /** + * Returns the angle remaining in the radar's turn, in radians. + *

+ * This call returns both positive and negative values. Positive values + * means that the radar is currently turning to the right. Negative values + * means that the radar is currently turning to the left. + * + * @return the angle remaining in the radar's turn, in radians + * @see #getDistanceRemaining() + * @see #getBodyTurnRemaining() + * @see #getGunTurnRemaining() + */ + double getRadarTurnRemaining(); + + /** + * Executes any pending actions, or continues executing actions that are + * in process. This call returns after the actions have been started. + *

+ * Note that advanced robots must call this function in order to + * execute pending set* calls like e.g. {@link + * IAdvancedRobotPeer#setMove(double) setMove(double)}, + * {@link IAdvancedRobotPeer#setFire(double) setFire(double)}, {@link + * IAdvancedRobotPeer#setTurnBody(double) setTurnBody(double)} etc. + * Otherwise, these calls will never get executed. + *

+ * In this example the robot will move while turning: + *

+	 *   setTurnBody(90);
+	 *   setMove(100);
+	 *   execute();
+	 * 

+ * while (getDistanceRemaining() > 0 && getTurnRemaining() > 0) { + * execute(); + * } + *

+ */ + void execute(); + + /** + * Immediately moves your robot forward or backward by distance measured in + * pixels. + *

+ * This call executes immediately, and does not return until it is complete, + * i.e. when the remaining distance to move is 0. + *

+ * If the robot collides with a wall, the move is complete, meaning that the + * robot will not move any further. If the robot collides with another + * robot, the move is complete if you are heading toward the other robot. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot is set to move forward, and negative + * values means that the robot is set to move backward. + *

+ * Example: + *

+	 *   // Move the robot 100 pixels forward
+	 *   ahead(100);
+	 * 

+ * // Afterwards, move the robot 50 pixels backward + * ahead(-50); + *

+ * + * @param distance the distance to move measured in pixels. + * If {@code distance} > 0 the robot is set to move forward. + * If {@code distance} < 0 the robot is set to move backward. + * If {@code distance} = 0 the robot will not move anywhere, but just + * finish its turn. + * @see robocode.robotinterfaces.IBasicEvents#onHitWall(robocode.HitWallEvent) + * @see robocode.robotinterfaces.IBasicEvents#onHitRobot(robocode.HitRobotEvent) + */ + void move(double distance); + + /** + * Immediately turns the robot's body to the right or left by radians. + * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the body's turn is 0. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot's body is set to turn right, and + * negative values means that the robot's body is set to turn left. + * If 0 is given as input, the robot's body will stop turning. + *

+ * Example: + *

+	 *   // Turn the robot's body 180 degrees to the right
+	 *   turnBody(Math.PI);
+	 * 

+ * // Afterwards, turn the robot's body 90 degrees to the left + * turnBody(-Math.PI / 2); + *

+ * + * @param radians the amount of radians to turn the robot's body. + * If {@code radians} > 0 the robot's body is set to turn right. + * If {@code radians} < 0 the robot's body is set to turn left. + * If {@code radians} = 0 the robot's body is set to stop turning. + * @see #turnGun(double) + * @see IStandardRobotPeer#turnRadar(double) turnRadar(double) + * @see #move(double) + */ + void turnBody(double radians); + + /** + * Immediately turns the robot's gun to the right or left by radians. + * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the gun's turn is 0. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot's gun is set to turn right, and + * negative values means that the robot's gun is set to turn left. + * If 0 is given as input, the robot's gun will stop turning. + *

+ * Example: + *

+	 *   // Turn the robot's gun 180 degrees to the right
+	 *   turnGun(Math.PI);
+	 * 

+ * // Afterwards, turn the robot's gun 90 degrees to the left + * turnGun(-Math.PI / 2); + *

+ * + * @param radians the amount of radians to turn the robot's gun. + * If {@code radians} > 0 the robot's gun is set to turn right. + * If {@code radians} < 0 the robot's gun is set to turn left. + * If {@code radians} = 0 the robot's gun is set to stop turning. + * @see #turnBody(double) + * @see IStandardRobotPeer#turnRadar(double) turnRadar(double) + * @see #move(double) + */ + void turnGun(double radians); + + /** + * Immediately fires a bullet. The bullet will travel in the direction the + * gun is pointing. + *

+ * The specified bullet power is an amount of energy that will be taken from + * the robot's energy. Hence, the more power you want to spend on the + * bullet, the more energy is taken from your robot. + *

+ * The bullet will do (4 * power) damage if it hits another robot. If power + * is greater than 1, it will do an additional 2 * (power - 1) damage. + * You will get (3 * power) back if you hit the other robot. You can call + * {@link Rules#getBulletDamage(double)} for getting the damage that a + * bullet with a specific bullet power will do. + *

+ * The specified bullet power should be between + * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. + *

+ * Note that the gun cannot fire if the gun is overheated, meaning that + * {@link #getGunHeat()} returns a value > 0. + *

+ * A event is generated when the bullet hits a robot + * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another + * bullet ({@link BulletHitBulletEvent}). + *

+ * Example: + *

+	 *   // Fire a bullet with maximum power if the gun is ready
+	 *   if (getGunHeat() == 0) {
+	 *       Bullet bullet = fire(Rules.MAX_BULLET_POWER);
+	 * 

+ * // Get the velocity of the bullet + * if (bullet != null) { + * double bulletVelocity = bullet.getVelocity(); + * } + * } + *

+ * + * @param power the amount of energy given to the bullet, and subtracted + * from the robot's energy. + * @return a {@link Bullet} that contains information about the bullet if it + * was actually fired, which can be used for tracking the bullet after it + * has been fired. If the bullet was not fired, {@code null} is returned. + * @see #setFire(double) + * @see Bullet + * @see #getGunHeat() + * @see #getGunCoolingRate() + * @see robocode.robotinterfaces.IBasicEvents#onBulletHit(BulletHitEvent) + * onBulletHit(BulletHitEvent) + * @see robocode.robotinterfaces.IBasicEvents#onBulletHitBullet(BulletHitBulletEvent) + * onBulletHitBullet(BulletHitBulletEvent) + * @see robocode.robotinterfaces.IBasicEvents#onBulletMissed(BulletMissedEvent) + * onBulletMissed(BulletMissedEvent) + */ + Bullet fire(double power); + + /** + * Sets the gun to fire a bullet when the next execution takes place. + * The bullet will travel in the direction the gun is pointing. + *

+ * This call returns immediately, and will not execute until you call + * execute() or take an action that executes. + *

+ * The specified bullet power is an amount of energy that will be taken from + * the robot's energy. Hence, the more power you want to spend on the + * bullet, the more energy is taken from your robot. + *

+ * The bullet will do (4 * power) damage if it hits another robot. If power + * is greater than 1, it will do an additional 2 * (power - 1) damage. + * You will get (3 * power) back if you hit the other robot. You can call + * {@link Rules#getBulletDamage(double)} for getting the damage that a + * bullet with a specific bullet power will do. + *

+ * The specified bullet power should be between + * {@link Rules#MIN_BULLET_POWER} and {@link Rules#MAX_BULLET_POWER}. + *

+ * Note that the gun cannot fire if the gun is overheated, meaning that + * {@link #getGunHeat()} returns a value > 0. + *

+ * A event is generated when the bullet hits a robot + * ({@link BulletHitEvent}), wall ({@link BulletMissedEvent}), or another + * bullet ({@link BulletHitBulletEvent}). + *

+ * Example: + *

+	 *   Bullet bullet = null;
+	 * 

+ * // Fire a bullet with maximum power if the gun is ready + * if (getGunHeat() == 0) { + * bullet = setFireBullet(Rules.MAX_BULLET_POWER); + * } + * ... + * execute(); + * ... + * // Get the velocity of the bullet + * if (bullet != null) { + * double bulletVelocity = bullet.getVelocity(); + * } + *

+ * + * @param power the amount of energy given to the bullet, and subtracted + * from the robot's energy. + * @return a {@link Bullet} that contains information about the bullet if it + * was actually fired, which can be used for tracking the bullet after it + * has been fired. If the bullet was not fired, {@code null} is returned. + * @see #fire(double) + * @see Bullet + * @see #getGunHeat() + * @see #getGunCoolingRate() + * @see robocode.robotinterfaces.IBasicEvents#onBulletHit(BulletHitEvent) + * onBulletHit(BulletHitEvent) + * @see robocode.robotinterfaces.IBasicEvents#onBulletHitBullet(BulletHitBulletEvent) + * onBulletHitBullet(BulletHitBulletEvent) + * @see robocode.robotinterfaces.IBasicEvents#onBulletMissed(BulletMissedEvent) + * onBulletMissed(BulletMissedEvent) + */ + Bullet setFire(double power); + + /** + * Sets the color of the robot's body. + *

+ * A {@code null} indicates the default (blue) color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 * 

+ * public void run() { + * setBodyColor(Color.BLACK); + * ... + * } + *

+ * + * @param color the new body color + * @see #setGunColor(Color) + * @see #setRadarColor(Color) + * @see #setBulletColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.2 + */ + void setBodyColor(Color color); + + /** + * Sets the color of the robot's gun. + *

+ * A {@code null} indicates the default (blue) color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 * 

+ * public void run() { + * setGunColor(Color.RED); + * ... + * } + *

+ * + * @param color the new gun color + * @see #setBodyColor(Color) + * @see #setRadarColor(Color) + * @see #setBulletColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.2 + */ + void setGunColor(Color color); + + /** + * Sets the color of the robot's radar. + *

+ * A {@code null} indicates the default (blue) color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 * 

+ * public void run() { + * setRadarColor(Color.YELLOW); + * ... + * } + *

+ * + * @param color the new radar color + * @see #setBodyColor(Color) + * @see #setGunColor(Color) + * @see #setBulletColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.2 + */ + void setRadarColor(Color color); + + /** + * Sets the color of the robot's bullets. + *

+ * A {@code null} indicates the default white color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 * 

+ * public void run() { + * setBulletColor(Color.GREEN); + * ... + * } + *

+ * + * @param color the new bullet color + * @see #setBodyColor(Color) + * @see #setGunColor(Color) + * @see #setRadarColor(Color) + * @see #setScanColor(Color) + * @see Color + * @since 1.1.2 + */ + void setBulletColor(Color color); + + /** + * Sets the color of the robot's scan arc. + *

+ * A {@code null} indicates the default (blue) color. + *

+ *

+	 * Example:
+	 *   // Don't forget to import java.awt.Color at the top...
+	 *   import java.awt.Color;
+	 *   ...
+	 * 

+ * public void run() { + * setScanColor(Color.WHITE); + * ... + * } + *

+ * + * @param color the new scan arc color + * @see #setBodyColor(Color) + * @see #setGunColor(Color) + * @see #setRadarColor(Color) + * @see #setBulletColor(Color) + * @see Color + * @since 1.1.2 + */ + void setScanColor(Color color); + + /** + * This call must be made from a robot call to inform the game + * that the robot made a {@code get*} call like e.g. {@link #getX()} or + * {@link #getVelocity()}. + *

+ * This method is used by the game to determine if the robot is inactive or + * not. Note: You should only make this call once in a {@code get*} method! + * + * @see #setCall() + */ + void getCall(); + + /** + * This call must be made from a robot call to inform the game + * that the robot made a {@code set*} call like e.g. {@link + * #setFire(double)} or {@link #setBodyColor(Color)}. + *

+ * This method is used by the game to determine if the robot is inactive or + * not. Note: You should only make this call once in a {@code set*} method! + * + * @see #getCall() + */ + void setCall(); + + /** + * Returns a graphics context used for painting graphical items for the robot. + *

+ * This method is very useful for debugging your robot. + *

+ * Note that the robot will only be painted if the "Paint" is enabled on the + * robot's console window; otherwise the robot will never get painted (the + * reason being that all robots might have graphical items that must be + * painted, and then you might not be able to tell what graphical items that + * have been painted for your robot). + *

+ * Also note that the coordinate system for the graphical context where you + * paint items fits for the Robocode coordinate system where (0, 0) is at + * the bottom left corner of the battlefield, where X is towards right and Y + * is upwards. + * + * @return a graphics context used for painting graphical items for the robot. + * @see robocode.robotinterfaces.IPaintEvents#onPaint(Graphics2D) + * @since 1.6.1 + */ + Graphics2D getGraphics(); + + /** + * Sets the debug property with the specified key to the specified value. + *

+ * This method is very useful when debugging or reviewing your robot as you + * will be able to see this property displayed in the robot console for your + * robots under the Debug Properties tab page. + * + * @param key the name/key of the debug property. + * @param value the new value of the debug property, where {@code null} or + * the empty string is used for removing this debug property. + * @since 1.6.2 + */ + void setDebugProperty(String key, String value); + + /** + * Rescan for other robots. This method is called automatically by the game, + * as long as the robot is moving, turning its body, turning its gun, or + * turning its radar. + *

+ * Rescan will cause {@link IBasicEvents#onScannedRobot(ScannedRobotEvent) + * onScannedRobot(ScannedRobotEvent)} to be called if you see a robot. + *

+ * There are 2 reasons to call {@code rescan()} manually: + *

    + *
  1. You want to scan after you stop moving. + *
  2. You want to interrupt the {@code onScannedRobot} event. This is more + * likely. If you are in {@code onScannedRobot} and call {@code scan()}, + * and you still see a robot, then the system will interrupt your + * {@code onScannedRobot} event immediately and start it from the top. + *
+ *

+ * This call executes immediately. + * + * @see IBasicEvents#onScannedRobot(ScannedRobotEvent) + * onScannedRobot(ScannedRobotEvent) + * @see ScannedRobotEvent + * + * @since 1.7.2 + */ + void rescan(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IJuniorRobotPeer.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IJuniorRobotPeer.java new file mode 100644 index 0000000..300ece1 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IJuniorRobotPeer.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces.peer; + + +/** + * The junior robot peer for junior robot types like {@link robocode.JuniorRobot}. + *

+ * A robot peer is the object that deals with game mechanics and rules, and + * makes sure your robot abides by them. + * + * @see IBasicRobotPeer + * @see IStandardRobotPeer + * @see IAdvancedRobotPeer + * @see ITeamRobotPeer + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IJuniorRobotPeer extends IBasicRobotPeer { + + /** + * Moves this robot forward or backwards by pixels and turns this robot + * right or left by degrees at the same time. The robot will move in a curve + * that follows a perfect circle, and the moving and turning will end at + * exactly the same time. + *

+ * Note that the max. velocity and max. turn rate is automatically adjusted, + * which means that the robot will move slower the sharper the turn is + * compared to the distance. + *

+ * Note that both positive and negative values can be given as input: + *

    + *
  • If the {@code distance} parameter is set to a positive value, it + * means that the robot is set to move forward, and a negative value means + * that the robot is set to move backward. If set to 0, the robot will not + * move, but will be able to turn. + *
  • If the {@code radians} parameter is set to a positive value, it means + * that the robot is set to turn to the right, and a negative value means + * that the robot is set to turn to the left. If set to 0, the robot will + * not turn, but will be able to move. + *
+ * + * @param distance the distance to move measured in pixels. + * If {@code distance} > 0 the robot is set to move forward. + * If {@code distance} < 0 the robot is set to move backward. + * If {@code distance} = 0 the robot will not move anywhere, but just + * finish its turn. + * @param radians the amount of radians to turn the robot's body. + * If {@code radians} > 0 the robot's body is set to turn right. + * If {@code radians} < 0 the robot's body is set to turn left. + * If {@code radians} = 0 the robot's body is set to stop turning. + * @see IBasicRobotPeer#move(double) move(double) + * @see IBasicRobotPeer#turnBody(double) turnBody(double) + * @see IBasicRobotPeer#getBodyHeading() getBodyHeading() + * @see IBasicRobotPeer#getX() getX() + * @see IBasicRobotPeer#getY() getY() + */ + void turnAndMove(double distance, double radians); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IStandardRobotPeer.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IStandardRobotPeer.java new file mode 100644 index 0000000..dd29d3c --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/IStandardRobotPeer.java @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces.peer; + + +/** + * The standard robot peer for standard robot types like {@link robocode.Robot}, + * {@link robocode.AdvancedRobot}, and {@link robocode.TeamRobot}. + *

+ * A robot peer is the object that deals with game mechanics and rules, and + * makes sure your robot abides by them. + * + * @see IBasicRobotPeer + * @see IAdvancedRobotPeer + * @see ITeamRobotPeer + * @see IJuniorRobotPeer + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6 + */ +public interface IStandardRobotPeer extends IBasicRobotPeer { + + /** + * Immediately stops all movement, and saves it for a call to + * {@link #resume()}. If there is already movement saved from a previous + * stop, you can overwrite it by calling {@code stop(true)}. + * + * @param overwrite If there is already movement saved from a previous stop, + * you can overwrite it by calling {@code stop(true)}. + * @see #resume() + */ + void stop(boolean overwrite); + + /** + * Immediately resumes the movement you stopped by {@link #stop(boolean)}, + * if any. + *

+ * This call executes immediately, and does not return until it is complete. + * + * @see #stop(boolean) + */ + void resume(); + + /** + * Immediately turns the robot's radar to the right or left by radians. + * This call executes immediately, and does not return until it is complete, + * i.e. when the angle remaining in the radar's turn is 0. + *

+ * Note that both positive and negative values can be given as input, where + * positive values means that the robot's radar is set to turn right, and + * negative values means that the robot's radar is set to turn left. + * If 0 is given as input, the robot's radar will stop turning. + *

+ * Example: + *

+	 *   // Turn the robot's radar 180 degrees to the right
+	 *   turnRadar(Math.PI);
+	 *
+	 *   // Afterwards, turn the robot's radar 90 degrees to the left
+	 *   turnRadar(-Math.PI / 2);
+	 * 
+ * + * @param radians the amount of radians to turn the robot's radar. + * If {@code radians} > 0 the robot's radar is set to turn right. + * If {@code radians} < 0 the robot's radar is set to turn left. + * If {@code radians} = 0 the robot's radar is set to stop turning. + * @see #turnBody(double) + * @see #turnGun(double) + * @see #move(double) + */ + void turnRadar(double radians); + + /** + * Sets the gun to turn independent from the robot's turn. + *

+ * Ok, so this needs some explanation: The gun is mounted on the robot's + * body. So, normally, if the robot turns 90 degrees to the right, then the + * gun will turn with it as it is mounted on top of the robot's body. To + * compensate for this, you can call {@code setAdjustGunForBodyTurn(true)}. + * When this is set, the gun will turn independent from the robot's turn, + * i.e. the gun will compensate for the robot's body turn. + *

+ * Note: This method is additive until you reach the maximum the gun can + * turn. The "adjust" is added to the amount you set for turning the robot, + * then capped by the physics of the game. If you turn infinite, then the + * adjust is ignored (and hence overridden). + *

+ * Example, assuming both the robot and gun start out facing up (0 degrees): + *

+	 *   // Set gun to turn with the robot's turn
+	 *   setAdjustGunForBodyTurn(false); // This is the default
+	 *   turnBodyRight(Math.PI / 2);
+	 *   // At this point, both the robot and gun are facing right (90 degrees)
+	 *   turnBodyLeft(Math.PI / 2);
+	 *   // Both are back to 0 degrees
+	 *
+	 *   -- or --
+	 *
+	 *   // Set gun to turn independent from the robot's turn
+	 *   setAdjustGunForBodyTurn(true);
+	 *   turnBodyRight(Math.PI / 2);
+	 *   // At this point, the robot is facing right (90 degrees), but the gun is still facing up.
+	 *   turnBodyLeft(Math.PI / 2);
+	 *   // Both are back to 0 degrees.
+	 * 
+ *

+ * Note: The gun compensating this way does count as "turning the gun". + * See {@link #setAdjustRadarForGunTurn(boolean)} for details. + * + * @param independent {@code true} if the gun must turn independent from the + * robot's turn; {@code false} if the gun must turn with the robot's turn. + * @see #setAdjustRadarForGunTurn(boolean) + */ + void setAdjustGunForBodyTurn(boolean independent); + + /** + * Sets the radar to turn independent from the gun's turn. + *

+ * Ok, so this needs some explanation: The radar is mounted on the robot's + * gun. So, normally, if the gun turns 90 degrees to the right, then the + * radar will turn with it as it is mounted on top of the gun. To compensate + * for this, you can call {@code setAdjustRadarForGunTurn(true)}. When this + * is set, the radar will turn independent from the robot's turn, i.e. the + * radar will compensate for the gun's turn. + *

+ * Note: This method is additive until you reach the maximum the radar can + * turn. The "adjust" is added to the amount you set for turning the robot, + * then capped by the physics of the game. If you turn infinite, then the + * adjust is ignored (and hence overridden). + *

+ * Example, assuming both the gun and radar start out facing up (0 degrees): + *

+	 *   // Set radar to turn with the gun's turn
+	 *   setAdjustRadarForGunTurn(false); // This is the default
+	 *   turnGunRight(Math.PI / 2);
+	 *   // At this point, both the radar and gun are facing right (90 degrees);
+	 *
+	 *   -- or --
+	 *
+	 *   // Set radar to turn independent from the gun's turn
+	 *   setAdjustRadarForGunTurn(true);
+	 *   turnGunRight(Math.PI / 2);
+	 *   // At this point, the gun is facing right (90 degrees), but the radar is still facing up.
+	 * 
+ * Note: Calling {@code setAdjustRadarForGunTurn(boolean)} will + * automatically call {@link #setAdjustRadarForBodyTurn(boolean)} with the + * same value, unless you have already called it earlier. This behavior is + * primarily for backward compatibility with older Robocode robots. + * + * @param independent {@code true} if the radar must turn independent from + * the gun's turn; {@code false} if the radar must turn with the gun's + * turn. + * @see #setAdjustRadarForBodyTurn(boolean) + * @see #setAdjustGunForBodyTurn(boolean) + */ + void setAdjustRadarForGunTurn(boolean independent); + + /** + * Sets the radar to turn independent from the robot's turn. + *

+ * Ok, so this needs some explanation: The radar is mounted on the gun, and + * the gun is mounted on the robot's body. So, normally, if the robot turns + * 90 degrees to the right, the gun turns, as does the radar. Hence, if the + * robot turns 90 degrees to the right, then the gun and radar will turn + * with it as the radar is mounted on top of the gun. To compensate for + * this, you can call {@code setAdjustRadarForBodyTurn(true)}. When this is + * set, the radar will turn independent from the robot's turn, i.e. the + * radar will compensate for the robot's turn. + *

+ * Note: This method is additive until you reach the maximum the radar can + * turn. The "adjust" is added to the amount you set for turning the gun, + * then capped by the physics of the game. If you turn infinite, then the + * adjust is ignored (and hence overridden). + *

+ * Example, assuming the robot, gun, and radar all start out facing up (0 + * degrees): + *

+	 *   // Set radar to turn with the robots's turn
+	 *   setAdjustRadarForBodyTurn(false); // This is the default
+	 *   turnRight(Math.PI / 2);
+	 *   // At this point, the body, gun, and radar are all facing right (90 degrees);
+	 *
+	 *   -- or --
+	 *
+	 *   // Set radar to turn independent from the robot's turn
+	 *   setAdjustRadarForBodyTurn(true);
+	 *   turnRight(Math.PI / 2);
+	 *   // At this point, the robot and gun are facing right (90 degrees), but the radar is still facing up.
+	 * 
+ * + * @param independent {@code true} if the radar must turn independent from + * the robots's turn; {@code false} if the radar must turn with the robot's + * turn. + * @see #setAdjustGunForBodyTurn(boolean) + * @see #setAdjustRadarForGunTurn(boolean) + */ + void setAdjustRadarForBodyTurn(boolean independent); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/ITeamRobotPeer.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/ITeamRobotPeer.java new file mode 100644 index 0000000..ddbb2ba --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/ITeamRobotPeer.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.robotinterfaces.peer; + + +import robocode.MessageEvent; + +import java.io.IOException; +import java.io.Serializable; +import java.util.List; + + +public interface ITeamRobotPeer extends IAdvancedRobotPeer { + + + String[] getTeammates(); + boolean isTeammate(String name); + + void broadcastMessage(Serializable message) throws IOException; + + void sendMessage(String name, Serializable message) throws IOException; + + /** + * Returns a vector containing all MessageEvents currently in the robot's + * queue. You might, for example, call this while processing another event. + *

+ * Example: + *

+	 *   for (MessageEvent e : getMessageEvents()) {
+	 *      // do something with e
+	 *   }
+	 * 
+ * + * @return a vector containing all MessageEvents currently in the robot's + * queue + * @see robocode.robotinterfaces.ITeamEvents#onMessageReceived(MessageEvent) + * onMessageReceived(MessageEvent) + * @see MessageEvent + * @since 1.2.6 + */ + List getMessageEvents(); +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/package-info.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/package-info.java new file mode 100644 index 0000000..a0d2b8f --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/robotinterfaces/peer/package-info.java @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + +/** + * Robot peers available for implementing new robot types based on the Robot Interfaces. + */ +package robocode.robotinterfaces.peer; diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/util/Utils.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/util/Utils.java new file mode 100644 index 0000000..2b0f87a --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/util/Utils.java @@ -0,0 +1,178 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode.util; + + +import robocode.control.RandomFactory; + +import static java.lang.Math.PI; +import java.util.Random; + + +/** + * Utility class that provide methods for normalizing angles. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class Utils { + + private final static double TWO_PI = 2 * PI; + private final static double THREE_PI_OVER_TWO = 3 * PI / 2; + private final static double PI_OVER_TWO = PI / 2; + public static final double NEAR_DELTA = .00001; + + // Hide the default constructor as this class only provides static method + private Utils() {} + + /** + * Normalizes an angle to an absolute angle. + * The normalized angle will be in the range from 0 to 2*PI, where 2*PI + * itself is not included. + * + * @param angle the angle to normalize + * @return the normalized angle that will be in the range of [0,2*PI[ + */ + public static double normalAbsoluteAngle(double angle) { + return (angle %= TWO_PI) >= 0 ? angle : (angle + TWO_PI); + } + + /** + * Normalizes an angle to an absolute angle. + * The normalized angle will be in the range from 0 to 360, where 360 + * itself is not included. + * + * @param angle the angle to normalize + * @return the normalized angle that will be in the range of [0,360[ + */ + public static double normalAbsoluteAngleDegrees(double angle) { + return (angle %= 360) >= 0 ? angle : (angle + 360); + } + + /** + * Normalizes an angle to a relative angle. + * The normalized angle will be in the range from -PI to PI, where PI + * itself is not included. + * + * @param angle the angle to normalize + * @return the normalized angle that will be in the range of [-PI,PI[ + */ + public static double normalRelativeAngle(double angle) { + return (angle %= TWO_PI) >= 0 ? (angle < PI) ? angle : angle - TWO_PI : (angle >= -PI) ? angle : angle + TWO_PI; + } + + /** + * Normalizes an angle to a relative angle. + * The normalized angle will be in the range from -180 to 180, where 180 + * itself is not included. + * + * @param angle the angle to normalize + * @return the normalized angle that will be in the range of [-180,180[ + */ + public static double normalRelativeAngleDegrees(double angle) { + return (angle %= 360) >= 0 ? (angle < 180) ? angle : angle - 360 : (angle >= -180) ? angle : angle + 360; + } + + /** + * Normalizes an angle to be near an absolute angle. + * The normalized angle will be in the range from 0 to 360, where 360 + * itself is not included. + * If the normalized angle is near to 0, 90, 180, 270 or 360, that + * angle will be returned. The {@link #isNear(double, double) isNear} + * method is used for defining when the angle is near one of angles listed + * above. + * + * @param angle the angle to normalize + * @return the normalized angle that will be in the range of [0,360[ + * @see #normalAbsoluteAngle(double) + * @see #isNear(double, double) + */ + public static double normalNearAbsoluteAngleDegrees(double angle) { + angle = (angle %= 360) >= 0 ? angle : (angle + 360); + + if (isNear(angle, 180)) { + return 180; + } else if (angle < 180) { + if (isNear(angle, 0)) { + return 0; + } else if (isNear(angle, 90)) { + return 90; + } + } else { + if (isNear(angle, 270)) { + return 270; + } else if (isNear(angle, 360)) { + return 0; + } + } + return angle; + } + + /** + * Normalizes an angle to be near an absolute angle. + * The normalized angle will be in the range from 0 to 2*PI, where 2*PI + * itself is not included. + * If the normalized angle is near to 0, PI/2, PI, 3*PI/2 or 2*PI, that + * angle will be returned. The {@link #isNear(double, double) isNear} + * method is used for defining when the angle is near one of angles listed + * above. + * + * @param angle the angle to normalize + * @return the normalized angle that will be in the range of [0,2*PI[ + * @see #normalAbsoluteAngle(double) + * @see #isNear(double, double) + */ + public static double normalNearAbsoluteAngle(double angle) { + angle = (angle %= TWO_PI) >= 0 ? angle : (angle + TWO_PI); + + if (isNear(angle, PI)) { + return PI; + } else if (angle < PI) { + if (isNear(angle, 0)) { + return 0; + } else if (isNear(angle, PI_OVER_TWO)) { + return PI_OVER_TWO; + } + } else { + if (isNear(angle, THREE_PI_OVER_TWO)) { + return THREE_PI_OVER_TWO; + } else if (isNear(angle, TWO_PI)) { + return 0; + } + } + return angle; + } + + /** + * Tests if the two {@code double} values are near to each other. + * It is recommended to use this method instead of testing if the two + * doubles are equal using an this expression: {@code value1 == value2}. + * The reason being, that this expression might never become + * {@code true} due to the precision of double values. + * Whether or not the specified doubles are near to each other is defined by + * the following expression: + * {@code (Math.abs(value1 - value2) < .00001)} + * + * @param value1 the first double value + * @param value2 the second double value + * @return {@code true} if the two doubles are near to each other; + * {@code false} otherwise. + */ + public static boolean isNear(double value1, double value2) { + return (Math.abs(value1 - value2) < NEAR_DELTA); + } + + /** + * Returns random number generator. It might be configured for repeatable behavior by setting -DRANDOMSEED option. + * + * @return random number generator + */ + public static Random getRandom() { + return RandomFactory.getRandom(); + } +} diff --git a/代码/workspace_robo4/robocode.api/src/main/java/robocode/util/package-info.java b/代码/workspace_robo4/robocode.api/src/main/java/robocode/util/package-info.java new file mode 100644 index 0000000..03e6838 --- /dev/null +++ b/代码/workspace_robo4/robocode.api/src/main/java/robocode/util/package-info.java @@ -0,0 +1,13 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ + +/** + * Utility classes that can be used when writing robots. + * Kept for compatibility with legacy robots. + */ +package robocode.util; diff --git a/代码/workspace_robo4/robocode.battle/.classpath b/代码/workspace_robo4/robocode.battle/.classpath new file mode 100644 index 0000000..3ae3e5a --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.battle/.project b/代码/workspace_robo4/robocode.battle/.project new file mode 100644 index 0000000..ef333f5 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/.project @@ -0,0 +1,19 @@ + + + robocode.battle + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + robocode.core + robocode.host + robocode.repository + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.battle/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.battle/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.battle/pom.xml b/代码/workspace_robo4/robocode.battle/pom.xml new file mode 100644 index 0000000..d0df636 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + robocode.battle + Robocode Battle + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + net.sf.robocode + robocode.core + ${project.version} + + + net.sf.robocode + robocode.host + ${project.version} + + + net.sf.robocode + robocode.repository + ${project.version} + runtime + + + diff --git a/代码/workspace_robo4/robocode.battle/robocode.battle.iml b/代码/workspace_robo4/robocode.battle/robocode.battle.iml new file mode 100644 index 0000000..5fa5b24 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/robocode.battle.iml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BaseBattle.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BaseBattle.java new file mode 100644 index 0000000..eded632 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BaseBattle.java @@ -0,0 +1,475 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +import net.sf.robocode.battle.events.BattleEventDispatcher; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.URLJarCollector; +import static net.sf.robocode.io.Logger.logError; +import static net.sf.robocode.io.Logger.logMessage; +import net.sf.robocode.settings.ISettingsManager; +import robocode.BattleRules; +import robocode.control.events.BattlePausedEvent; +import robocode.control.events.BattleResumedEvent; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; + + +/** + * @author Pavel Savara (original) + */ +public abstract class BaseBattle implements IBattle, Runnable { + + private final static int MAX_TPS = 10000; + + // Maximum turns to display the battle when battle ended + protected final static int TURNS_DISPLAYED_AFTER_ENDING = 30; + + // Objects we use + private Thread battleThread; + IBattleManager battleManager; + protected final BattleEventDispatcher eventDispatcher; + private final ISettingsManager properties; + + // rules + protected BattleRules battleRules; + + // Current round items + private int roundNum; + protected int currentTime; + protected int totalTurns; + + protected int endTimer; + + // TPS (turns per second) calculation stuff + private int tps; + private long turnStartTime; + private long measuredTurnStartTime; + private int measuredTurnCounter; + + // Battle state + private final AtomicBoolean isRunning = new AtomicBoolean(false); + protected boolean isAborted; + + // Battle control + protected boolean isPaused; + private int stepCount; + private boolean runBackward; + private boolean roundOver; + private final Queue pendingCommands = new ConcurrentLinkedQueue(); + + protected BaseBattle(ISettingsManager properties, IBattleManager battleManager, BattleEventDispatcher eventDispatcher) { + stepCount = 0; + + this.properties = properties; + this.eventDispatcher = eventDispatcher; + + this.battleManager = battleManager; + } + + public void setBattleThread(Thread newBattleThread) { + battleThread = newBattleThread; + } + + /** + * Sets the roundNum. + * + * @param roundNum The roundNum to set + */ + public void setRoundNum(int roundNum) { + this.roundNum = roundNum; + } + + /** + * Gets the roundNum. + * + * @return Returns a int + */ + public int getRoundNum() { + return roundNum; + } + + public int getNumRounds() { + return battleRules.getNumRounds(); + } + + public Thread getBattleThread() { + return battleThread; + } + + public int getTime() { + return currentTime; + } + + public int getTotalTurns() { + return totalTurns; + } + + public boolean isLastRound() { + return (roundNum + 1 == getNumRounds()); + } + + public int getTPS() { + return tps; + } + + /** + * Informs on whether the battle is running or not. + * + * @return true if the battle is running, false otherwise + */ + public boolean isRunning() { + return isRunning.get(); + } + + /** + * Informs on whether the battle is aborted or not. + * + * @return true if the battle is aborted, false otherwise + */ + public boolean isAborted() { + return isAborted; + } + + public void cleanup() { + battleRules = null; + if (pendingCommands != null) { + pendingCommands.clear(); + // don't pendingCommands = null; + } + URLJarCollector.enableGc(true); + URLJarCollector.gc(); + } + + public void waitTillStarted() { + synchronized (isRunning) { + while (!isRunning.get()) { + try { + isRunning.wait(); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + + return; // Break out + } + } + } + } + + public void waitTillOver() { + synchronized (isRunning) { + while (isRunning.get()) { + try { + isRunning.wait(); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + + return; // Break out + } + } + } + } + + /** + * When an object implementing interface {@code Runnable} is used + * to create a thread, starting the thread causes the object's + * {@code run()} method to be called in that separately executing + * thread. + *

+ * The general contract of the method {@code run()} is that it may + * take any action whatsoever. + * + * @see java.lang.Thread#run() + */ + public void run() { + try { + initializeBattle(); + + while (!isAborted && roundNum < getNumRounds()) { + try { + preloadRound(); + initializeRound(); + runRound(); + } catch (Exception e) { + logError("Exception running a battle round", e); + isAborted = true; + } finally { + finalizeRound(); + cleanupRound(); + } + roundNum++; + } + } finally { + finalizeBattle(); + cleanup(); + } + } + + protected void initializeBattle() { + URLJarCollector.enableGc(false); + roundNum = 0; + totalTurns = 0; + + // Notify that the battle is now running + synchronized (isRunning) { + isRunning.set(true); + isRunning.notifyAll(); + } + } + + protected void finalizeBattle() { + // Notify that the battle is over + synchronized (isRunning) { + isRunning.set(false); + isRunning.notifyAll(); + } + } + + protected void preloadRound() { + logMessage("----------------------"); + Logger.logMessage("Round " + (roundNum + 1) + " initializing..", false); + } + + protected void initializeRound() { + logMessage(""); + logMessage("Let the games begin!"); + + roundOver = false; + endTimer = 0; + currentTime = 0; + } + + private void runRound() { + + while (!roundOver) { + processCommand(); + + if (shouldPause() && !shouldStep()) { + shortSleep(); + continue; + } + + initializeTurn(); + + runTurn(); + + roundOver = isRoundOver(); + + finalizeTurn(); + } + } + + protected boolean isRoundOver() { + return (endTimer > 5 * TURNS_DISPLAYED_AFTER_ENDING); + } + + protected void finalizeRound() {} + + private void cleanupRound() { + logMessage("Round " + (roundNum + 1) + " cleaning up."); + } + + protected void initializeTurn() { + turnStartTime = System.nanoTime(); + } + + protected void runTurn() { + if (runBackward) { + currentTime--; + totalTurns--; + if (currentTime == 0 && !isPaused) { + pauseImpl(); + } + } else { + currentTime++; + totalTurns++; + } + } + + protected void shutdownTurn() { + endTimer++; + } + + protected void finalizeTurn() { + synchronizeTPS(); + calculateTPS(); + } + + private void synchronizeTPS() { + // Let the battle sleep is the GUI is enabled and is not minimized + // in order to keep the desired TPS + + if (battleManager.isManagedTPS()) { + long delay = 0; + + if (!isAborted() && endTimer < TURNS_DISPLAYED_AFTER_ENDING) { + int desiredTPS = properties.getOptionsBattleDesiredTPS(); + + if (desiredTPS < MAX_TPS) { + long deltaTime = System.nanoTime() - turnStartTime; + + delay = Math.max(1000000000 / desiredTPS - deltaTime, 0); + } + } + if (delay > 500000) { // sleep granularity is worse than 500000 + try { + Thread.sleep(delay / 1000000, (int) (delay % 1000000)); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + } + } + } + } + + private void calculateTPS() { + // Calculate the current turns per second (TPS) + + if (measuredTurnCounter++ == 0) { + measuredTurnStartTime = turnStartTime; + } + + long deltaTime = System.nanoTime() - measuredTurnStartTime; + + if (deltaTime / 500000000 >= 1) { + tps = (int) (measuredTurnCounter * 1000000000L / deltaTime); + measuredTurnCounter = 0; + } + } + + private boolean shouldPause() { + return (isPaused && !isAborted); + } + + private boolean shouldStep() { + if (stepCount > 0) { + stepCount--; + return true; + } + return false; + } + + // -------------------------------------------------------------------------- + // Processing and maintaining robot and battle controls + // -------------------------------------------------------------------------- + + protected void sendCommand(Command command) { + pendingCommands.add(command); + } + + private void processCommand() { + Command command = pendingCommands.poll(); + + while (command != null) { + try { + command.execute(); + } catch (Exception e) { + logError(e); + } + command = pendingCommands.poll(); + } + } + + public void stop(boolean waitTillEnd) { + sendCommand(new AbortCommand()); + + if (waitTillEnd) { + waitTillOver(); + } + } + + public void pause() { + sendCommand(new PauseCommand()); + } + + public void resume() { + sendCommand(new ResumeCommand()); + } + + public void step() { + sendCommand(new StepCommand()); + } + + protected void stepBack() { + sendCommand(new StepBackCommand()); + } + + private class PauseCommand extends Command { + public void execute() { + pauseImpl(); + } + + } + + private void pauseImpl() { + isPaused = true; + stepCount = 0; + eventDispatcher.onBattlePaused(new BattlePausedEvent()); + } + + private class ResumeCommand extends Command { + public void execute() { + isPaused = false; + stepCount = 0; + eventDispatcher.onBattleResumed(new BattleResumedEvent()); + } + } + + + private class StepCommand extends Command { + public void execute() { + runBackward = false; + if (isPaused) { + stepCount++; + } + } + } + + + private class StepBackCommand extends Command { + public void execute() { + runBackward = true; + if (isPaused) { + stepCount++; + } + } + } + + + private class AbortCommand extends Command { + public void execute() { + isAborted = true; + } + } + + + protected class RobotCommand extends Command { + protected final int robotIndex; + + protected RobotCommand(int robotIndex) { + this.robotIndex = robotIndex; + } + } + + // + // Utility + // + + private void shortSleep() { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + } + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Battle.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Battle.java new file mode 100644 index 0000000..c70727a --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Battle.java @@ -0,0 +1,886 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +import net.sf.robocode.battle.events.BattleEventDispatcher; +import net.sf.robocode.battle.peer.BulletPeer; +import net.sf.robocode.battle.peer.ContestantPeer; +import net.sf.robocode.battle.peer.RobotPeer; +import net.sf.robocode.battle.peer.TeamPeer; +import net.sf.robocode.battle.snapshot.TurnSnapshot; +import net.sf.robocode.host.ICpuManager; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.security.HiddenAccess; +import net.sf.robocode.settings.ISettingsManager; +import robocode.*; +import robocode.control.RandomFactory; +import robocode.control.RobotResults; +import robocode.control.RobotSetup; +import robocode.control.RobotSpecification; +import robocode.control.events.*; +import robocode.control.events.RoundEndedEvent; +import robocode.control.snapshot.BulletState; +import robocode.control.snapshot.ITurnSnapshot; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +/** + * The {@code Battle} class is used for controlling a battle. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Luis Crespo (contributor) + * @author Robert D. Maupin (contributor) + * @author Titus Chen (contributor) + * @author Nathaniel Troutman (contributor) + * @author Julian Kent (contributor) + * @author Pavel Savara (contributor) + */ +public final class Battle extends BaseBattle { + + private static final int DEBUG_TURN_WAIT_MILLIS = 10 * 60 * 1000; // 10 seconds + + private final IHostManager hostManager; + private final long cpuConstant; + + // Inactivity related items + private int inactiveTurnCount; + private double inactivityEnergy; + + // Turn skip related items + private boolean parallelOn; + private long millisWait; + private int nanoWait; + + // Objects in the battle + private int robotsCount; + private List robots = new ArrayList(); + private List contestants = new ArrayList(); + private final List bullets = new CopyOnWriteArrayList(); + + // Robot counters + private int activeParticipants; + private int activeSentries; + + // Death events + private final List deathRobots = new CopyOnWriteArrayList(); + + // Initial robot setups (if any) + private RobotSetup[] initialRobotSetups; + + public Battle(ISettingsManager properties, IBattleManager battleManager, IHostManager hostManager, ICpuManager cpuManager, BattleEventDispatcher eventDispatcher) { // NO_UCD (unused code) + super( + properties, battleManager, eventDispatcher); + this.hostManager = hostManager; + this.cpuConstant = cpuManager.getCpuConstant(); + } + + void setup(RobotSpecification[] battlingRobotsList, BattleProperties battleProps, boolean paused) { + isPaused = paused; + battleRules = HiddenAccess.createRules(battleProps.getBattlefieldWidth(), battleProps.getBattlefieldHeight(), + battleProps.getNumRounds(), battleProps.getGunCoolingRate(), battleProps.getInactivityTime(), + battleProps.getHideEnemyNames(), battleProps.getSentryBorderSize()); + robotsCount = battlingRobotsList.length; + computeInitialPositions(battleProps.getInitialPositions()); + createPeers(battlingRobotsList); + } + + private void createPeers(RobotSpecification[] battlingRobotsList) { + // create teams + Map countedNames = new HashMap(); + List teams = new ArrayList(); + List teamDuplicates = new ArrayList(); + List robotDuplicates = new ArrayList(); + + // count duplicate robots, enumerate teams, enumerate team members + for (RobotSpecification specification : battlingRobotsList) { + final String name = ((IRobotItem) HiddenAccess.getFileSpecification(specification)).getUniqueFullClassNameWithVersion(); + + if (countedNames.containsKey(name)) { + int value = countedNames.get(name); + + countedNames.put(name, value == 1 ? 3 : value + 1); + } else { + countedNames.put(name, 1); + } + + String teamFullName = HiddenAccess.getRobotTeamName(specification); + + if (teamFullName != null) { + if (!teams.contains(teamFullName)) { + teams.add(teamFullName); + String teamName = teamFullName.substring(0, teamFullName.length() - 6); + + if (countedNames.containsKey(teamName)) { + int value = countedNames.get(teamName); + + countedNames.put(teamName, value == 1 ? 3 : value + 1); + } else { + countedNames.put(teamName, 1); + } + } + } + } + + Map> teamMembers = new HashMap>(); + + // name teams + for (int i = teams.size() - 1; i >= 0; i--) { + String teamFullName = teams.get(i); + String name = teamFullName.substring(0, teamFullName.length() - 6); + Integer order = countedNames.get(name); + String newTeamName = name; + + if (order > 1) { + newTeamName = name + " (" + (order - 1) + ")"; + } + teamDuplicates.add(0, newTeamName); + teamMembers.put(teamFullName, new ArrayList()); + countedNames.put(name, order - 1); + } + + // name robots + for (int i = battlingRobotsList.length - 1; i >= 0; i--) { + RobotSpecification specification = battlingRobotsList[i]; + String name = ((IRobotItem) HiddenAccess.getFileSpecification(specification)).getUniqueFullClassNameWithVersion(); + Integer order = countedNames.get(name); + int duplicate = -1; + + String newName = name; + + if (order > 1) { + duplicate = (order - 2); + newName = name + " (" + (order - 1) + ")"; + } + countedNames.put(name, (order - 1)); + robotDuplicates.add(0, duplicate); + + String teamFullName = HiddenAccess.getRobotTeamName(specification); + + if (teamFullName != null) { + List members = teamMembers.get(teamFullName); + + members.add(newName); + } + } + + // create teams + Map namedTeams = new HashMap(); + + // create robots + for (int i = 0; i < battlingRobotsList.length; i++) { + RobotSpecification specification = battlingRobotsList[i]; + TeamPeer team = null; + + String teamFullName = HiddenAccess.getRobotTeamName(specification); + + // The team index and robot index depends on current sizes of the contestant list and robot list + int teamIndex = contestants.size(); + int robotIndex = robots.size(); + + if (teamFullName != null) { + if (!namedTeams.containsKey(teamFullName)) { + String newTeamName = teamDuplicates.get(teams.indexOf(teamFullName)); + + team = new TeamPeer(newTeamName, teamMembers.get(teamFullName), teamIndex); + + namedTeams.put(teamFullName, team); + contestants.add(team); + + } else { + team = namedTeams.get(teamFullName); + if (team != null) { + teamIndex = team.getTeamIndex(); + } + } + } + Integer duplicate = robotDuplicates.get(i); + RobotPeer robotPeer = new RobotPeer(this, hostManager, specification, duplicate, team, robotIndex); + + robots.add(robotPeer); + if (team == null) { + contestants.add(robotPeer); + } + } + } + + public void registerDeathRobot(RobotPeer r) { + deathRobots.add(r); + } + + public BattleRules getBattleRules() { + return battleRules; + } + + public int getRobotsCount() { + return robotsCount; + } + + public boolean isDebugging() { + return RobocodeProperties.isDebuggingOn(); + } + + public void addBullet(BulletPeer bullet) { + bullets.add(bullet); + } + + public void resetInactiveTurnCount(double energyLoss) { + if (energyLoss < 0) { + return; + } + inactivityEnergy += energyLoss; + while (inactivityEnergy >= 10) { + inactivityEnergy -= 10; + inactiveTurnCount = 0; + } + } + + /** + * Returns the number of active participants. + * + * @return the number of active participants. + */ + public int countActiveParticipants() { + return activeParticipants; + } + + /** + * Returns the number of active sentry robots. + * + * @return the number of active sentry robots. + */ + public int countActiveSentries() { + return activeSentries; + } + + @Override + public void cleanup() { + + if (contestants != null) { + contestants.clear(); + contestants = null; + } + + if (robots != null) { + robots.clear(); + robots = null; + } + + super.cleanup(); + + battleManager = null; + + // Request garbage collecting + for (int i = 4; i >= 0; i--) { // Make sure it is run + System.gc(); + } + } + + @Override + protected void initializeBattle() { + super.initializeBattle(); + + parallelOn = System.getProperty("PARALLEL", "false").equals("true"); + if (parallelOn) { + // how could robots share CPUs ? + double parallelConstant = robots.size() / Runtime.getRuntime().availableProcessors(); + + // four CPUs can't run two single threaded robot faster than two CPUs + if (parallelConstant < 1) { + parallelConstant = 1; + } + final long waitTime = (long) (cpuConstant * parallelConstant); + + millisWait = waitTime / 1000000; + nanoWait = (int) (waitTime % 1000000); + } else { + millisWait = cpuConstant / 1000000; + nanoWait = (int) (cpuConstant % 1000000); + } + if (nanoWait == 0) { + nanoWait = 1; + } + } + + @Override + protected void finalizeBattle() { + eventDispatcher.onBattleFinished(new BattleFinishedEvent(isAborted())); + + if (!isAborted()) { + eventDispatcher.onBattleCompleted(new BattleCompletedEvent(battleRules, computeBattleResults())); + } + + for (RobotPeer robotPeer : robots) { + robotPeer.cleanup(); + } + hostManager.resetThreadManager(); + + super.finalizeBattle(); + } + + @Override + protected void preloadRound() { + super.preloadRound(); + + computeActiveRobots(); // Used for robotPeer.initializeRound() + + // At this point the unsafe loader thread will now set itself to wait for a notify + + for (RobotPeer robotPeer : robots) { + robotPeer.initializeRound(robots, initialRobotSetups); + robotPeer.println("========================="); + robotPeer.println("Round " + (getRoundNum() + 1) + " of " + getNumRounds()); + robotPeer.println("========================="); + } + + if (getRoundNum() == 0) { + eventDispatcher.onBattleStarted(new BattleStartedEvent(battleRules, robots.size(), false)); + if (isPaused) { + eventDispatcher.onBattlePaused(new BattlePausedEvent()); + } + } + + computeActiveRobots(); // Used for RoundEnded check hostManager.resetThreadManager(); + } + + @Override + protected void initializeRound() { + super.initializeRound(); + + inactiveTurnCount = 0; + + // Start robots + + long waitMillis; + int waitNanos; + + if (isDebugging()) { + waitMillis = DEBUG_TURN_WAIT_MILLIS; + waitNanos = 0; + } else { + long waitTime = Math.min(300 * cpuConstant, 10000000000L); + + waitMillis = waitTime / 1000000; + waitNanos = (int) (waitTime % 1000000); + } + + for (RobotPeer robotPeer : getRobotsAtRandom()) { + robotPeer.startRound(waitMillis, waitNanos); + } + + Logger.logMessage(""); // puts in a new-line in the log message + + final ITurnSnapshot snapshot = new TurnSnapshot(this, robots, bullets, false); + + eventDispatcher.onRoundStarted(new RoundStartedEvent(snapshot, getRoundNum())); + } + + @Override + protected void finalizeRound() { + super.finalizeRound(); + + for (RobotPeer robotPeer : robots) { + robotPeer.waitForStop(); + } + bullets.clear(); + + eventDispatcher.onRoundEnded(new RoundEndedEvent(getRoundNum(), currentTime, totalTurns)); + } + + @Override + protected void initializeTurn() { + super.initializeTurn(); + + eventDispatcher.onTurnStarted(new TurnStartedEvent()); + } + + @Override + protected void runTurn() { + super.runTurn(); + + loadCommands(); + + updateBullets(); + + updateRobots(); + + handleDeadRobots(); + + if (isAborted() || oneTeamRemaining()) { + shutdownTurn(); + } + + inactiveTurnCount++; + + computeActiveRobots(); + + publishStatuses(); + + // Robot time! + wakeupRobots(); + } + + @Override + protected void shutdownTurn() { + if (endTimer == 0) { + if (isAborted()) { + for (RobotPeer robotPeer : getRobotsAtRandom()) { + if (robotPeer.isAlive()) { + robotPeer.println("SYSTEM: game aborted."); + } + } + } else if (oneTeamRemaining()) { + boolean leaderFirsts = false; + TeamPeer winningTeam = null; + + robocode.RoundEndedEvent roundEndedEvent = new robocode.RoundEndedEvent(getRoundNum(), currentTime, + totalTurns); + + for (RobotPeer robotPeer : getRobotsAtRandom()) { + robotPeer.addEvent(roundEndedEvent); + if (robotPeer.isAlive() && !robotPeer.isWinner() && !robotPeer.isSentryRobot()) { + robotPeer.getRobotStatistics().scoreLastSurvivor(); + robotPeer.setWinner(true); + robotPeer.println("SYSTEM: " + robotPeer.getNameForEvent(robotPeer) + " wins the round."); + robotPeer.addEvent(new WinEvent()); + if (robotPeer.getTeamPeer() != null) { + if (robotPeer.isTeamLeader()) { + leaderFirsts = true; + } else { + winningTeam = robotPeer.getTeamPeer(); + } + } + } + // Generate totals as round has ended, but first when the last scores has been calculated + robotPeer.getRobotStatistics().generateTotals(); + } + if (!leaderFirsts && winningTeam != null) { + winningTeam.getTeamLeader().getRobotStatistics().scoreFirsts(); + } + } + if (isAborted() || isLastRound()) { + List orderedRobots = new ArrayList(robots); + Collections.sort(orderedRobots); + Collections.reverse(orderedRobots); + + for (int rank = 0; rank < robots.size(); rank++) { + RobotPeer robotPeer = orderedRobots.get(rank); + robotPeer.getStatistics().setRank(rank + 1); + BattleResults battleResults = robotPeer.getStatistics().getFinalResults(); + robotPeer.addEvent(new BattleEndedEvent(isAborted(), battleResults)); + } + } + } + + if (endTimer > 4 * TURNS_DISPLAYED_AFTER_ENDING) { + for (RobotPeer robotPeer : robots) { + robotPeer.setHalt(true); + } + } + + super.shutdownTurn(); + } + + @Override + protected void finalizeTurn() { + eventDispatcher.onTurnEnded(new TurnEndedEvent(new TurnSnapshot(this, robots, bullets, true))); + + super.finalizeTurn(); + } + + private BattleResults[] computeBattleResults() { + ArrayList results = new ArrayList(); + for (int i = 0; i < contestants.size(); i++) { + results.add(null); + } + for (int rank = 0; rank < contestants.size(); rank++) { + ContestantPeer contestant = contestants.get(rank); + contestant.getStatistics().setRank(rank + 1); + BattleResults battleResults = contestant.getStatistics().getFinalResults(); + + RobotSpecification robotSpec = null; + if (contestant instanceof RobotPeer) { + robotSpec = ((RobotPeer) contestant).getRobotSpecification(); + } else if (contestant instanceof TeamPeer) { + robotSpec = ((TeamPeer) contestant).getTeamLeader().getRobotSpecification(); + } + results.set(rank, new RobotResults(robotSpec, battleResults)); + } + return results.toArray(new BattleResults[results.size()]); + } + + /** + * Returns a list of all robots in random order. This method is used to gain fair play in Robocode, + * so that a robot placed before another robot in the list will not gain any benefit when the game + * checks if a robot has won, is dead, etc. + * This method was introduced as two equal robots like sample.RamFire got different scores even + * though the code was exactly the same. + * + * @return a list of robot peers. + */ + private List getRobotsAtRandom() { + List shuffledList = new ArrayList(robots); + + Collections.shuffle(shuffledList, RandomFactory.getRandom()); + return shuffledList; + } + + /** + * Returns a list of all bullets in random order. This method is used to gain fair play in Robocode. + * + * @return a list of bullet peers. + */ + private List getBulletsAtRandom() { + List shuffledList = new ArrayList(bullets); + + Collections.shuffle(shuffledList, RandomFactory.getRandom()); + return shuffledList; + } + + /** + * Returns a list of all death robots in random order. This method is used to gain fair play in Robocode. + * + * @return a list of robot peers. + */ + private List getDeathRobotsAtRandom() { + List shuffledList = new ArrayList(deathRobots); + + Collections.shuffle(shuffledList, RandomFactory.getRandom()); + return shuffledList; + } + + private void loadCommands() { + // this will load commands, including bullets from last turn + for (RobotPeer robotPeer : robots) { + robotPeer.performLoadCommands(); + } + } + + private void updateBullets() { + for (BulletPeer bullet : getBulletsAtRandom()) { + bullet.update(getRobotsAtRandom(), getBulletsAtRandom()); + if (bullet.getState() == BulletState.INACTIVE) { + bullets.remove(bullet); + } + } + } + + private void updateRobots() { + boolean zap = (inactiveTurnCount > battleRules.getInactivityTime()); + + final double zapEnergy = isAborted() ? 5 : zap ? .1 : 0; + + // Move all bots + for (RobotPeer robotPeer : getRobotsAtRandom()) { + robotPeer.performMove(getRobotsAtRandom(), zapEnergy); + } + + // Scan after moved all + for (RobotPeer robotPeer : getRobotsAtRandom()) { + robotPeer.performScan(getRobotsAtRandom()); + } + } + + private void handleDeadRobots() { + + for (RobotPeer deadRobot : getDeathRobotsAtRandom()) { + // Compute scores for dead robots + if (deadRobot.getTeamPeer() == null) { + deadRobot.getRobotStatistics().scoreRobotDeath(getActiveContestantCount(deadRobot)); + } else { + boolean teammatesalive = false; + + for (RobotPeer tm : robots) { + if (tm.getTeamPeer() == deadRobot.getTeamPeer() && tm.isAlive()) { + teammatesalive = true; + break; + } + } + if (!teammatesalive) { + deadRobot.getRobotStatistics().scoreRobotDeath(getActiveContestantCount(deadRobot)); + } + } + + // Publish death to live robots + for (RobotPeer robotPeer : getRobotsAtRandom()) { + if (robotPeer.isAlive()) { + robotPeer.addEvent(new RobotDeathEvent(robotPeer.getNameForEvent(deadRobot))); + + if (robotPeer.getTeamPeer() == null || robotPeer.getTeamPeer() != deadRobot.getTeamPeer()) { + robotPeer.getRobotStatistics().scoreSurvival(); + } + } + } + } + + deathRobots.clear(); + } + + private void publishStatuses() { + for (RobotPeer robotPeer : robots) { + robotPeer.publishStatus(currentTime); + } + } + + private void computeActiveRobots() { + int countActiveParticipants = 0; + int countActiveSentries = 0; + + for (RobotPeer robot : robots) { + if (robot.isAlive()) { // robot must be alive in order to be active + if (robot.isSentryRobot()) { + countActiveSentries++; + } else { + countActiveParticipants++; + } + } + } + this.activeParticipants = countActiveParticipants; + this.activeSentries = countActiveSentries; + } + + private void wakeupRobots() { + // Wake up all robot threads + final List robotsAtRandom = getRobotsAtRandom(); + + if (parallelOn) { + wakeupParallel(robotsAtRandom); + } else { + wakeupSerial(robotsAtRandom); + } + } + + private void wakeupSerial(List robotsAtRandom) { + for (RobotPeer robotPeer : robotsAtRandom) { + if (robotPeer.isRunning()) { + // This call blocks until the robot's thread actually wakes up. + robotPeer.waitWakeup(); + + if (robotPeer.isAlive()) { + if (isDebugging() || robotPeer.isPaintEnabled()) { + robotPeer.waitSleeping(DEBUG_TURN_WAIT_MILLIS, 1); + } else if (currentTime == 1) { + robotPeer.waitSleeping(millisWait * 10, 1); + } else { + robotPeer.waitSleeping(millisWait, nanoWait); + } + } + } + } + } + + private void wakeupParallel(List robotsAtRandom) { + for (RobotPeer robotPeer : robotsAtRandom) { + if (robotPeer.isRunning()) { + // This call blocks until the robot's thread actually wakes up. + robotPeer.waitWakeup(); + } + } + for (RobotPeer robotPeer : robotsAtRandom) { + if (robotPeer.isRunning() && robotPeer.isAlive()) { + if (isDebugging() || robotPeer.isPaintEnabled()) { + robotPeer.waitSleeping(DEBUG_TURN_WAIT_MILLIS, 1); + } else if (currentTime == 1) { + robotPeer.waitSleeping(millisWait * 10, 1); + } else { + robotPeer.waitSleeping(millisWait, nanoWait); + } + } + } + } + + private int getActiveContestantCount(RobotPeer peer) { + int count = 0; + + for (ContestantPeer c : contestants) { + if (c instanceof RobotPeer) { + RobotPeer robot = (RobotPeer) c; + if (!robot.isSentryRobot() && robot.isAlive()) { + count++; + } + } else if (c instanceof TeamPeer && c != peer.getTeamPeer()) { + for (RobotPeer robot: (TeamPeer) c) { + if (!robot.isSentryRobot() && robot.isAlive()) { + count++; + break; + } + } + } + } + return count; + } + + private void computeInitialPositions(String initialPositions) { + initialRobotSetups = null; + + if (initialPositions == null || initialPositions.trim().length() == 0) { + return; + } + + List positions = new ArrayList(); + + Pattern pattern = Pattern.compile("([^,(]*[(][^)]*[)])?[^,]*,?"); + Matcher matcher = pattern.matcher(initialPositions); + + while (matcher.find()) { + String pos = matcher.group(); + if (pos.length() > 0) { + positions.add(pos); + } + } + if (positions.size() == 0) { + return; + } + + initialRobotSetups = new RobotSetup[positions.size()]; + + String[] coords; + double x, y, heading; + + for (int i = 0; i < positions.size(); i++) { + coords = positions.get(i).split(","); + + Random random = RandomFactory.getRandom(); + + x = RobotPeer.WIDTH + random.nextDouble() * (battleRules.getBattlefieldWidth() - 2 * RobotPeer.WIDTH); + y = RobotPeer.HEIGHT + random.nextDouble() * (battleRules.getBattlefieldHeight() - 2 * RobotPeer.HEIGHT); + heading = 2 * Math.PI * random.nextDouble(); + + int len = coords.length; + + if (len >= 1 && coords[0].trim().length() > 0) { + try { + x = Double.parseDouble(coords[0].replaceAll("[^0-9.]", "")); + } catch (NumberFormatException ignore) {// Could be the '?', which is fine + } + if (len >= 2 && coords[1].trim().length() > 0) { + try { + y = Double.parseDouble(coords[1].replaceAll("[^0-9.]", "")); + } catch (NumberFormatException ignore) {// Could be the '?', which is fine + } + if (len >= 3 && coords[2].trim().length() > 0) { + try { + heading = Math.toRadians(Double.parseDouble(coords[2].replaceAll("[^0-9.]", ""))); + } catch (NumberFormatException ignore) {// Could be the '?', which is fine + } + } + } + } + initialRobotSetups[i] = new RobotSetup(x, y, heading); + } + } + + private boolean oneTeamRemaining() { + if (countActiveParticipants() <= 1) { + return true; + } + + boolean found = false; + TeamPeer currentTeam = null; + + for (RobotPeer currentRobot : robots) { + if (currentRobot.isAlive()) { + if (!found) { + found = true; + currentTeam = currentRobot.getTeamPeer(); + } else { + if (currentTeam == null && currentRobot.getTeamPeer() == null) { + return false; + } + if (currentTeam != currentRobot.getTeamPeer()) { + return false; + } + } + } + } + return true; + } + + // -------------------------------------------------------------------------- + // Processing and maintaining robot and battle controls + // -------------------------------------------------------------------------- + + void killRobot(int robotIndex) { + sendCommand(new KillRobotCommand(robotIndex)); + } + + public void setPaintEnabled(int robotIndex, boolean enable) { + sendCommand(new EnableRobotPaintCommand(robotIndex, enable)); + } + + void setSGPaintEnabled(int robotIndex, boolean enable) { + sendCommand(new EnableRobotSGPaintCommand(robotIndex, enable)); + } + + void sendInteractiveEvent(Event e) { + sendCommand(new SendInteractiveEventCommand(e)); + } + + private class KillRobotCommand extends RobotCommand { + KillRobotCommand(int robotIndex) { + super(robotIndex); + } + + public void execute() { + robots.get(robotIndex).kill(); + } + } + + + private class EnableRobotPaintCommand extends RobotCommand { + final boolean enablePaint; + + EnableRobotPaintCommand(int robotIndex, boolean enablePaint) { + super(robotIndex); + this.enablePaint = enablePaint; + } + + public void execute() { + robots.get(robotIndex).setPaintEnabled(enablePaint); + } + } + + + private class EnableRobotSGPaintCommand extends RobotCommand { + final boolean enableSGPaint; + + EnableRobotSGPaintCommand(int robotIndex, boolean enableSGPaint) { + super(robotIndex); + this.enableSGPaint = enableSGPaint; + } + + public void execute() { + robots.get(robotIndex).setSGPaintEnabled(enableSGPaint); + } + } + + + private class SendInteractiveEventCommand extends Command { + public final Event event; + + SendInteractiveEventCommand(Event event) { + this.event = event; + } + + public void execute() { + for (RobotPeer robotPeer : robots) { + if (robotPeer.isInteractiveRobot()) { + robotPeer.addEvent(event); + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BattleManager.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BattleManager.java new file mode 100644 index 0000000..413c0ac --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BattleManager.java @@ -0,0 +1,404 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +import net.sf.robocode.battle.events.BattleEventDispatcher; +import net.sf.robocode.core.Container; +import net.sf.robocode.host.ICpuManager; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import static net.sf.robocode.io.Logger.logError; +import static net.sf.robocode.io.Logger.logMessage; +import net.sf.robocode.recording.BattlePlayer; +import net.sf.robocode.recording.IRecordManager; +import net.sf.robocode.repository.IRepositoryManager; +import net.sf.robocode.settings.ISettingsManager; +import robocode.Event; +import robocode.control.BattleSpecification; +import robocode.control.RandomFactory; +import robocode.control.RobotSetup; +import robocode.control.RobotSpecification; +import robocode.control.events.BattlePausedEvent; +import robocode.control.events.BattleResumedEvent; +import robocode.control.events.IBattleListener; + +import java.io.*; +import java.util.concurrent.atomic.AtomicBoolean; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Luis Crespo (contributor) + * @author Robert D. Maupin (contributor) + * @author Nathaniel Troutman (contributor) + * @author Pavel Savara (contributor) + */ +public class BattleManager implements IBattleManager { + private final ISettingsManager properties; + private final IHostManager hostManager; + private final ICpuManager cpuManager; + private final IRecordManager recordManager; + private final IRepositoryManager repositoryManager; + + private volatile IBattle battle; + private Thread battleThread; + private BattleProperties battleProperties = new BattleProperties(); + + private final BattleEventDispatcher battleEventDispatcher; + + private String battleFilename; + private String battlePath; + + private int pauseCount = 0; + private final AtomicBoolean isManagedTPS = new AtomicBoolean(false); + + public BattleManager(ISettingsManager properties, IRepositoryManager repositoryManager, IHostManager hostManager, ICpuManager cpuManager, BattleEventDispatcher battleEventDispatcher, IRecordManager recordManager) { // NO_UCD (unused code) + this.properties = properties; + this.recordManager = recordManager; + this.repositoryManager = repositoryManager; + this.cpuManager = cpuManager; + this.hostManager = hostManager; + this.battleEventDispatcher = battleEventDispatcher; + Logger.setLogListener(battleEventDispatcher); + } + + public synchronized void cleanup() { + if (battle != null) { + battle.waitTillOver(); + battle.cleanup(); + } + battle = null; + } + + // Called when starting a new battle from GUI + public void startNewBattle(BattleProperties battleProperties, boolean waitTillOver, boolean enableCLIRecording) { + this.battleProperties = battleProperties; + final RobotSpecification[] robots = repositoryManager.loadSelectedRobots(battleProperties.getSelectedRobots()); + + startNewBattleImpl(robots, waitTillOver, enableCLIRecording); + } + + // Called from the RobocodeEngine + public void startNewBattle(BattleSpecification spec, String initialPositions, boolean waitTillOver, boolean enableCLIRecording) { + battleProperties = new BattleProperties(); + battleProperties.setBattlefieldWidth(spec.getBattlefield().getWidth()); + battleProperties.setBattlefieldHeight(spec.getBattlefield().getHeight()); + battleProperties.setGunCoolingRate(spec.getGunCoolingRate()); + battleProperties.setInactivityTime(spec.getInactivityTime()); + battleProperties.setNumRounds(spec.getNumRounds()); + battleProperties.setHideEnemyNames(spec.getHideEnemyNames()); + battleProperties.setSentryBorderSize(spec.getSentryBorderSize()); + battleProperties.setSelectedRobots(spec.getRobots()); + + final RobotSetup[] initialSetups = spec.getInitialSetups(); + if (initialSetups != null) { + battleProperties.setInitialPositions(initialSetups); + } else { + battleProperties.setInitialPositions(initialPositions); + } + + final RobotSpecification[] robots = repositoryManager.loadSelectedRobots(spec.getRobots()); + + startNewBattleImpl(robots, waitTillOver, enableCLIRecording); + } + + private void startNewBattleImpl(RobotSpecification[] battlingRobotsList, boolean waitTillOver, boolean enableCLIRecording) { + stop(true); + + logMessage("Preparing battle..."); + + final boolean recording = (properties.getOptionsCommonEnableReplayRecording() + && System.getProperty("TESTING", "none").equals("none")) + || enableCLIRecording; + + if (recording) { + recordManager.attachRecorder(battleEventDispatcher); + } else { + recordManager.detachRecorder(); + } + + // resets seed for deterministic behavior of Random + final String seed = System.getProperty("RANDOMSEED", "none"); + + if (!seed.equals("none")) { + // init soon as it reads random + cpuManager.getCpuConstant(); + + RandomFactory.resetDeterministic(Long.valueOf(seed)); + } + + Battle realBattle = Container.createComponent(Battle.class); + realBattle.setup(battlingRobotsList, battleProperties, isPaused()); + + battle = realBattle; + + battleThread = new Thread(Thread.currentThread().getThreadGroup(), realBattle); + battleThread.setPriority(Thread.NORM_PRIORITY); + battleThread.setName("Battle Thread"); + realBattle.setBattleThread(battleThread); + + if (RobocodeProperties.isSecurityOn()) { + hostManager.addSafeThread(battleThread); + } + + // Start the realBattle thread + battleThread.start(); + + // Wait until the realBattle is running and ended. + // This must be done as a new realBattle could be started immediately after this one causing + // multiple realBattle threads to run at the same time, which must be prevented! + realBattle.waitTillStarted(); + if (waitTillOver) { + realBattle.waitTillOver(); + } + } + + public void waitTillOver() { + if (battle != null) { + battle.waitTillOver(); + } + } + + private void replayBattle() { + if (!recordManager.hasRecord()) { + return; + } + logMessage("Preparing replay..."); + + if (battle != null && battle.isRunning()) { + battle.stop(true); + } + + Logger.setLogListener(battleEventDispatcher); + + recordManager.detachRecorder(); + battle = Container.createComponent(BattlePlayer.class); + + Thread battleThread = new Thread(Thread.currentThread().getThreadGroup(), battle); + + battleThread.setPriority(Thread.NORM_PRIORITY); + battleThread.setName("BattlePlayer Thread"); + + // Start the battlePlayer thread + battleThread.start(); + } + + public String getBattleFilename() { + return battleFilename; + } + + public void setBattleFilename(String newBattleFilename) { + if (newBattleFilename != null) { + battleFilename = newBattleFilename.replace((File.separatorChar == '/') ? '\\' : '/', File.separatorChar); + + if (battleFilename.indexOf(File.separatorChar) < 0) { + try { + battleFilename = FileUtil.getBattlesDir().getCanonicalPath() + File.separatorChar + battleFilename; + } catch (IOException ignore) {} + } + if (!battleFilename.endsWith(".battle")) { + battleFilename += ".battle"; + } + } + } + + public String getBattlePath() { + if (battlePath == null) { + battlePath = System.getProperty("BATTLEPATH"); + if (battlePath == null) { + battlePath = "battles"; + } + battlePath = new File(FileUtil.getCwd(), battlePath).getAbsolutePath(); + } + return battlePath; + } + + public void saveBattleProperties() { + if (battleProperties == null) { + logError("Cannot save null battle properties"); + return; + } + if (battleFilename == null) { + logError("Cannot save battle to null path, use setBattleFilename()"); + return; + } + FileOutputStream out = null; + + try { + out = new FileOutputStream(battleFilename); + + battleProperties.store(out, "Battle Properties"); + } catch (IOException e) { + logError("IO Exception saving battle properties: " + e); + } finally { + FileUtil.cleanupStream(out); + } + } + + public BattleProperties loadBattleProperties() { + BattleProperties res = new BattleProperties(); + FileInputStream in = null; + try { + in = new FileInputStream(getBattleFilename()); + res.load(in); + } catch (FileNotFoundException e) { + logError("No file " + battleFilename + " found, using defaults."); + } catch (IOException e) { + logError("Error while reading " + getBattleFilename() + ": " + e); + } finally { + FileUtil.cleanupStream(in); + } + return res; + } + + public BattleProperties getBattleProperties() { + if (battleProperties == null) { + battleProperties = new BattleProperties(); + } + return battleProperties; + } + + public void setDefaultBattleProperties() { + battleProperties = new BattleProperties(); + } + + public boolean isManagedTPS() { + return isManagedTPS.get(); + } + + public void setManagedTPS(boolean value) { + isManagedTPS.set(value); + } + + public synchronized void addListener(IBattleListener listener) { + battleEventDispatcher.addListener(listener); + } + + public synchronized void removeListener(IBattleListener listener) { + battleEventDispatcher.removeListener(listener); + } + + public synchronized void stop(boolean waitTillEnd) { + if (battle != null && battle.isRunning()) { + battle.stop(waitTillEnd); + } + if (hostManager != null && battleThread != null) { + hostManager.removeSafeThread(battleThread); + } + battleThread = null; + } + + public synchronized void restart() { + // Start new battle. The old battle is automatically stopped + startNewBattle(battleProperties, false, false); + } + + public synchronized void replay() { + replayBattle(); + } + + private boolean isPaused() { + return (pauseCount != 0); + } + + public synchronized void togglePauseResumeBattle() { + if (isPaused()) { + resumeBattle(); + } else { + pauseBattle(); + } + } + + public synchronized void pauseBattle() { + if (++pauseCount == 1) { + if (battle != null && battle.isRunning()) { + battle.pause(); + } else { + battleEventDispatcher.onBattlePaused(new BattlePausedEvent()); + } + } + } + + public synchronized void pauseIfResumedBattle() { + if (pauseCount == 0) { + pauseCount++; + if (battle != null && battle.isRunning()) { + battle.pause(); + } else { + battleEventDispatcher.onBattlePaused(new BattlePausedEvent()); + } + } + } + + public synchronized void resumeIfPausedBattle() { + if (pauseCount == 1) { + pauseCount--; + if (battle != null && battle.isRunning()) { + battle.resume(); + } else { + battleEventDispatcher.onBattleResumed(new BattleResumedEvent()); + } + } + } + + public synchronized void resumeBattle() { + if (--pauseCount < 0) { + pauseCount = 0; + logError("SYSTEM: pause game bug!"); + } else if (pauseCount == 0) { + if (battle != null && battle.isRunning()) { + battle.resume(); + } else { + battleEventDispatcher.onBattleResumed(new BattleResumedEvent()); + } + } + } + + /** + * Steps for a single turn, then goes back to paused + */ + public synchronized void nextTurn() { + if (battle != null && battle.isRunning()) { + battle.step(); + } + } + + public synchronized void prevTurn() { + if (battle != null && battle.isRunning() && battle instanceof BattlePlayer) { + ((BattlePlayer) battle).stepBack(); + } + } + + public synchronized void killRobot(int robotIndex) { + if (battle != null && battle.isRunning() && battle instanceof Battle) { + ((Battle) battle).killRobot(robotIndex); + } + } + + public synchronized void setPaintEnabled(int robotIndex, boolean enable) { + if (battle != null && battle.isRunning()) { + battle.setPaintEnabled(robotIndex, enable); + } + } + + public synchronized void setSGPaintEnabled(int robotIndex, boolean enable) { + if (battle != null && battle.isRunning() && battle instanceof Battle) { + ((Battle) battle).setSGPaintEnabled(robotIndex, enable); + } + } + + public synchronized void sendInteractiveEvent(Event event) { + if (battle != null && battle.isRunning() && !isPaused() && battle instanceof Battle) { + ((Battle) battle).sendInteractiveEvent(event); + } + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BoundingRectangle.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BoundingRectangle.java new file mode 100644 index 0000000..5257252 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/BoundingRectangle.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +/* + * Class exists to fix two bugs, both related to bug# 4320890 referenced below + * 1. intersectsLine can cause an infinite loop in Java 1.3 + * -- This is why the outcode() method is here, below + * 2. The problem still exists with Rectangle2D.Double as of Java 1.4, + * -- This is why we're using Rectangle2D.Float + * + * @author Mathew A. Nelson (original) + */ +@SuppressWarnings("serial") +public class BoundingRectangle extends java.awt.geom.Rectangle2D.Float { + + public BoundingRectangle() { + super(); + } + + public BoundingRectangle(double x, double y, double w, double h) { + super((float) x, (float) y, (float) w, (float) h); + } + + @Override + public int outcode(double x, double y) { + + /* + * Note on casts to double below. If the arithmetic of + * x+w or y+h is done in float, then some bits may be + * lost if the binary exponents of x/y and w/h are not + * similar. By converting to double before the addition + * we force the addition to be carried out in double to + * avoid rounding error in the comparison. + * + * See bug 4320890 for problems that this inaccuracy causes. + */ + int out = 0; + + if (this.width <= 0) { + out |= OUT_LEFT | OUT_RIGHT; + } else if (x < this.x) { + out |= OUT_LEFT; + } else if (x > this.x + (double) this.width) { + out |= OUT_RIGHT; + } + if (this.height <= 0) { + out |= OUT_TOP | OUT_BOTTOM; + } else if (y < this.y) { + out |= OUT_TOP; + } else if (y > this.y + (double) this.height) { + out |= OUT_BOTTOM; + } + return out; + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Command.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Command.java new file mode 100644 index 0000000..054c152 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Command.java @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +abstract class Command { + + public void execute() {} +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/IBattle.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/IBattle.java new file mode 100644 index 0000000..8a35a86 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/IBattle.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +/** + * @author Pavel Savara (original) + */ +interface IBattle extends Runnable { + void cleanup(); + + boolean isRunning(); + + void stop(boolean waitTillEnd); + + void pause(); + + void resume(); + + void step(); + + void waitTillStarted(); + + void waitTillOver(); + + void setPaintEnabled(int robotIndex, boolean enable); +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Module.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Module.java new file mode 100644 index 0000000..bc78da0 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/Module.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +import net.sf.robocode.battle.events.BattleEventDispatcher; +import net.sf.robocode.core.Container; +import net.sf.robocode.recording.BattlePlayer; +import net.sf.robocode.recording.IRecordManager; +import net.sf.robocode.recording.RecordManager; + + +/** + * @author Pavel Savara (original) + */ +public class Module { + static { + Container.cache.addComponent(IBattleManager.class, BattleManager.class); + Container.cache.addComponent(BattleEventDispatcher.class); + Container.cache.addComponent(IRecordManager.class, RecordManager.class); + + Container.factory.addComponent(Battle.class); + Container.factory.addComponent(BattlePlayer.class); + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/BulletPeer.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/BulletPeer.java new file mode 100644 index 0000000..462dfe6 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/BulletPeer.java @@ -0,0 +1,364 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.peer; + + +import net.sf.robocode.peer.BulletStatus; +import robocode.*; +import robocode.control.snapshot.BulletState; + +import java.awt.geom.Line2D; +import static java.lang.Math.cos; +import static java.lang.Math.sin; +import java.util.List; + + +public class BulletPeer { + + private static final int EXPLOSION_LENGTH = 17; + + private static final int RADIUS = 3; + + protected final RobotPeer owner; + + private final BattleRules battleRules; + private final int bulletId; + + protected RobotPeer victim; + + protected BulletState state; + + private double heading; + + protected double x; + protected double y; + + private double lastX; + private double lastY; + + protected double power; + + private double deltaX; + private double deltaY; + + private final Line2D.Double boundingLine = new Line2D.Double(); + + protected int frame; // Do not set to -1 + + private final int color; + + protected int explosionImageIndex; // Do not set to -1 + + BulletPeer(RobotPeer owner, BattleRules battleRules, int bulletId) { + super(); + this.owner = owner; + this.battleRules = battleRules; + this.bulletId = bulletId; + state = BulletState.FIRED; + color = owner.getBulletColor(); // Store current bullet color set on robot + } + + private void checkBulletCollision(List bullets) { + for (BulletPeer b : bullets) { + if (b != null && b != this && b.isActive() && intersect(b.boundingLine)) { + // Check if one of the bullets belongs to a sentry robot and is within the safe zone + if (owner.isSentryRobot() || b.getOwner().isSentryRobot()) { + int sentryBorderSize = battleRules.getSentryBorderSize(); + if (x > sentryBorderSize && x < (battleRules.getBattlefieldWidth() - sentryBorderSize) + && y > sentryBorderSize && y < (battleRules.getBattlefieldHeight() - sentryBorderSize)) { + + continue; // Continue, as the sentry should not interfere with bullets in the safe zone + } + } + + state = BulletState.HIT_BULLET; + frame = 0; + x = lastX; + y = lastY; + + b.state = BulletState.HIT_BULLET; + b.frame = 0; + b.x = b.lastX; + b.y = b.lastY; + + // Bugfix #366 + owner.addEvent(new BulletHitBulletEvent(createBullet(false), b.createBullet(true))); + b.owner.addEvent(new BulletHitBulletEvent(b.createBullet(false), createBullet(true))); + break; + } + } + } + + private Bullet createBullet(boolean hideOwnerName) { + String ownerName = (owner == null) ? null : (hideOwnerName ? getNameForEvent(owner) : owner.getName()); + String victimName = (victim == null) ? null : (hideOwnerName ? victim.getName() : getNameForEvent(victim)); + + return new Bullet(heading, x, y, power, ownerName, victimName, isActive(), bulletId); + } + + private BulletStatus createStatus() { + return new BulletStatus(bulletId, x, y, victim == null ? null : getNameForEvent(victim), isActive()); + } + + private String getNameForEvent(RobotPeer otherRobot) { + if (battleRules.getHideEnemyNames() && !owner.isTeamMate(otherRobot)) { + return otherRobot.getAnnonymousName(); + } + return otherRobot.getName(); + } + + // Workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6457965 + private boolean intersect(Line2D.Double line) { + double x1 = line.x1, x2 = line.x2, x3 = boundingLine.x1, x4 = boundingLine.x2; + double y1 = line.y1, y2 = line.y2, y3 = boundingLine.y1, y4 = boundingLine.y2; + + double dx13 = (x1 - x3), dx21 = (x2 - x1), dx43 = (x4 - x3); + double dy13 = (y1 - y3), dy21 = (y2 - y1), dy43 = (y4 - y3); + + double dn = dy43 * dx21 - dx43 * dy21; + + double ua = (dx43 * dy13 - dy43 * dx13) / dn; + double ub = (dx21 * dy13 - dy21 * dx13) / dn; + + return (ua >= 0 && ua <= 1) && (ub >= 0 && ub <= 1); + } + + private void checkRobotCollision(List robots) { + for (RobotPeer otherRobot : robots) { + if (!(otherRobot == null || otherRobot == owner || otherRobot.isDead()) + && otherRobot.getBoundingBox().intersectsLine(boundingLine)) { + + state = BulletState.HIT_VICTIM; + frame = 0; + victim = otherRobot; + + double damage = Rules.getBulletDamage(power); + + if (owner.isSentryRobot()) { + if (victim.isSentryRobot()) { + damage = 0; + } else { + int range = battleRules.getSentryBorderSize(); + if (x > range && x < (battleRules.getBattlefieldWidth() - range) && y > range + && y < (battleRules.getBattlefieldHeight() - range)) { + damage = 0; + } + } + } + + double score = damage; + if (score > otherRobot.getEnergy()) { + score = otherRobot.getEnergy(); + } + otherRobot.updateEnergy(-damage); + + boolean teamFire = (owner.getTeamPeer() != null && owner.getTeamPeer() == otherRobot.getTeamPeer()); + + if (!teamFire && !otherRobot.isSentryRobot()) { + owner.getRobotStatistics().scoreBulletDamage(otherRobot.getName(), score); + } + + if (otherRobot.getEnergy() <= 0 && otherRobot.isAlive()) { + otherRobot.kill(); + if (!teamFire && !otherRobot.isSentryRobot()) { + double bonus = owner.getRobotStatistics().scoreBulletKill(otherRobot.getName()); + if (bonus > 0) { + owner.println( + "SYSTEM: Bonus for killing " + + (owner.getNameForEvent(otherRobot) + ": " + (int) (bonus + .5))); + } + } + } + + if (!victim.isSentryRobot()) { + owner.updateEnergy(Rules.getBulletHitBonus(power)); + } + + otherRobot.addEvent( + new HitByBulletEvent( + robocode.util.Utils.normalRelativeAngle(heading + Math.PI - otherRobot.getBodyHeading()), + createBullet(true))); // Bugfix #366 + + owner.addEvent( + new BulletHitEvent(owner.getNameForEvent(otherRobot), otherRobot.getEnergy(), createBullet(false))); // Bugfix #366 + + double newX, newY; + + if (otherRobot.getBoundingBox().contains(lastX, lastY)) { + newX = lastX; + newY = lastY; + + setX(newX); + setY(newY); + } else { + newX = x; + newY = y; + } + + deltaX = newX - otherRobot.getX(); + deltaY = newY - otherRobot.getY(); + + break; + } + } + } + + private void checkWallCollision() { + if ((x - RADIUS <= 0) || (y - RADIUS <= 0) || (x + RADIUS >= battleRules.getBattlefieldWidth()) + || (y + RADIUS >= battleRules.getBattlefieldHeight())) { + state = BulletState.HIT_WALL; + frame = 0; + owner.addEvent(new BulletMissedEvent(createBullet(false))); // Bugfix #366 + } + } + + public int getBulletId() { + return bulletId; + } + + public int getFrame() { + return frame; + } + + public double getHeading() { + return heading; + } + + public RobotPeer getOwner() { + return owner; + } + + public double getPower() { + return power; + } + + public double getVelocity() { + return Rules.getBulletSpeed(power); + } + + public RobotPeer getVictim() { + return victim; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getPaintX() { + return (state == BulletState.HIT_VICTIM && victim != null) ? victim.getX() + deltaX : x; + } + + public double getPaintY() { + return (state == BulletState.HIT_VICTIM && victim != null) ? victim.getY() + deltaY : y; + } + + public boolean isActive() { + return state.isActive(); + } + + public BulletState getState() { + return state; + } + + public int getColor() { + return color; + } + + public void setHeading(double newHeading) { + heading = newHeading; + } + + public void setPower(double newPower) { + power = newPower; + } + + public void setVictim(RobotPeer newVictim) { + victim = newVictim; + } + + public void setX(double newX) { + x = lastX = newX; + } + + public void setY(double newY) { + y = lastY = newY; + } + + public void setState(BulletState newState) { + state = newState; + } + + public void update(List robots, List bullets) { + frame++; + if (isActive()) { + updateMovement(); + checkWallCollision(); + if (isActive()) { + checkRobotCollision(robots); + } + if (isActive() && bullets != null) { + checkBulletCollision(bullets); + } + } + updateBulletState(); + owner.addBulletStatus(createStatus()); + } + + protected void updateBulletState() { + switch (state) { + case FIRED: + // Note that the bullet must be in the FIRED state before it goes to the MOVING state + if (frame > 0) { + state = BulletState.MOVING; + } + break; + + case HIT_BULLET: + case HIT_VICTIM: + case HIT_WALL: + case EXPLODED: + // Note that the bullet explosion must be ended before it goes into the INACTIVE state + if (frame >= getExplosionLength()) { + state = BulletState.INACTIVE; + } + break; + + default: + } + } + + private void updateMovement() { + lastX = x; + lastY = y; + + double v = getVelocity(); + + x += v * sin(heading); + y += v * cos(heading); + + boundingLine.setLine(lastX, lastY, x, y); + } + + public int getExplosionImageIndex() { + return explosionImageIndex; + } + + protected int getExplosionLength() { + return EXPLOSION_LENGTH; + } + + @Override + public String toString() { + return getOwner().getName() + " V" + getVelocity() + " *" + (int) power + " X" + (int) x + " Y" + (int) y + " H" + + heading + " " + state.toString(); + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ContestantPeer.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ContestantPeer.java new file mode 100644 index 0000000..8030135 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ContestantPeer.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.peer; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public interface ContestantPeer extends Comparable { + String getName(); + + int getRobotIndex(); + int getTeamIndex(); + + ContestantStatistics getStatistics(); + + String toString(); +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ContestantStatistics.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ContestantStatistics.java new file mode 100644 index 0000000..73d61e0 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ContestantStatistics.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.peer; + + +import robocode.BattleResults; + + +/** + * @author Mathew A. Nelson (original) + * @author Luis Crespo (contributor) + * @author Flemming N. Larsen (contributor) + */ +public interface ContestantStatistics { // NO_UCD (use default) + double getTotalScore(); + + double getTotalSurvivalScore(); + + double getTotalLastSurvivorBonus(); + + double getTotalBulletDamageScore(); + + double getTotalBulletKillBonus(); + + double getTotalRammingDamageScore(); + + double getTotalRammingKillBonus(); + + int getTotalFirsts(); + + int getTotalSeconds(); + + int getTotalThirds(); + + double getCurrentScore(); + + double getCurrentSurvivalScore(); + + double getCurrentSurvivalBonus(); + + double getCurrentBulletDamageScore(); + + double getCurrentBulletKillBonus(); + + double getCurrentRammingDamageScore(); + + double getCurrentRammingKillBonus(); + + BattleResults getFinalResults(); + + void setRank(int rank); +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ExplosionPeer.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ExplosionPeer.java new file mode 100644 index 0000000..e2c470c --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/ExplosionPeer.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.peer; + + +import robocode.BattleRules; +import robocode.control.snapshot.BulletState; + +import java.util.List; + + +/** + * @author Mathew A. Nelson (original) + * @author Luis Crespo (contributor) + * @author Flemming N. Larsen (contributor) + * @author Titus Chen (contributor) + */ +public class ExplosionPeer extends BulletPeer { + + private static final int EXPLOSION_LENGTH = 71; + + ExplosionPeer(RobotPeer owner, BattleRules battleRules) { + super(owner, battleRules, 0); + frame = 0; + x = owner.getX(); + y = owner.getY(); + victim = owner; + power = 1; + state = BulletState.EXPLODED; + explosionImageIndex = 1; + } + + @Override + public final void update(List robots, List bullets) { + frame++; + + x = owner.getX(); + y = owner.getY(); + + updateBulletState(); + } + + @Override + protected int getExplosionLength() { + return EXPLOSION_LENGTH; + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/IRobotPeerBattle.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/IRobotPeerBattle.java new file mode 100644 index 0000000..18a9d85 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/IRobotPeerBattle.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.peer; + + +import robocode.Event; +import robocode.control.RobotSetup; + +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +interface IRobotPeerBattle extends ContestantPeer { + void setSGPaintEnabled(boolean enabled); + + RobotStatistics getRobotStatistics(); + + TeamPeer getTeamPeer(); + + void publishStatus(long currentTurn); + + void addEvent(Event event); + + void setPaintEnabled(boolean enabled); + + void kill(); + + void cleanup(); + + boolean isDead(); + + boolean isAlive(); + + boolean isRunning(); + + boolean isWinner(); + + boolean isTeamLeader(); + + void setHalt(boolean value); + + void println(String s); + + void waitWakeup(); + + void waitSleeping(long millisWait, int nanosWait); + + void waitForStop(); + + void setWinner(boolean newWinner); + + void initializeRound(List robots, RobotSetup[] initialRobotPositions); + + void startRound(long millisWait, int nanosWait); + + void checkSkippedTurn(); + + void performLoadCommands(); + + void performMove(List robots, double zapEnergy); + + void performScan(List robots); +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/RobotPeer.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/RobotPeer.java new file mode 100644 index 0000000..c41d9fe --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/RobotPeer.java @@ -0,0 +1,1764 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.peer; + + +import static net.sf.robocode.io.Logger.logMessage; +import net.sf.robocode.battle.Battle; +import net.sf.robocode.battle.BoundingRectangle; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.host.RobotStatics; +import net.sf.robocode.host.events.EventManager; +import net.sf.robocode.host.events.EventQueue; +import net.sf.robocode.host.proxies.IHostingRobotProxy; +import net.sf.robocode.io.Logger; +import net.sf.robocode.peer.*; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.security.HiddenAccess; +import net.sf.robocode.serialization.RbSerializer; +import robocode.*; +import robocode.control.RandomFactory; +import robocode.control.RobotSetup; +import robocode.control.RobotSpecification; +import robocode.control.snapshot.BulletState; +import robocode.control.snapshot.RobotState; +import robocode.exception.AbortedException; +import robocode.exception.DeathException; +import robocode.exception.WinException; +import static robocode.util.Utils.*; + +import java.awt.geom.Arc2D; +import java.awt.geom.Rectangle2D; +import java.io.IOException; + +import static java.lang.Math.*; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + + +/** + * RobotPeer is an object that deals with game mechanics and rules, and makes + * sure that robots abides the rules. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Luis Crespo (contributor) + * @author Titus Chen (contributor) + * @author Robert D. Maupin (contributor) + * @author Nathaniel Troutman (contributor) + * @author Pavel Savara (contributor) + * @author Patrick Cupka (contributor) + * @author Julian Kent (contributor) + * @author "Positive" (contributor) + * @author "BD123" (contributor) + */ +public final class RobotPeer implements IRobotPeerBattle, IRobotPeer { + + public static final int + WIDTH = 36, + HEIGHT = 36; + + private static final int + HALF_WIDTH_OFFSET = WIDTH / 2, + HALF_HEIGHT_OFFSET = HEIGHT / 2; + + private static final int MAX_SKIPPED_TURNS = 30; + private static final int MAX_SKIPPED_TURNS_WITH_IO = 240; + + private Battle battle; + private RobotStatistics statistics; + private final TeamPeer teamPeer; + private final RobotSpecification robotSpecification; + + private IHostingRobotProxy robotProxy; + private AtomicReference status = new AtomicReference(); + private AtomicReference commands = new AtomicReference(); + private AtomicReference events = new AtomicReference(new EventQueue()); + private AtomicReference> teamMessages = new AtomicReference>( + new ArrayList()); + private AtomicReference> bulletUpdates = new AtomicReference>( + new ArrayList()); + + // thread is running + private final AtomicBoolean isRunning = new AtomicBoolean(false); + + private final StringBuilder battleText = new StringBuilder(1024); + private final StringBuilder proxyText = new StringBuilder(1024); + private RobotStatics statics; + private BattleRules battleRules; + + // for battle thread, during robots processing + private ExecCommands currentCommands; + private double lastHeading; + private double lastGunHeading; + private double lastRadarHeading; + + private double energy; + private double velocity; + private double bodyHeading; + private double radarHeading; + private double gunHeading; + private double gunHeat; + private double x; + private double y; + + private boolean scan; + private boolean turnedRadarWithGun; // last round + + private boolean isIORobot; + private boolean isPaintEnabled; + private boolean sgPaintEnabled; + + // waiting for next tick + private final AtomicBoolean isSleeping = new AtomicBoolean(false); + private final AtomicBoolean halt = new AtomicBoolean(false); + + // last and current execution time and detecting skipped turns + private int lastExecutionTime = -1; + private int currentExecutionTime; + + private boolean isExecFinishedAndDisabled; + private boolean isEnergyDrained; + private boolean isWinner; + private boolean inCollision; + private boolean isOverDriving; + + private RobotState state; + private final Arc2D scanArc; + private final BoundingRectangle boundingBox; + private final RbSerializer rbSerializer; + + public RobotPeer(Battle battle, IHostManager hostManager, RobotSpecification robotSpecification, int duplicate, TeamPeer team, int robotIndex) { + super(); + + this.battle = battle; + this.robotSpecification = robotSpecification; + + this.rbSerializer = new RbSerializer(); + + this.boundingBox = new BoundingRectangle(); + this.scanArc = new Arc2D.Double(); + this.teamPeer = team; + this.state = RobotState.ACTIVE; + this.battleRules = battle.getBattleRules(); + + if (team != null) { + team.add(this); + } + String teamName; + List teamMembers; + boolean isTeamLeader; + int teamIndex; + + if (teamPeer == null) { + teamName = null; + teamMembers = null; + isTeamLeader = false; + teamIndex = -1; // Must be set to -1 when robot is not in a team + } else { + teamName = team.getName(); + teamMembers = team.getMemberNames(); + isTeamLeader = team.size() == 1; // That is current team size, more might follow later. First robot is leader + teamIndex = team.getTeamIndex(); + } + + this.statics = new RobotStatics(robotSpecification, duplicate, isTeamLeader, battleRules, teamName, teamMembers, + robotIndex, teamIndex); + this.statistics = new RobotStatistics(this, battle.getRobotsCount()); + + this.robotProxy = (IHostingRobotProxy) hostManager.createRobotProxy(robotSpecification, statics, this); + } + + public void println(String s) { + synchronized (proxyText) { + battleText.append(s); + battleText.append("\n"); + } + } + + private void print(String s) { + synchronized (proxyText) { + proxyText.append(s); + } + } + + public String readOutText() { + synchronized (proxyText) { + final String robotText = battleText.toString() + proxyText.toString(); + + battleText.setLength(0); + proxyText.setLength(0); + return robotText; + } + } + + public RobotStatistics getRobotStatistics() { + return statistics; + } + + public ContestantStatistics getStatistics() { + return statistics; + } + + public RobotSpecification getRobotSpecification() { + return robotSpecification; + } + + // ------------------- + // statics + // ------------------- + + public boolean isJuniorRobot() { + return statics.isJuniorRobot(); + } + + public boolean isAdvancedRobot() { + return statics.isAdvancedRobot(); + } + + public boolean isTeamRobot() { + return statics.isTeamRobot(); + } + + public boolean isDroid() { + return statics.isDroid(); + } + + public boolean isSentryRobot() { + return statics.isSentryRobot(); + } + + public boolean isInteractiveRobot() { + return statics.isInteractiveRobot(); + } + + public boolean isPaintRobot() { + return statics.isPaintRobot(); + } + + public String getName() { + return statics.getName(); + } + + public String getAnnonymousName() { + return statics.getAnnonymousName(); + } + + public String getShortName() { + return statics.getShortName(); + } + + public String getVeryShortName() { + return statics.getVeryShortName(); + } + + public int getRobotIndex() { + return statics.getRobotIndex(); + } + + public int getTeamIndex() { + return statics.getTeamIndex(); + } + + public int getContestantIndex() { + return getTeamIndex() >= 0 ? getTeamIndex() : getRobotIndex(); + } + + // ------------------- + // status + // ------------------- + + public void setPaintEnabled(boolean enabled) { + isPaintEnabled = enabled; + } + + public boolean isPaintEnabled() { + return isPaintEnabled; + } + + public void setSGPaintEnabled(boolean enabled) { + sgPaintEnabled = enabled; + } + + public boolean isSGPaintEnabled() { + return sgPaintEnabled; + } + + public RobotState getState() { + return state; + } + + public void setState(RobotState state) { + this.state = state; + } + + public boolean isDead() { + return state == RobotState.DEAD; + } + + public boolean isAlive() { + return state != RobotState.DEAD; + } + + public boolean isWinner() { + return isWinner; + } + + public boolean isRunning() { + return isRunning.get(); + } + + public boolean isSleeping() { + return isSleeping.get(); + } + + public boolean isHalt() { + return halt.get(); + } + + public void setHalt(boolean value) { + halt.set(value); + } + + public BoundingRectangle getBoundingBox() { + return boundingBox; + } + + public Arc2D getScanArc() { + return scanArc; + } + + // ------------------- + // robot space + // ------------------- + + public double getGunHeading() { + return gunHeading; + } + + public double getBodyHeading() { + return bodyHeading; + } + + public double getRadarHeading() { + return radarHeading; + } + + public double getVelocity() { + return velocity; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getEnergy() { + return energy; + } + + public double getGunHeat() { + return gunHeat; + } + + public int getBodyColor() { + return commands.get().getBodyColor(); + } + + public int getRadarColor() { + return commands.get().getRadarColor(); + } + + public int getGunColor() { + return commands.get().getGunColor(); + } + + public int getBulletColor() { + return commands.get().getBulletColor(); + } + + public int getScanColor() { + return commands.get().getScanColor(); + } + + // ------------ + // team + // ------------ + + public TeamPeer getTeamPeer() { + return teamPeer; + } + + public String getTeamName() { + return statics.getTeamName(); + } + + public boolean isTeamLeader() { + return statics.isTeamLeader(); + } + + boolean isTeamMate(RobotPeer otherRobot) { + if (getTeamPeer() != null) { + for (RobotPeer mate : getTeamPeer()) { + if (otherRobot == mate) { + return true; + } + } + } + return false; + } + + // ----------- + // execute + // ----------- + + private ByteBuffer bidirectionalBuffer; + + public void setupBuffer(ByteBuffer bidirectionalBuffer) { + this.bidirectionalBuffer = bidirectionalBuffer; + } + + public void setupThread() { + Thread.currentThread().setName(getName()); + } + + public void executeImplSerial() throws IOException { + ExecCommands commands = (ExecCommands) rbSerializer.deserialize(bidirectionalBuffer); + + final ExecResults results = executeImpl(commands); + + bidirectionalBuffer.clear(); + rbSerializer.serializeToBuffer(bidirectionalBuffer, RbSerializer.ExecResults_TYPE, results); + } + + public void waitForBattleEndImplSerial() throws IOException { + ExecCommands commands = (ExecCommands) rbSerializer.deserialize(bidirectionalBuffer); + + final ExecResults results = waitForBattleEndImpl(commands); + + bidirectionalBuffer.clear(); + rbSerializer.serializeToBuffer(bidirectionalBuffer, RbSerializer.ExecResults_TYPE, results); + } + + public final ExecResults executeImpl(ExecCommands newCommands) { + validateCommands(newCommands); + + if (!isExecFinishedAndDisabled) { + // from robot to battle + commands.set(new ExecCommands(newCommands, true)); + print(newCommands.getOutputText()); + } else { + // slow down spammer + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + // If we are stopping, yet the robot took action (in onWin or onDeath), stop now. + if (battle.isAborted()) { + isExecFinishedAndDisabled = true; + throw new AbortedException(); + } + if (isDead()) { + isExecFinishedAndDisabled = true; + throw new DeathException(); + } + if (isHalt()) { + isExecFinishedAndDisabled = true; + if (isWinner) { + throw new WinException(); + } else { + throw new AbortedException(); + } + } + + waitForNextTurn(); + + checkSkippedTurn(); + + // from battle to robot + final ExecCommands resCommands = new ExecCommands(this.commands.get(), false); + final RobotStatus resStatus = status.get(); + + final boolean shouldWait = battle.isAborted() || (battle.isLastRound() && isWinner()); + + return new ExecResults(resCommands, resStatus, readoutEvents(), readoutTeamMessages(), readoutBullets(), + isHalt(), shouldWait, isPaintEnabled()); + } + + public final ExecResults waitForBattleEndImpl(ExecCommands newCommands) { + if (!isHalt()) { + // from robot to battle + commands.set(new ExecCommands(newCommands, true)); + print(newCommands.getOutputText()); + + waitForNextTurn(); + } + // from battle to robot + final ExecCommands resCommands = new ExecCommands(this.commands.get(), false); + final RobotStatus resStatus = status.get(); + + final boolean shouldWait = battle.isAborted() || (battle.isLastRound() && !isWinner()); + + readoutTeamMessages(); // throw away + + return new ExecResults(resCommands, resStatus, readoutEvents(), new ArrayList(), readoutBullets(), + isHalt(), shouldWait, false); + } + + private void validateCommands(ExecCommands newCommands) { + if (Double.isNaN(newCommands.getMaxTurnRate())) { + println("You cannot setMaxTurnRate to: " + newCommands.getMaxTurnRate()); + } + newCommands.setMaxTurnRate(Math.min(abs(newCommands.getMaxTurnRate()), Rules.MAX_TURN_RATE_RADIANS)); + + if (Double.isNaN(newCommands.getMaxVelocity())) { + println("You cannot setMaxVelocity to: " + newCommands.getMaxVelocity()); + } + newCommands.setMaxVelocity(Math.min(abs(newCommands.getMaxVelocity()), Rules.MAX_VELOCITY)); + } + + private List readoutEvents() { + return events.getAndSet(new EventQueue()); + } + + private List readoutTeamMessages() { + return teamMessages.getAndSet(new ArrayList()); + } + + private List readoutBullets() { + return bulletUpdates.getAndSet(new ArrayList()); + } + + private void waitForNextTurn() { + synchronized (isSleeping) { + // Notify the battle that we are now asleep. + // This ends any pending wait() call in battle.runRound(). + // Should not actually take place until we release the lock in wait(), below. + isSleeping.set(true); + isSleeping.notifyAll(); + // Notifying battle that we're asleep + // Sleeping and waiting for battle to wake us up. + try { + isSleeping.wait(); + } catch (InterruptedException e) { + // We are expecting this to happen when a round is ended! + + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + } + isSleeping.set(false); + // Notify battle thread, which is waiting in + // our wakeup() call, to return. + // It's quite possible, by the way, that we'll be back in sleep (above) + // before the battle thread actually wakes up + isSleeping.notifyAll(); + } + } + + // ----------- + // called on battle thread + // ----------- + + public void waitWakeup() { + synchronized (isSleeping) { + if (isSleeping()) { + // Wake up the thread + isSleeping.notifyAll(); + try { + isSleeping.wait(10000); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + } + } + } + } + + private void waitWakeupNoWait() { + synchronized (isSleeping) { + if (isSleeping()) { + // Wake up the thread + isSleeping.notifyAll(); + } + } + } + + public void waitSleeping(long millisWait, int nanosWait) { + synchronized (isSleeping) { + // It's quite possible for simple robots to + // complete their processing before we get here, + // so we test if the robot is already asleep. + + if (!isSleeping()) { + try { + for (long i = millisWait; i > 0 && !isSleeping() && isRunning(); i--) { + isSleeping.wait(0, 999999); + } + if (!isSleeping() && isRunning()) { + isSleeping.wait(0, nanosWait); + } + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + + logMessage("Wait for " + getName() + " interrupted."); + } + } + } + } + + public void checkSkippedTurn() { + // Store last and current execution time for detecting skipped turns + lastExecutionTime = currentExecutionTime; + currentExecutionTime = battle.getTime(); + + int numSkippedTurns = (currentExecutionTime - lastExecutionTime) - 1; + if (numSkippedTurns >= 1) { + events.get().clear(false); + + if (isAlive()) { + for (int skippedTurn = lastExecutionTime + 1; skippedTurn < currentExecutionTime; skippedTurn++) { + addEvent(new SkippedTurnEvent(skippedTurn)); + println("SYSTEM: " + getShortName() + " skipped turn " + skippedTurn); + } + } + + if ((!isIORobot && (numSkippedTurns > MAX_SKIPPED_TURNS)) + || (isIORobot && (numSkippedTurns > MAX_SKIPPED_TURNS_WITH_IO))) { + println("SYSTEM: " + getShortName() + " has not performed any actions in a reasonable amount of time."); + println("SYSTEM: No score will be generated."); + setHalt(true); + waitWakeupNoWait(); + punishBadBehavior(BadBehavior.SKIPPED_TOO_MANY_TURNS); + robotProxy.forceStopThread(); + } + } + } + + public void initializeRound(List robots, RobotSetup[] initialRobotSetups) { + boolean valid = false; + + if (initialRobotSetups != null) { + int robotIndex = statics.getRobotIndex(); + + if (robotIndex >= 0 && robotIndex < initialRobotSetups.length) { + RobotSetup setup = initialRobotSetups[robotIndex]; + if (setup != null) { + x = setup.getX(); + y = setup.getY(); + bodyHeading = gunHeading = radarHeading = setup.getHeading(); + + updateBoundingBox(); + valid = validSpot(robots); + } + } + } + + if (!valid) { + final Random random = RandomFactory.getRandom(); + + double maxWidth = battleRules.getBattlefieldWidth() - RobotPeer.WIDTH; + double maxHeight = battleRules.getBattlefieldHeight() - RobotPeer.HEIGHT; + + double halfRobotWidth = RobotPeer.WIDTH / 2; + double halfRobotHeight = RobotPeer.HEIGHT / 2; + + int sentryBorderSize = battle.getBattleRules().getSentryBorderSize(); + int sentryBorderMoveWidth = sentryBorderSize - RobotPeer.WIDTH; + int sentryBorderMoveHeight = sentryBorderSize - RobotPeer.HEIGHT; + + for (int j = 0; j < 1000; j++) { + double rndX = random.nextDouble(); + double rndY = random.nextDouble(); + + if (isSentryRobot()) { + boolean placeOnHorizontalBar = random.nextDouble() + <= ((double) battleRules.getBattlefieldWidth() + / (battleRules.getBattlefieldWidth() + battleRules.getBattlefieldHeight())); + + if (placeOnHorizontalBar) { + x = halfRobotWidth + rndX * maxWidth; + y = halfRobotHeight + (sentryBorderMoveHeight * (rndY * 2.0 - 1.0) + maxHeight) % maxHeight; + } else { + y = halfRobotHeight + rndY * maxHeight; + x = halfRobotWidth + (sentryBorderMoveWidth * (rndX * 2.0 - 1.0) + maxWidth) % maxWidth; + } + } else { + if (battle.countActiveSentries() > 0) { + int safeZoneWidth = battleRules.getBattlefieldWidth() - 2 * sentryBorderSize; + int safeZoneHeight = battleRules.getBattlefieldHeight() - 2 * sentryBorderSize; + + x = sentryBorderSize + RobotPeer.WIDTH + rndX * (safeZoneWidth - 2 * RobotPeer.WIDTH); + y = sentryBorderSize + RobotPeer.HEIGHT + rndY * (safeZoneHeight - 2 * RobotPeer.HEIGHT); + } else { + x = RobotPeer.WIDTH + rndX * (battleRules.getBattlefieldWidth() - 2 * RobotPeer.WIDTH); + y = RobotPeer.HEIGHT + rndY * (battleRules.getBattlefieldHeight() - 2 * RobotPeer.HEIGHT); + } + } + + bodyHeading = 2 * Math.PI * random.nextDouble(); + gunHeading = radarHeading = bodyHeading; + updateBoundingBox(); + + if (validSpot(robots)) { + break; + } + } + } + + setState(RobotState.ACTIVE); + + isWinner = false; + velocity = 0; + + energy = 100; + if (statics.isSentryRobot()) { + energy += 400; + } + if (statics.isTeamLeader()) { + energy += 100; + } + if (statics.isDroid()) { + energy += 20; + } + + gunHeat = 3; + + setHalt(false); + isExecFinishedAndDisabled = false; + isEnergyDrained = false; + + scan = false; + + inCollision = false; + + scanArc.setAngleStart(0); + scanArc.setAngleExtent(0); + scanArc.setFrame(-100, -100, 1, 1); + + lastExecutionTime = -1; + + status = new AtomicReference(); + + readoutEvents(); + readoutTeamMessages(); + readoutBullets(); + + battleText.setLength(0); + proxyText.setLength(0); + + // Prepare new execution commands, but copy the colors from the last commands. + // Bugfix [2628217] - Robot Colors don't stick between rounds. + ExecCommands newExecCommands = new ExecCommands(); + + newExecCommands.copyColors(commands.get()); + commands = new AtomicReference(newExecCommands); + } + + private boolean validSpot(List robots) { + for (RobotPeer otherRobot : robots) { + if (otherRobot != null && otherRobot != this) { + if (getBoundingBox().intersects(otherRobot.getBoundingBox())) { + return false; + } + } + } + return true; + } + + public void startRound(long waitMillis, int waitNanos) { + Logger.logMessage(".", false); + + statistics.reset(); + + ExecCommands newExecCommands = new ExecCommands(); + + // Copy the colors from the last commands. + // Bugfix [2628217] - Robot Colors don't stick between rounds. + newExecCommands.copyColors(commands.get()); + + currentCommands = newExecCommands; + + int others = battle.countActiveParticipants() - (isAlive() ? 1 : 0); + int numSentries = battle.countActiveSentries(); + + RobotStatus stat = HiddenAccess.createStatus(energy, x, y, bodyHeading, gunHeading, radarHeading, velocity, + currentCommands.getBodyTurnRemaining(), currentCommands.getRadarTurnRemaining(), + currentCommands.getGunTurnRemaining(), currentCommands.getDistanceRemaining(), gunHeat, others, numSentries, + battle.getRoundNum(), battle.getNumRounds(), battle.getTime()); + + status.set(stat); + robotProxy.startRound(currentCommands, stat); + + synchronized (isSleeping) { + try { + // Wait for the robot to go to sleep (take action) + isSleeping.wait(waitMillis, waitNanos); + } catch (InterruptedException e) { + logMessage("Wait for " + getName() + " interrupted."); + + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + } + } + if (!isSleeping() && !battle.isDebugging()) { + logMessage("\n" + getName() + " still has not started after " + waitMillis + " ms... giving up."); + } + } + + public void performLoadCommands() { + currentCommands = commands.get(); + + fireBullets(currentCommands.getBullets()); + + if (currentCommands.isScan()) { + scan = true; + } + + if (currentCommands.isIORobot()) { + isIORobot = true; + } + + if (currentCommands.isMoved()) { + currentCommands.setMoved(false); + } + } + + private void fireBullets(List bulletCommands) { + BulletPeer newBullet = null; + + for (BulletCommand bulletCmd : bulletCommands) { + if (Double.isNaN(bulletCmd.getPower())) { + println("SYSTEM: You cannot call fire(NaN)"); + continue; + } + if (gunHeat > 0 || energy == 0) { + return; + } + + double firePower = min(energy, + min(max(bulletCmd.getPower(), Rules.MIN_BULLET_POWER), Rules.MAX_BULLET_POWER)); + + updateEnergy(-firePower); + + gunHeat += Rules.getGunHeat(firePower); + + newBullet = new BulletPeer(this, battleRules, bulletCmd.getBulletId()); + + newBullet.setPower(firePower); + if (!turnedRadarWithGun || !bulletCmd.isFireAssistValid() || statics.isAdvancedRobot()) { + newBullet.setHeading(gunHeading); + } else { + newBullet.setHeading(bulletCmd.getFireAssistAngle()); + } + newBullet.setX(x); + newBullet.setY(y); + } + // there is only last bullet in one turn + if (newBullet != null) { + // newBullet.update(robots, bullets); + battle.addBullet(newBullet); + } + } + + public final void performMove(List robots, double zapEnergy) { + + // Reset robot state to active if it is not dead + if (isDead()) { + return; + } + + setState(RobotState.ACTIVE); + + updateGunHeat(); + + lastHeading = bodyHeading; + lastGunHeading = gunHeading; + lastRadarHeading = radarHeading; + final double lastX = x; + final double lastY = y; + + if (!inCollision) { + updateHeading(); + } + + updateGunHeading(); + updateRadarHeading(); + updateMovement(); + + // At this point, robot has turned then moved. + // We could be touching a wall or another bot... + + // First and foremost, we can never go through a wall: + checkWallCollision(); + + // If this robot is a border sentry robot then check if it hits its "range border" + if (isSentryRobot()) { + checkSentryOutsideBorder(); + } + + // Now check for robot collision + checkRobotCollision(robots); + + // Scan false means robot did not call scan() manually. + // But if we're moving, scan + if (!scan) { + scan = (lastHeading != bodyHeading || lastGunHeading != gunHeading || lastRadarHeading != radarHeading + || lastX != x || lastY != y); + } + + if (isDead()) { + return; + } + + // zap + if (zapEnergy != 0) { + zap(zapEnergy); + } + } + + public void performScan(List robots) { + if (isDead()) { + return; + } + + turnedRadarWithGun = false; + // scan + if (scan) { + scan(lastRadarHeading, robots); + turnedRadarWithGun = (lastGunHeading == lastRadarHeading) && (gunHeading == radarHeading); + scan = false; + } + + // dispatch messages + if (statics.isTeamRobot() && teamPeer != null) { + for (TeamMessage teamMessage : currentCommands.getTeamMessages()) { + for (RobotPeer member : teamPeer) { + if (checkDispatchToMember(member, teamMessage.recipient)) { + member.addTeamMessage(teamMessage); + } + } + } + } + currentCommands = null; + lastHeading = -1; + lastGunHeading = -1; + lastRadarHeading = -1; + } + + private void addTeamMessage(TeamMessage message) { + final List queue = teamMessages.get(); + + queue.add(message); + } + + private boolean checkDispatchToMember(RobotPeer member, String recipient) { + if (member.isAlive()) { + if (recipient == null) { + if (member != this) { + return true; + } + } else { + final int nl = recipient.length(); + final String currentName = member.statics.getName(); + + if ((currentName.length() >= nl && currentName.substring(0, nl).equals(recipient))) { + return true; + } + + final String currentClassName = member.statics.getFullClassName(); + + if ((currentClassName.length() >= nl && currentClassName.substring(0, nl).equals(recipient))) { + return true; + } + + } + } + return false; + } + + public String getNameForEvent(RobotPeer otherRobot) { + if (battleRules.getHideEnemyNames() && !isTeamMate(otherRobot)) { + return otherRobot.getAnnonymousName(); + } + return otherRobot.getName(); + } + + private void checkRobotCollision(List robots) { + inCollision = false; + + for (RobotPeer otherRobot : robots) { + if (!(otherRobot == null || otherRobot == this || otherRobot.isDead()) + && boundingBox.intersects(otherRobot.boundingBox)) { + // Bounce back + double angle = atan2(otherRobot.x - x, otherRobot.y - y); + + double movedx = velocity * sin(bodyHeading); + double movedy = velocity * cos(bodyHeading); + + boolean atFault; + double bearing = normalRelativeAngle(angle - bodyHeading); + + if ((velocity > 0 && bearing > -PI / 2 && bearing < PI / 2) + || (velocity < 0 && (bearing < -PI / 2 || bearing > PI / 2))) { + + inCollision = true; + atFault = true; + velocity = 0; + currentCommands.setDistanceRemaining(0); + x -= movedx; + y -= movedy; + + boolean teamFire = (teamPeer != null && teamPeer == otherRobot.teamPeer); + + if (!teamFire && !otherRobot.isSentryRobot()) { + statistics.scoreRammingDamage(otherRobot.getName()); + } + + this.updateEnergy(-Rules.ROBOT_HIT_DAMAGE); + otherRobot.updateEnergy(-Rules.ROBOT_HIT_DAMAGE); + + if (otherRobot.energy == 0) { + if (otherRobot.isAlive()) { + otherRobot.kill(); + if (!teamFire && !otherRobot.isSentryRobot()) { + final double bonus = statistics.scoreRammingKill(otherRobot.getName()); + + if (bonus > 0) { + println( + "SYSTEM: Ram bonus for killing " + this.getNameForEvent(otherRobot) + ": " + + (int) (bonus + .5)); + } + } + } + } + addEvent( + new HitRobotEvent(getNameForEvent(otherRobot), normalRelativeAngle(angle - bodyHeading), + otherRobot.energy, atFault)); + otherRobot.addEvent( + new HitRobotEvent(getNameForEvent(this), + normalRelativeAngle(PI + angle - otherRobot.getBodyHeading()), energy, false)); + } + } + } + if (inCollision) { + setState(RobotState.HIT_ROBOT); + } + } + + private void checkWallCollision() { + int minX = 0 + HALF_WIDTH_OFFSET; + int minY = 0 + HALF_HEIGHT_OFFSET; + int maxX = (int) getBattleFieldWidth() - HALF_WIDTH_OFFSET; + int maxY = (int) getBattleFieldHeight() - HALF_HEIGHT_OFFSET; + + boolean hitWall = false; + double adjustX = 0, adjustY = 0; + double angle = 0; + + if (x < minX) { + hitWall = true; + adjustX = minX - x; + angle = normalRelativeAngle(3 * PI / 2 - bodyHeading); + + } else if (x > maxX) { + hitWall = true; + adjustX = maxX - x; + angle = normalRelativeAngle(PI / 2 - bodyHeading); + + } else if (y < minY) { + hitWall = true; + adjustY = minY - y; + angle = normalRelativeAngle(PI - bodyHeading); + + } else if (y > maxY) { + hitWall = true; + adjustY = maxY - y; + angle = normalRelativeAngle(-bodyHeading); + } + + if (hitWall) { + addEvent(new HitWallEvent(angle)); + + // only fix both x and y values if hitting wall at an angle + if ((bodyHeading % (Math.PI / 2)) != 0) { + double tanHeading = tan(bodyHeading); + + // if it hits bottom or top wall + if (adjustX == 0) { + adjustX = adjustY * tanHeading; + } // if it hits a side wall + else if (adjustY == 0) { + adjustY = adjustX / tanHeading; + } // if the robot hits 2 walls at the same time (rare, but just in case) + else if (abs(adjustX / tanHeading) > abs(adjustY)) { + adjustY = adjustX / tanHeading; + } else if (abs(adjustY * tanHeading) > abs(adjustX)) { + adjustX = adjustY * tanHeading; + } + } + x += adjustX; + y += adjustY; + + if (x < minX) { + x = minX; + } else if (x > maxX) { + x = maxX; + } + if (y < minY) { + y = minY; + } else if (y > maxY) { + y = maxY; + } + + // Update energy, but do not reset inactiveTurnCount + if (statics.isAdvancedRobot()) { + setEnergy(energy - Rules.getWallHitDamage(velocity), false); + } + + updateBoundingBox(); + + currentCommands.setDistanceRemaining(0); + velocity = 0; + + setState(RobotState.HIT_WALL); + } + } + + private void checkSentryOutsideBorder() { + int range = battle.getBattleRules().getSentryBorderSize(); + + int minX = range - HALF_WIDTH_OFFSET; + int minY = range - HALF_HEIGHT_OFFSET; + int maxX = (int) getBattleFieldWidth() - range + HALF_WIDTH_OFFSET; + int maxY = (int) getBattleFieldHeight() - range + HALF_HEIGHT_OFFSET; + + boolean hitWall = false; + double adjustX = 0, adjustY = 0; + double angle = 0; + + boolean isOutsideBorder = x > minX && x < maxX && y > minY && y < maxY; + + if (isOutsideBorder) { + if ((x - minX) <= Rules.MAX_VELOCITY) { + hitWall = true; + adjustX = minX - x; + angle = normalRelativeAngle(PI / 2 - bodyHeading); + + } else if ((maxX - x) <= Rules.MAX_VELOCITY) { + hitWall = true; + adjustX = maxX - x; + angle = normalRelativeAngle(3 * PI / 2 - bodyHeading); + + } else if ((y - minY) <= Rules.MAX_VELOCITY) { + hitWall = true; + adjustY = minY - y; + angle = normalRelativeAngle(-bodyHeading); + + } else if ((maxY - y) <= Rules.MAX_VELOCITY) { + hitWall = true; + adjustY = maxY - y; + angle = normalRelativeAngle(PI - bodyHeading); + } + } + + if (hitWall) { + addEvent(new HitWallEvent(angle)); + + // only fix both x and y values if hitting wall at an angle + if ((bodyHeading % (Math.PI / 2)) != 0) { + double tanHeading = tan(bodyHeading); + + // if it hits bottom or top wall + if (adjustX == 0) { + adjustX = adjustY * tanHeading; + } // if it hits a side wall + else if (adjustY == 0) { + adjustY = adjustX / tanHeading; + } // if the robot hits 2 walls at the same time (rare, but just in case) + else if (abs(adjustX / tanHeading) > abs(adjustY)) { + adjustY = adjustX / tanHeading; + } else if (abs(adjustY * tanHeading) > abs(adjustX)) { + adjustX = adjustY * tanHeading; + } + } + + x += adjustX; + y += adjustY; + + if (isOutsideBorder) { + if ((x - minX) <= Rules.MAX_VELOCITY) { + x = minX; + } else if ((maxX - x) <= Rules.MAX_VELOCITY) { + x = maxX; + } + if ((y - minY) <= Rules.MAX_VELOCITY) { + y = minY; + } else if ((maxY - y) <= Rules.MAX_VELOCITY) { + y = maxY; + } + } + + // Update energy, but do not reset inactiveTurnCount + if (statics.isAdvancedRobot()) { + setEnergy(energy - Rules.getWallHitDamage(velocity), false); + } + + updateBoundingBox(); + + currentCommands.setDistanceRemaining(0); + velocity = 0; + + setState(RobotState.HIT_WALL); + } + } + + private double getBattleFieldHeight() { + return battleRules.getBattlefieldHeight(); + } + + private double getBattleFieldWidth() { + return battleRules.getBattlefieldWidth(); + } + + private void updateBoundingBox() { + boundingBox.setRect(x - HALF_WIDTH_OFFSET, y - HALF_HEIGHT_OFFSET, WIDTH, HEIGHT); + } + + // TODO: Only add events to robots that are alive? + Remove checks if the Robot is alive before adding the event? + public void addEvent(Event event) { + if (isRunning()) { + final EventQueue queue = events.get(); + + if ((queue.size() > EventManager.MAX_QUEUE_SIZE) + && !(event instanceof DeathEvent || event instanceof WinEvent || event instanceof SkippedTurnEvent)) { + println( + "Not adding to " + statics.getShortName() + "'s queue, exceeded " + EventManager.MAX_QUEUE_SIZE + + " events in queue."); + // clean up old stuff + queue.clear(battle.getTime() - EventManager.MAX_EVENT_STACK); + } else { + queue.add(event); + } + } + } + + private void updateGunHeading() { + if (currentCommands.getGunTurnRemaining() > 0) { + if (currentCommands.getGunTurnRemaining() < Rules.GUN_TURN_RATE_RADIANS) { + gunHeading += currentCommands.getGunTurnRemaining(); + radarHeading += currentCommands.getGunTurnRemaining(); + if (currentCommands.isAdjustRadarForGunTurn()) { + currentCommands.setRadarTurnRemaining( + currentCommands.getRadarTurnRemaining() - currentCommands.getGunTurnRemaining()); + } + currentCommands.setGunTurnRemaining(0); + } else { + gunHeading += Rules.GUN_TURN_RATE_RADIANS; + radarHeading += Rules.GUN_TURN_RATE_RADIANS; + currentCommands.setGunTurnRemaining(currentCommands.getGunTurnRemaining() - Rules.GUN_TURN_RATE_RADIANS); + if (currentCommands.isAdjustRadarForGunTurn()) { + currentCommands.setRadarTurnRemaining( + currentCommands.getRadarTurnRemaining() - Rules.GUN_TURN_RATE_RADIANS); + } + } + } else if (currentCommands.getGunTurnRemaining() < 0) { + if (currentCommands.getGunTurnRemaining() > -Rules.GUN_TURN_RATE_RADIANS) { + gunHeading += currentCommands.getGunTurnRemaining(); + radarHeading += currentCommands.getGunTurnRemaining(); + if (currentCommands.isAdjustRadarForGunTurn()) { + currentCommands.setRadarTurnRemaining( + currentCommands.getRadarTurnRemaining() - currentCommands.getGunTurnRemaining()); + } + currentCommands.setGunTurnRemaining(0); + } else { + gunHeading -= Rules.GUN_TURN_RATE_RADIANS; + radarHeading -= Rules.GUN_TURN_RATE_RADIANS; + currentCommands.setGunTurnRemaining(currentCommands.getGunTurnRemaining() + Rules.GUN_TURN_RATE_RADIANS); + if (currentCommands.isAdjustRadarForGunTurn()) { + currentCommands.setRadarTurnRemaining( + currentCommands.getRadarTurnRemaining() + Rules.GUN_TURN_RATE_RADIANS); + } + } + } + gunHeading = normalAbsoluteAngle(gunHeading); + } + + private void updateHeading() { + boolean normalizeHeading = true; + + double turnRate = min(currentCommands.getMaxTurnRate(), + (.4 + .6 * (1 - (abs(velocity) / Rules.MAX_VELOCITY))) * Rules.MAX_TURN_RATE_RADIANS); + + if (currentCommands.getBodyTurnRemaining() > 0) { + if (currentCommands.getBodyTurnRemaining() < turnRate) { + bodyHeading += currentCommands.getBodyTurnRemaining(); + gunHeading += currentCommands.getBodyTurnRemaining(); + radarHeading += currentCommands.getBodyTurnRemaining(); + if (currentCommands.isAdjustGunForBodyTurn()) { + currentCommands.setGunTurnRemaining( + currentCommands.getGunTurnRemaining() - currentCommands.getBodyTurnRemaining()); + } + if (currentCommands.isAdjustRadarForBodyTurn()) { + currentCommands.setRadarTurnRemaining( + currentCommands.getRadarTurnRemaining() - currentCommands.getBodyTurnRemaining()); + } + currentCommands.setBodyTurnRemaining(0); + } else { + bodyHeading += turnRate; + gunHeading += turnRate; + radarHeading += turnRate; + currentCommands.setBodyTurnRemaining(currentCommands.getBodyTurnRemaining() - turnRate); + if (currentCommands.isAdjustGunForBodyTurn()) { + currentCommands.setGunTurnRemaining(currentCommands.getGunTurnRemaining() - turnRate); + } + if (currentCommands.isAdjustRadarForBodyTurn()) { + currentCommands.setRadarTurnRemaining(currentCommands.getRadarTurnRemaining() - turnRate); + } + } + } else if (currentCommands.getBodyTurnRemaining() < 0) { + if (currentCommands.getBodyTurnRemaining() > -turnRate) { + bodyHeading += currentCommands.getBodyTurnRemaining(); + gunHeading += currentCommands.getBodyTurnRemaining(); + radarHeading += currentCommands.getBodyTurnRemaining(); + if (currentCommands.isAdjustGunForBodyTurn()) { + currentCommands.setGunTurnRemaining( + currentCommands.getGunTurnRemaining() - currentCommands.getBodyTurnRemaining()); + } + if (currentCommands.isAdjustRadarForBodyTurn()) { + currentCommands.setRadarTurnRemaining( + currentCommands.getRadarTurnRemaining() - currentCommands.getBodyTurnRemaining()); + } + currentCommands.setBodyTurnRemaining(0); + } else { + bodyHeading -= turnRate; + gunHeading -= turnRate; + radarHeading -= turnRate; + currentCommands.setBodyTurnRemaining(currentCommands.getBodyTurnRemaining() + turnRate); + if (currentCommands.isAdjustGunForBodyTurn()) { + currentCommands.setGunTurnRemaining(currentCommands.getGunTurnRemaining() + turnRate); + } + if (currentCommands.isAdjustRadarForBodyTurn()) { + currentCommands.setRadarTurnRemaining(currentCommands.getRadarTurnRemaining() + turnRate); + } + } + } else { + normalizeHeading = false; + } + + if (normalizeHeading) { + if (currentCommands.getBodyTurnRemaining() == 0) { + bodyHeading = normalNearAbsoluteAngle(bodyHeading); + } else { + bodyHeading = normalAbsoluteAngle(bodyHeading); + } + } + if (Double.isNaN(bodyHeading)) { + Logger.realErr.println("HOW IS HEADING NAN HERE"); + } + } + + private void updateRadarHeading() { + if (currentCommands.getRadarTurnRemaining() > 0) { + if (currentCommands.getRadarTurnRemaining() < Rules.RADAR_TURN_RATE_RADIANS) { + radarHeading += currentCommands.getRadarTurnRemaining(); + currentCommands.setRadarTurnRemaining(0); + } else { + radarHeading += Rules.RADAR_TURN_RATE_RADIANS; + currentCommands.setRadarTurnRemaining( + currentCommands.getRadarTurnRemaining() - Rules.RADAR_TURN_RATE_RADIANS); + } + } else if (currentCommands.getRadarTurnRemaining() < 0) { + if (currentCommands.getRadarTurnRemaining() > -Rules.RADAR_TURN_RATE_RADIANS) { + radarHeading += currentCommands.getRadarTurnRemaining(); + currentCommands.setRadarTurnRemaining(0); + } else { + radarHeading -= Rules.RADAR_TURN_RATE_RADIANS; + currentCommands.setRadarTurnRemaining( + currentCommands.getRadarTurnRemaining() + Rules.RADAR_TURN_RATE_RADIANS); + } + } + + radarHeading = normalAbsoluteAngle(radarHeading); + } + + /** + * Updates the robots movement. + * + * This is Nat Pavasants method described here: + * http://robowiki.net/wiki/User:Positive/Optimal_Velocity#Nat.27s_updateMovement + */ + private void updateMovement() { + double distance = currentCommands.getDistanceRemaining(); + + if (Double.isNaN(distance)) { + distance = 0; + } + + velocity = getNewVelocity(velocity, distance); + + // If we are over-driving our distance and we are now at velocity=0 + // then we stopped. + if (isNear(velocity, 0) && isOverDriving) { + currentCommands.setDistanceRemaining(0); + distance = 0; + isOverDriving = false; + } + + // If we are moving normally and the breaking distance is more + // than remaining distance, enabled the overdrive flag. + if (Math.signum(distance * velocity) != -1) { + if (getDistanceTraveledUntilStop(velocity) > Math.abs(distance)) { + isOverDriving = true; + } else { + isOverDriving = false; + } + } + + currentCommands.setDistanceRemaining(distance - velocity); + + if (velocity != 0) { + x += velocity * sin(bodyHeading); + y += velocity * cos(bodyHeading); + updateBoundingBox(); + } + } + + private double getDistanceTraveledUntilStop(double velocity) { + double distance = 0; + + velocity = Math.abs(velocity); + while (velocity > 0) { + distance += (velocity = getNewVelocity(velocity, 0)); + } + return distance; + } + + /** + * Returns the new velocity based on the current velocity and distance to move. + * + * @param velocity the current velocity + * @param distance the distance to move + * @return the new velocity based on the current velocity and distance to move + * + * This is Patrick Cupka (aka Voidious), Julian Kent (aka Skilgannon), and Positive's method described here: + * http://robowiki.net/wiki/User:Voidious/Optimal_Velocity#Hijack_2 + */ + private double getNewVelocity(double velocity, double distance) { + if (distance < 0) { + // If the distance is negative, then change it to be positive + // and change the sign of the input velocity and the result + return -getNewVelocity(-velocity, -distance); + } + + final double goalVel; + + if (distance == Double.POSITIVE_INFINITY) { + goalVel = currentCommands.getMaxVelocity(); + } else { + goalVel = Math.min(getMaxVelocity(distance), currentCommands.getMaxVelocity()); + } + + if (velocity >= 0) { + return Math.max(velocity - Rules.DECELERATION, Math.min(goalVel, velocity + Rules.ACCELERATION)); + } + // else + return Math.max(velocity - Rules.ACCELERATION, Math.min(goalVel, velocity + maxDecel(-velocity))); + } + + private final static double getMaxVelocity(double distance) { + final double decelTime = Math.max(1, Math.ceil(// sum of 0... decelTime, solving for decelTime using quadratic formula + (Math.sqrt((4 * 2 / Rules.DECELERATION) * distance + 1) - 1) / 2)); + + if (decelTime == Double.POSITIVE_INFINITY) { + return Rules.MAX_VELOCITY; + } + + final double decelDist = (decelTime / 2.0) * (decelTime - 1) // sum of 0..(decelTime-1) + * Rules.DECELERATION; + + return ((decelTime - 1) * Rules.DECELERATION) + ((distance - decelDist) / decelTime); + } + + private static double maxDecel(double speed) { + double decelTime = speed / Rules.DECELERATION; + double accelTime = (1 - decelTime); + + return Math.min(1, decelTime) * Rules.DECELERATION + Math.max(0, accelTime) * Rules.ACCELERATION; + } + + private void updateGunHeat() { + gunHeat -= battleRules.getGunCoolingRate(); + if (gunHeat < 0) { + gunHeat = 0; + } + } + + private void scan(double lastRadarHeading, List robots) { + if (statics.isDroid()) { + return; + } + + double startAngle = lastRadarHeading; + double scanRadians = getRadarHeading() - startAngle; + + // Check if we passed through 360 + if (scanRadians < -PI) { + scanRadians = 2 * PI + scanRadians; + } else if (scanRadians > PI) { + scanRadians = scanRadians - 2 * PI; + } + + // In our coords, we are scanning clockwise, with +y up + // In java coords, we are scanning counterclockwise, with +y down + // All we need to do is adjust our angle by -90 for this to work. + startAngle -= PI / 2; + + startAngle = normalAbsoluteAngle(startAngle); + + scanArc.setArc(x - Rules.RADAR_SCAN_RADIUS, y - Rules.RADAR_SCAN_RADIUS, 2 * Rules.RADAR_SCAN_RADIUS, + 2 * Rules.RADAR_SCAN_RADIUS, 180.0 * startAngle / PI, 180.0 * scanRadians / PI, Arc2D.PIE); + + for (RobotPeer otherRobot : robots) { + if (!(otherRobot == null || otherRobot == this || otherRobot.isDead()) + && intersects(scanArc, otherRobot.boundingBox)) { + double dx = otherRobot.x - x; + double dy = otherRobot.y - y; + double angle = atan2(dx, dy); + double dist = Math.hypot(dx, dy); + + final ScannedRobotEvent event = new ScannedRobotEvent(getNameForEvent(otherRobot), otherRobot.energy, + normalRelativeAngle(angle - getBodyHeading()), dist, otherRobot.getBodyHeading(), + otherRobot.getVelocity(), otherRobot.isSentryRobot()); + + addEvent(event); + } + } + } + + private boolean intersects(Arc2D arc, Rectangle2D rect) { + return (rect.intersectsLine(arc.getCenterX(), arc.getCenterY(), arc.getStartPoint().getX(), + arc.getStartPoint().getY())) + || arc.intersects(rect); + } + + private void zap(double zapAmount) { + if (energy == 0) { + kill(); + return; + } + energy -= abs(zapAmount); + if (energy < .1) { + energy = 0; + currentCommands.setDistanceRemaining(0); + currentCommands.setBodyTurnRemaining(0); + } + } + + public void setRunning(boolean value) { + isRunning.set(value); + } + + public void drainEnergy() { + setEnergy(0, true); + isEnergyDrained = true; + } + + public void punishBadBehavior(BadBehavior badBehavior) { + kill(); // Bug fix [2828479] - Missed onRobotDeath events + + statistics.setInactive(); + + final IRobotItem repositoryItem = (IRobotItem) HiddenAccess.getFileSpecification(robotSpecification); + + StringBuffer message = new StringBuffer(getName()).append(' '); + + boolean disableInRepository = false; // Per default, robots are not disabled in the repository + + switch (badBehavior) { + case CANNOT_START: + message.append("could not be started or loaded."); + disableInRepository = true; // Disable in repository when it cannot be started anyways + break; + + case UNSTOPPABLE: + message.append("cannot be stopped."); + break; + + case SKIPPED_TOO_MANY_TURNS: + message.append("has skipped too many turns."); + break; + + case SECURITY_VIOLATION: + message.append("has caused a security violation."); + disableInRepository = true; // No mercy here! + break; + } + + if (disableInRepository) { + repositoryItem.setValid(false); + message.append(" This ").append(repositoryItem.isTeam() ? "team" : "robot").append( + " has been banned and will not be allowed to participate in battles."); + } + + logMessage(message.toString()); + } + + void updateEnergy(double delta) { + if ((!isExecFinishedAndDisabled && !isEnergyDrained) || delta < 0) { + setEnergy(energy + delta, true); + } + } + + private void setEnergy(double newEnergy, boolean resetInactiveTurnCount) { + if (resetInactiveTurnCount && (energy != newEnergy)) { + battle.resetInactiveTurnCount(energy - newEnergy); + } + energy = newEnergy; + if (energy < .01) { + energy = 0; + ExecCommands localCommands = commands.get(); + + localCommands.setDistanceRemaining(0); + localCommands.setBodyTurnRemaining(0); + } + } + + public void setWinner(boolean newWinner) { + isWinner = newWinner; + } + + public void kill() { + battle.resetInactiveTurnCount(10.0); + if (isAlive()) { + addEvent(new DeathEvent()); + if (statics.isTeamLeader()) { + for (RobotPeer teammate : teamPeer) { + if (teammate.isAlive() && teammate != this) { + teammate.updateEnergy(-30); + + BulletPeer sBullet = new BulletPeer(this, battleRules, 0); + sBullet.setState(BulletState.HIT_VICTIM); + sBullet.setX(teammate.x); + sBullet.setY(teammate.y); + sBullet.setVictim(teammate); + sBullet.setPower(4); + battle.addBullet(sBullet); + } + } + } + battle.registerDeathRobot(this); + + // 'fake' bullet for explosion on self + final ExplosionPeer fake = new ExplosionPeer(this, battleRules); + + battle.addBullet(fake); + } + updateEnergy(-energy); + + setState(RobotState.DEAD); + } + + public void waitForStop() { + robotProxy.waitForStopThread(); + } + + /** + * Clean things up removing all references to the robot. + */ + public void cleanup() { + battle = null; + + if (robotProxy != null) { + robotProxy.cleanup(); + robotProxy = null; + } + + if (statistics != null) { + statistics.cleanup(); + statistics = null; + } + + status = null; + commands = null; + events = null; + teamMessages = null; + bulletUpdates = null; + battleText.setLength(0); + proxyText.setLength(0); + statics = null; + battleRules = null; + } + + public Object getGraphicsCalls() { + return commands.get().getGraphicsCalls(); + } + + public boolean isTryingToPaint() { + return commands.get().isTryingToPaint(); + } + + public List getDebugProperties() { + return commands.get().getDebugProperties(); + } + + public void publishStatus(long currentTurn) { + + final ExecCommands currentCommands = commands.get(); + + int others = battle.countActiveParticipants() - (isDead() || isSentryRobot() ? 0 : 1); + int numSentries = battle.countActiveSentries(); + + RobotStatus stat = HiddenAccess.createStatus(energy, x, y, bodyHeading, gunHeading, radarHeading, velocity, + currentCommands.getBodyTurnRemaining(), currentCommands.getRadarTurnRemaining(), + currentCommands.getGunTurnRemaining(), currentCommands.getDistanceRemaining(), gunHeat, others, numSentries, + battle.getRoundNum(), battle.getNumRounds(), battle.getTime()); + + status.set(stat); + } + + void addBulletStatus(BulletStatus bulletStatus) { + if (isAlive()) { + bulletUpdates.get().add(bulletStatus); + } + } + + public int compareTo(ContestantPeer cp) { + double myScore = statistics.getTotalScore(); + double hisScore = cp.getStatistics().getTotalScore(); + + if (statistics.isInRound()) { + myScore += statistics.getCurrentScore(); + hisScore += cp.getStatistics().getCurrentScore(); + } + if (myScore < hisScore) { + return -1; + } + if (myScore > hisScore) { + return 1; + } + return 0; + } + + @Override + public String toString() { + return statics.getShortName() + "(" + (int) energy + ") X" + (int) x + " Y" + (int) y + " " + state.toString() + + (isSleeping() ? " sleeping " : "") + (isRunning() ? " running" : "") + (isHalt() ? " halted" : ""); + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/RobotStatistics.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/RobotStatistics.java new file mode 100644 index 0000000..0cb9c3f --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/RobotStatistics.java @@ -0,0 +1,298 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.peer; + + +import robocode.BattleResults; +import java.util.Map; +import java.util.HashMap; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Luis Crespo (contributor) + * @author Titus Chen (contributor) + * @author Robert D. Maupin (contributor) + * @author Nathaniel Troutman (contributor) + */ +public class RobotStatistics implements ContestantStatistics { + + private final RobotPeer robotPeer; + private int rank; + private final int numberOfRobots; + private boolean isActive; + private boolean isInRound; + + private double survivalScore; + private double lastSurvivorBonus; + private double bulletDamageScore; + private double bulletKillBonus; + private double rammingDamageScore; + private double rammingKillBonus; + + private Map robotDamageMap; + + private double totalScore; + private double totalSurvivalScore; + private double totalLastSurvivorBonus; + private double totalBulletDamageScore; + private double totalBulletKillBonus; + private double totalRammingDamageScore; + private double totalRammingKillBonus; + + private int totalFirsts; + private int totalSeconds; + private int totalThirds; + + RobotStatistics(RobotPeer robotPeer, int numberOfRobots) { + super(); + this.robotPeer = robotPeer; + this.numberOfRobots = numberOfRobots; + } + + public void setRank(int rank) { + this.rank = rank; + } + + void reset() { + resetScores(); + + isActive = true; + isInRound = true; + } + + private void resetScores() { + robotDamageMap = null; + survivalScore = 0; + lastSurvivorBonus = 0; + bulletDamageScore = 0; + bulletKillBonus = 0; + rammingDamageScore = 0; + rammingKillBonus = 0; + } + + public void generateTotals() { + totalSurvivalScore += survivalScore; + totalLastSurvivorBonus += lastSurvivorBonus; + totalBulletDamageScore += bulletDamageScore; + totalBulletKillBonus += bulletKillBonus; + totalRammingDamageScore += rammingDamageScore; + totalRammingKillBonus += rammingKillBonus; + + totalScore = robotPeer.isSentryRobot() + ? 0 + : totalBulletDamageScore + totalRammingDamageScore + totalSurvivalScore + totalRammingKillBonus + + totalBulletKillBonus + totalLastSurvivorBonus; + + isInRound = false; + } + + public double getTotalScore() { + return totalScore; + } + + public double getTotalSurvivalScore() { + return totalSurvivalScore; + } + + public double getTotalLastSurvivorBonus() { + return totalLastSurvivorBonus; + } + + public double getTotalBulletDamageScore() { + return totalBulletDamageScore; + } + + public double getTotalBulletKillBonus() { + return totalBulletKillBonus; + } + + public double getTotalRammingDamageScore() { + return totalRammingDamageScore; + } + + public double getTotalRammingKillBonus() { + return totalRammingKillBonus; + } + + public int getTotalFirsts() { + return totalFirsts; + } + + public int getTotalSeconds() { + return totalSeconds; + } + + public int getTotalThirds() { + return totalThirds; + } + + public double getCurrentScore() { + return robotPeer.isSentryRobot() + ? 0 + : (bulletDamageScore + rammingDamageScore + survivalScore + rammingKillBonus + bulletKillBonus + + lastSurvivorBonus); + } + + public double getCurrentSurvivalScore() { + return survivalScore; + } + + public double getCurrentSurvivalBonus() { + return lastSurvivorBonus; + } + + public double getCurrentBulletDamageScore() { + return bulletDamageScore; + } + + public double getCurrentBulletKillBonus() { + return bulletKillBonus; + } + + public double getCurrentRammingDamageScore() { + return rammingDamageScore; + } + + public double getCurrentRammingKillBonus() { + return rammingKillBonus; + } + + public void scoreSurvival() { + if (isActive && !robotPeer.isSentryRobot()) { + survivalScore += 50; + } + } + + public void scoreLastSurvivor() { + if (isActive && !robotPeer.isSentryRobot()) { + int enemyCount = numberOfRobots - 1; + + if (robotPeer.getTeamPeer() != null) { + enemyCount -= (robotPeer.getTeamPeer().size() - 1); + } + + lastSurvivorBonus += 10 * enemyCount; + + if ((robotPeer.getTeamPeer() == null || robotPeer.isTeamLeader())) { + totalFirsts++; + } + } + } + + void scoreBulletDamage(String robot, double damage) { + if (isActive) { + incrementRobotDamage(robot, damage); + bulletDamageScore += damage; + } + } + + double scoreBulletKill(String robot) { + if (isActive) { + double bonus; + + if (robotPeer.getTeamPeer() == null) { + bonus = getRobotDamage(robot) * 0.20; + } else { + bonus = 0; + for (RobotPeer teammate : robotPeer.getTeamPeer()) { + bonus += teammate.getRobotStatistics().getRobotDamage(robot) * 0.20; + } + } + + bulletKillBonus += bonus; + return bonus; + } + return 0; + } + + void scoreRammingDamage(String robot) { + if (isActive) { + incrementRobotDamage(robot, robocode.Rules.ROBOT_HIT_DAMAGE); + rammingDamageScore += robocode.Rules.ROBOT_HIT_BONUS; + } + } + + double scoreRammingKill(String robot) { + if (isActive) { + double bonus; + + if (robotPeer.getTeamPeer() == null) { + bonus = getRobotDamage(robot) * 0.30; + } else { + bonus = 0; + for (RobotPeer teammate : robotPeer.getTeamPeer()) { + bonus += teammate.getRobotStatistics().getRobotDamage(robot) * 0.30; + } + } + rammingKillBonus += bonus; + return bonus; + } + return 0; + } + + public void scoreRobotDeath(int enemiesRemaining) { + if (!robotPeer.isSentryRobot()) { + switch (enemiesRemaining) { + case 0: + if (!robotPeer.isWinner()) { + totalFirsts++; + } + break; + + case 1: + totalSeconds++; + break; + + case 2: + totalThirds++; + break; + } + } + } + + public void scoreFirsts() { + if (isActive && !robotPeer.isSentryRobot()) { + totalFirsts++; + } + } + + void setInactive() { + resetScores(); + isActive = false; + } + + public BattleResults getFinalResults() { + return new BattleResults(robotPeer.getTeamName(), rank, totalScore, totalSurvivalScore, totalLastSurvivorBonus, + totalBulletDamageScore, totalBulletKillBonus, totalRammingDamageScore, totalRammingKillBonus, totalFirsts, + totalSeconds, totalThirds); + } + + private double getRobotDamage(String robot) { + if (robotDamageMap == null) { + robotDamageMap = new HashMap(); + } + Double damage = robotDamageMap.get(robot); + + return (damage != null) ? damage : 0; + } + + private void incrementRobotDamage(String robot, double damage) { + double newDamage = getRobotDamage(robot) + damage; + + robotDamageMap.put(robot, newDamage); + } + + void cleanup() {// Do nothing, for now + } + + public boolean isInRound() { + return isInRound; + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/TeamPeer.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/TeamPeer.java new file mode 100644 index 0000000..7e384bb --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/TeamPeer.java @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.peer; + + +import java.util.ArrayList; +import java.util.List; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + * @author Pavel Savara (contributor) + */ +@SuppressWarnings("serial") +public class TeamPeer extends ArrayList implements ContestantPeer { + + private final List memberNames; + private final String name; + private final int teamIndex; + private RobotPeer teamLeader; + private final TeamStatistics teamStatistics; + + public TeamPeer(String name, List memberNames, int teamIndex) { + this.name = name; + this.teamIndex = teamIndex; + this.memberNames = memberNames; + this.teamStatistics = new TeamStatistics(this); + } + + public int compareTo(ContestantPeer cp) { + double myScore = teamStatistics.getTotalScore(); + double hisScore = cp.getStatistics().getTotalScore(); + + if (teamLeader != null && teamLeader.getRobotStatistics().isInRound()) { + myScore += teamStatistics.getCurrentScore(); + hisScore += cp.getStatistics().getCurrentScore(); + } + if (myScore < hisScore) { + return -1; + } + if (myScore > hisScore) { + return 1; + } + return 0; + } + + public ContestantStatistics getStatistics() { + return teamStatistics; + } + + public String getName() { + return name; + } + + public int getRobotIndex() { + return -1; + } + + public int getTeamIndex() { + return teamIndex; + } + + public int getContestantIndex() { + return teamIndex; // This contestant is always a team for this TeamPeer + } + + public List getMemberNames() { + return memberNames; + } + + public RobotPeer getTeamLeader() { + return teamLeader; + } + + @Override + public boolean add(RobotPeer r) { + if (teamLeader == null) { + teamLeader = r; + } + return super.add(r); + } + + @Override + public String toString() { + return " [" + size() + "] " + getName(); + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/TeamStatistics.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/TeamStatistics.java new file mode 100644 index 0000000..18316bf --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/peer/TeamStatistics.java @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.peer; + + +import robocode.BattleResults; + + +/** + * @author Mathew A. Nelson (original) + * @author Luis Crespo (contributor) + * @author Flemming N. Larsen (contributor) + */ +class TeamStatistics implements ContestantStatistics { + + private final TeamPeer teamPeer; + private int rank; + + TeamStatistics(TeamPeer teamPeer) { + this.teamPeer = teamPeer; + } + + public void setRank(int rank) { + this.rank = rank; + } + + public double getTotalScore() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalScore(); + } + return d; + } + + public double getTotalSurvivalScore() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalSurvivalScore(); + } + return d; + } + + public double getTotalLastSurvivorBonus() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalLastSurvivorBonus(); + } + return d; + } + + public double getTotalBulletDamageScore() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalBulletDamageScore(); + } + return d; + } + + public double getTotalBulletKillBonus() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalBulletKillBonus(); + } + return d; + } + + public double getTotalRammingDamageScore() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalRammingDamageScore(); + } + return d; + } + + public double getTotalRammingKillBonus() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalRammingKillBonus(); + } + return d; + } + + public int getTotalFirsts() { + int d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalFirsts(); + } + return d; + } + + public int getTotalSeconds() { + int d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalSeconds(); + } + return d; + } + + public int getTotalThirds() { + int d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getTotalThirds(); + } + return d; + } + + public double getCurrentScore() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getCurrentScore(); + } + return d; + } + + public double getCurrentSurvivalScore() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getCurrentSurvivalScore(); + } + return d; + } + + public double getCurrentSurvivalBonus() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getCurrentSurvivalBonus(); + } + return d; + } + + public double getCurrentBulletDamageScore() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getCurrentBulletDamageScore(); + } + return d; + } + + public double getCurrentBulletKillBonus() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getCurrentBulletKillBonus(); + } + return d; + } + + public double getCurrentRammingDamageScore() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getCurrentRammingDamageScore(); + } + return d; + } + + public double getCurrentRammingKillBonus() { + double d = 0; + + for (RobotPeer teammate : teamPeer) { + d += teammate.getRobotStatistics().getCurrentRammingKillBonus(); + } + return d; + } + + public BattleResults getFinalResults() { + return new BattleResults(teamPeer.getName(), rank, getTotalScore(), getTotalSurvivalScore(), + getTotalLastSurvivorBonus(), getTotalBulletDamageScore(), getTotalBulletKillBonus(), + getTotalRammingDamageScore(), getTotalRammingKillBonus(), getTotalFirsts(), getTotalSeconds(), + getTotalThirds()); + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/BulletSnapshot.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/BulletSnapshot.java new file mode 100644 index 0000000..14fcfa9 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/BulletSnapshot.java @@ -0,0 +1,360 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.snapshot; + + +import net.sf.robocode.battle.peer.BulletPeer; +import net.sf.robocode.battle.peer.ExplosionPeer; +import net.sf.robocode.battle.peer.RobotPeer; +import net.sf.robocode.peer.ExecCommands; +import net.sf.robocode.serialization.IXmlSerializable; +import net.sf.robocode.serialization.XmlReader; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.serialization.XmlWriter; +import robocode.control.snapshot.BulletState; +import robocode.control.snapshot.IBulletSnapshot; + +import java.io.IOException; + + +/** + * A snapshot of a bullet at a specific time instant in a battle. + * The snapshot contains a snapshot of the bullet data at that specific time. + * + * @author Flemming N. Larsen (original) + * @author Pavel Savara (contributor) + * + * @since 1.6.1 + */ +final class BulletSnapshot implements java.io.Serializable, IXmlSerializable, IBulletSnapshot { + + private static final long serialVersionUID = 2L; + + /** The bullet state */ + private BulletState state; + + /** The bullet power */ + private double power; + + /** The x position */ + private double x; + + /** The y position */ + private double y; + + /** The x painting position (due to offset on robot when bullet hits a robot) */ + private double paintX; + + /** The y painting position (due to offset on robot when bullet hits a robot) */ + private double paintY; + + /** The ARGB color of the bullet */ + private int color = ExecCommands.defaultBulletColor; + + /** The current frame number to display, i.e. when the bullet explodes */ + private int frame; + + /** Flag specifying if this bullet has turned into an explosion */ + private boolean isExplosion; + + /** Index to which explosion image that must be rendered */ + private int explosionImageIndex; + + private int bulletId; + + private int victimIndex = -1; + + private int ownerIndex; + + private double heading; + + /** + * Creates a snapshot of a bullet that must be filled out with data later. + */ + public BulletSnapshot() { + state = BulletState.INACTIVE; + ownerIndex = -1; + victimIndex = -1; + explosionImageIndex = -1; + heading = Double.NaN; + power = Double.NaN; + } + + /** + * Creates a snapshot of a bullet. + * + * @param bullet the bullet to make a snapshot of. + */ + BulletSnapshot(BulletPeer bullet) { + state = bullet.getState(); + + power = bullet.getPower(); + + x = bullet.getX(); + y = bullet.getY(); + + paintX = bullet.getPaintX(); + paintY = bullet.getPaintY(); + + color = bullet.getColor(); + + frame = bullet.getFrame(); + + isExplosion = (bullet instanceof ExplosionPeer); + explosionImageIndex = bullet.getExplosionImageIndex(); + + bulletId = bullet.getBulletId(); + + final RobotPeer victim = bullet.getVictim(); + + if (victim != null) { + victimIndex = victim.getRobotIndex(); + } + + ownerIndex = bullet.getOwner().getRobotIndex(); + + heading = bullet.getHeading(); + } + + @Override + public String toString() { + return ownerIndex + "-" + bulletId + " (" + (int) power + ") X" + (int) x + " Y" + (int) y + " " + + state.toString(); + } + + /** + * {@inheritDoc} + */ + public int getBulletId() { + return bulletId; + } + + /** + * {@inheritDoc} + */ + public BulletState getState() { + return state; + } + + /** + * {@inheritDoc} + */ + public double getPower() { + return power; + } + + /** + * {@inheritDoc} + */ + public double getX() { + return x; + } + + /** + * {@inheritDoc} + */ + public double getY() { + return y; + } + + /** + * {@inheritDoc} + */ + public double getPaintX() { + return paintX; + } + + /** + * {@inheritDoc} + */ + public double getPaintY() { + return paintY; + } + + /** + * {@inheritDoc} + */ + public int getColor() { + return color; + } + + /** + * {@inheritDoc} + */ + public int getFrame() { + return frame; + } + + /** + * {@inheritDoc} + */ + public boolean isExplosion() { + return isExplosion; + } + + /** + * {@inheritDoc} + */ + public int getExplosionImageIndex() { + return explosionImageIndex; + } + + /** + * {@inheritDoc} + */ + public double getHeading() { + return heading; + } + + /** + * {@inheritDoc} + */ + public int getVictimIndex() { + return victimIndex; + } + + /** + * {@inheritDoc} + */ + public int getOwnerIndex() { + return ownerIndex; + } + + /** + * {@inheritDoc} + */ + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException { + writer.startElement(options.shortAttributes ? "b" : "bullet"); { + writer.writeAttribute("id", ownerIndex + "-" + bulletId); + if (!options.skipExploded || state != BulletState.MOVING) { + writer.writeAttribute(options.shortAttributes ? "s" : "state", state.toString()); + writer.writeAttribute(options.shortAttributes ? "p" : "power", power, options.trimPrecision); + } + if (state == BulletState.HIT_VICTIM) { + writer.writeAttribute(options.shortAttributes ? "v" : "victim", victimIndex); + } + if (state == BulletState.FIRED) { + writer.writeAttribute(options.shortAttributes ? "o" : "owner", ownerIndex); + writer.writeAttribute(options.shortAttributes ? "h" : "heading", heading, options.trimPrecision); + } + writer.writeAttribute("x", paintX, options.trimPrecision); + writer.writeAttribute("y", paintY, options.trimPrecision); + if (!options.skipNames) { + if (color != ExecCommands.defaultBulletColor) { + writer.writeAttribute(options.shortAttributes ? "c" : "color", + Integer.toHexString(color).toUpperCase()); + } + } + if (!options.skipExploded) { + if (frame != 0) { + writer.writeAttribute("frame", frame); + } + if (isExplosion) { + writer.writeAttribute("isExplosion", true); + writer.writeAttribute("explosion", explosionImageIndex); + } + } + if (!options.skipVersion) { + writer.writeAttribute("ver", serialVersionUID); + } + } + writer.endElement(); + } + + /** + * {@inheritDoc} + */ + public XmlReader.Element readXml(XmlReader reader) { + return reader.expect("bullet", "b", new XmlReader.Element() { + public IXmlSerializable read(XmlReader reader) { + final BulletSnapshot snapshot = new BulletSnapshot(); + + reader.expect("id", new XmlReader.Attribute() { + public void read(String value) { + String[] parts = value.split("-"); + + snapshot.ownerIndex = Integer.parseInt(parts[0]); + snapshot.bulletId = Integer.parseInt(parts[1]); + } + }); + + reader.expect("state", "s", new XmlReader.Attribute() { + public void read(String value) { + snapshot.state = BulletState.valueOf(value); + } + }); + + reader.expect("power", "p", new XmlReader.Attribute() { + public void read(String value) { + snapshot.power = Double.parseDouble(value); + } + }); + + reader.expect("heading", "h", new XmlReader.Attribute() { + public void read(String value) { + snapshot.heading = Double.parseDouble(value); + } + }); + + reader.expect("victim", "v", new XmlReader.Attribute() { + public void read(String value) { + snapshot.victimIndex = Integer.parseInt(value); + } + }); + + reader.expect("owner", "o", new XmlReader.Attribute() { + public void read(String value) { + snapshot.ownerIndex = Integer.parseInt(value); + } + }); + + reader.expect("x", new XmlReader.Attribute() { + public void read(String value) { + snapshot.x = Double.parseDouble(value); + snapshot.paintX = snapshot.x; + } + }); + + reader.expect("y", new XmlReader.Attribute() { + public void read(String value) { + snapshot.y = Double.parseDouble(value); + snapshot.paintY = snapshot.y; + } + }); + + reader.expect("color", "c", new XmlReader.Attribute() { + public void read(String value) { + snapshot.color = Long.valueOf(value.toUpperCase(), 16).intValue(); + } + }); + + reader.expect("isExplosion", new XmlReader.Attribute() { + public void read(String value) { + snapshot.isExplosion = Boolean.parseBoolean(value); + if (snapshot.isExplosion && snapshot.state == null) { + snapshot.state = BulletState.EXPLODED; + } + } + }); + + reader.expect("explosion", new XmlReader.Attribute() { + public void read(String value) { + snapshot.explosionImageIndex = Integer.parseInt(value); + } + }); + + reader.expect("frame", new XmlReader.Attribute() { + public void read(String value) { + snapshot.frame = Integer.parseInt(value); + } + }); + return snapshot; + } + }); + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/RobotSnapshot.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/RobotSnapshot.java new file mode 100644 index 0000000..c83404d --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/RobotSnapshot.java @@ -0,0 +1,729 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.snapshot; + + +import net.sf.robocode.battle.peer.RobotPeer; +import net.sf.robocode.peer.DebugProperty; +import net.sf.robocode.peer.ExecCommands; +import net.sf.robocode.serialization.IXmlSerializable; +import net.sf.robocode.serialization.XmlReader; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.serialization.XmlWriter; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.snapshot.IScoreSnapshot; +import robocode.control.snapshot.RobotState; + +import java.awt.geom.Arc2D; +import java.io.IOException; +import java.io.Serializable; +import java.util.List; +import java.util.Map; + + +/** + * A snapshot of a robot at a specific time instant in a battle. + * The snapshot contains a snapshot of the robot data at that specific time. + * + * @author Flemming N. Larsen (original) + * @author Pavel Savara (contributor) + * + * @since 1.6.1 + */ +public final class RobotSnapshot implements Serializable, IXmlSerializable, IRobotSnapshot { + + private static final long serialVersionUID = 2L; + + /** The name of the robot */ + private String name; + + /** The short name of the robot */ + private String shortName; + + /** Very short name of the robot */ + private String veryShortName; + + /** Very short name of the team leader robot (might be null) */ + private String teamName; + + /** The unique robot index */ + private int robotIndex; + + /** The team index for the robot */ + private int teamIndex; + + /** The robot state */ + private RobotState state; + + /** The energy level of the robot */ + private double energy; + + /** The velocity of the robot */ + private double velocity; + + /** The gun heat level of the robot */ + private double gunHeat; + + /** The body heading in radians */ + private double bodyHeading; + + /** The gun heading in radians */ + private double gunHeading; + + /** The radar heading in radians */ + private double radarHeading; + + /** The X position */ + private double x; + + /** The Y position */ + private double y; + + /** The ARGB color of the body */ + private int bodyColor = ExecCommands.defaultBodyColor; + + /** The ARGB color of the gun */ + private int gunColor = ExecCommands.defaultGunColor; + + /** The ARGB color of the radar */ + private int radarColor = ExecCommands.defaultRadarColor; + + /** The ARGB color of the scan arc */ + private int scanColor = ExecCommands.defaultScanColor; + + /** Flag specifying if this robot is a Droid */ + private boolean isDroid; + + /** Flag specifying if this robot is a SentryRobot */ + private boolean isSentryRobot; + + /** Flag specifying if this robot is a IPaintRobot or is invoking getGraphics() */ + private boolean isPaintRobot; + + /** Flag specifying if painting is enabled for this robot */ + private boolean isPaintEnabled; + + /** Flag specifying if RobocodeSG painting is enabled for this robot */ + private boolean isSGPaintEnabled; + + /** Snapshot of the scan arc */ + private SerializableArc scanArc; + + /** Snapshot of the object with queued calls for Graphics object */ + private Object graphicsCalls; + + /** Snapshot of debug properties */ + private DebugProperty[] debugProperties; + + /** Snapshot of the output print stream for this robot */ + private String outputStreamSnapshot; + + /** Snapshot of score of the robot */ + private IScoreSnapshot robotScoreSnapshot; + + /** + * Creates a snapshot of a robot that must be filled out with data later. + */ + public RobotSnapshot() { + state = RobotState.ACTIVE; + } + + /** + * Creates a snapshot of a robot. + * + * @param robot the robot to make a snapshot of. + * @param readoutText {@code true} if the output text from the robot must be included in the snapshot; + * {@code false} otherwise. + */ + RobotSnapshot(RobotPeer robot, boolean readoutText) { + name = robot.getName(); + shortName = robot.getShortName(); + veryShortName = robot.getVeryShortName(); + teamName = robot.getTeamName(); + + robotIndex = robot.getRobotIndex(); + teamIndex = robot.getTeamIndex(); + + state = robot.getState(); + + energy = robot.getEnergy(); + velocity = robot.getVelocity(); + gunHeat = robot.getGunHeat(); + + bodyHeading = robot.getBodyHeading(); + gunHeading = robot.getGunHeading(); + radarHeading = robot.getRadarHeading(); + + x = robot.getX(); + y = robot.getY(); + + bodyColor = robot.getBodyColor(); + gunColor = robot.getGunColor(); + radarColor = robot.getRadarColor(); + scanColor = robot.getScanColor(); + + isDroid = robot.isDroid(); + isPaintRobot = robot.isPaintRobot() || robot.isTryingToPaint(); + isPaintEnabled = robot.isPaintEnabled(); + isSGPaintEnabled = robot.isSGPaintEnabled(); + + scanArc = robot.getScanArc() != null ? new SerializableArc((Arc2D.Double) robot.getScanArc()) : null; + + graphicsCalls = robot.getGraphicsCalls(); + + final List dp = robot.getDebugProperties(); + + debugProperties = dp != null ? dp.toArray(new DebugProperty[dp.size()]) : null; + + if (readoutText) { + outputStreamSnapshot = robot.readOutText(); + } + + robotScoreSnapshot = new ScoreSnapshot(robot.getName(), robot.getRobotStatistics()); + } + + @Override + public String toString() { + return shortName + " (" + (int) energy + ") X" + (int) x + " Y" + (int) y + " " + state.toString(); + } + + /** + * {@inheritDoc} + */ + // Used to identify buttons + // TODO: Fix this so that getRobotIndex() is used instead + public String getName() { + return name; + } + + /** + * {@inheritDoc} + */ + // Used for text on buttons + public String getShortName() { + return shortName; + } + + /** + * {@inheritDoc} + */ + // Used for drawing the name of the robot on the battle view + public String getVeryShortName() { + return veryShortName; + } + + /** + * {@inheritDoc} + */ + public String getTeamName() { + return teamName; + } + + /** + * {@inheritDoc} + */ + public int getContestantIndex() { + return teamIndex >= 0 ? teamIndex : robotIndex; + } + + /** + * {@inheritDoc} + */ + public int getRobotIndex() { + return robotIndex; + } + + /** + * {@inheritDoc} + */ + public int getTeamIndex() { + return teamIndex; + } + + /** + * {@inheritDoc} + */ + public RobotState getState() { + return state; + } + + /** + * {@inheritDoc} + */ + public double getEnergy() { + return energy; + } + + /** + * {@inheritDoc} + */ + public double getVelocity() { + return velocity; + } + + /** + * {@inheritDoc} + */ + public double getBodyHeading() { + return bodyHeading; + } + + /** + * {@inheritDoc} + */ + public double getGunHeading() { + return gunHeading; + } + + /** + * {@inheritDoc} + */ + public double getRadarHeading() { + return radarHeading; + } + + /** + * {@inheritDoc} + */ + public double getGunHeat() { + return gunHeat; + } + + /** + * {@inheritDoc} + */ + public double getX() { + return x; + } + + /** + * {@inheritDoc} + */ + public double getY() { + return y; + } + + /** + * {@inheritDoc} + */ + public int getBodyColor() { + return bodyColor; + } + + /** + * {@inheritDoc} + */ + public int getGunColor() { + return gunColor; + } + + /** + * {@inheritDoc} + */ + public int getRadarColor() { + return radarColor; + } + + /** + * {@inheritDoc} + */ + public int getScanColor() { + return scanColor; + } + + /** + * {@inheritDoc} + */ + public boolean isDroid() { + return isDroid; + } + + /** + * {@inheritDoc} + */ + public boolean isSentryRobot() { + return isSentryRobot; + } + + /** + * {@inheritDoc} + */ + public boolean isPaintRobot() { + return isPaintRobot; + } + + /** + * {@inheritDoc} + */ + public boolean isPaintEnabled() { + return isPaintEnabled; + } + + /** + * Sets the flag specifying if painting is enabled for the robot. + * + * @param isPaintEnabled {@code true} if painting must be enabled; + * {@code false} otherwise. + */ + public void setPaintEnabled(boolean isPaintEnabled) { + this.isPaintEnabled = isPaintEnabled; + } + + /** + * {@inheritDoc} + */ + public boolean isSGPaintEnabled() { + return isSGPaintEnabled; + } + + /** + * {@inheritDoc} + */ + public DebugProperty[] getDebugProperties() { + return debugProperties; + } + + /** + * {@inheritDoc} + */ + public String getOutputStreamSnapshot() { + return outputStreamSnapshot; + } + + /** + * Sets the snapshot of the output print stream for this robot. + * + * @param outputStreamSnapshot new output print stream snapshot. + */ + public void setOutputStreamSnapshot(String outputStreamSnapshot) { + this.outputStreamSnapshot = outputStreamSnapshot; + } + + void stripDetails(SerializableOptions options) { + if (options.skipDebug) { + graphicsCalls = null; + debugProperties = null; + outputStreamSnapshot = null; + isPaintEnabled = false; + isSGPaintEnabled = false; + } + if (options.skipNames) { + name = veryShortName; + shortName = veryShortName; + teamName = veryShortName; + } + } + + /** + * {@inheritDoc} + */ + public IScoreSnapshot getScoreSnapshot() { + return robotScoreSnapshot; + } + + /** + * Returns the scan arc snapshot for the robot. + * + * @return the scan arc snapshot for the robot. + */ + public Arc2D getScanArc() { + return scanArc != null ? scanArc.create() : null; + } + + /** + * Returns the object with queued calls for Graphics object. + * + * @return the object with queued calls for Graphics object. + */ + public Object getGraphicsCalls() { + return graphicsCalls; + } + + /** + * {@inheritDoc} + */ + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException { + writer.startElement(options.shortAttributes ? "r" : "robot"); { + writer.writeAttribute("id", robotIndex); + if (!options.skipNames) { + writer.writeAttribute("vsName", veryShortName); + } + if (!options.skipExploded || state != RobotState.ACTIVE) { + writer.writeAttribute(options.shortAttributes ? "s" : "state", state.toString()); + } + writer.writeAttribute(options.shortAttributes ? "e" : "energy", energy, options.trimPrecision); + writer.writeAttribute("x", x, options.trimPrecision); + writer.writeAttribute("y", y, options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "b" : "bodyHeading", bodyHeading, options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "g" : "gunHeading", gunHeading, options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "r" : "radarHeading", radarHeading, options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "h" : "gunHeat", gunHeat, options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "v" : "velocity", velocity, options.trimPrecision); + if (!options.skipNames) { + writer.writeAttribute("teamName", teamName); + writer.writeAttribute("name", name); + writer.writeAttribute("sName", shortName); + if (isDroid) { + writer.writeAttribute("isDroid", true); + } + if (bodyColor != ExecCommands.defaultBodyColor) { + writer.writeAttribute("bodyColor", Integer.toHexString(bodyColor).toUpperCase()); + } + if (gunColor != ExecCommands.defaultGunColor) { + writer.writeAttribute("gunColor", Integer.toHexString(gunColor).toUpperCase()); + } + if (radarColor != ExecCommands.defaultRadarColor) { + writer.writeAttribute("radarColor", Integer.toHexString(radarColor).toUpperCase()); + } + if (scanColor != ExecCommands.defaultScanColor) { + writer.writeAttribute("scanColor", Integer.toHexString(scanColor).toUpperCase()); + } + } + if (!options.skipVersion) { + writer.writeAttribute("ver", serialVersionUID); + } + if (!options.skipDebug) { + if (outputStreamSnapshot != null && outputStreamSnapshot.length() != 0) { + writer.writeAttribute("out", outputStreamSnapshot); + } + if (debugProperties != null) { + writer.startElement("debugProperties"); { + for (DebugProperty prop : debugProperties) { + prop.writeXml(writer, options); + } + } + writer.endElement(); + } + } + + ((ScoreSnapshot) robotScoreSnapshot).writeXml(writer, options); + } + writer.endElement(); + + } + + // allows loading of minimalistic XML + RobotSnapshot(String robotName, int robotIndex, RobotState state) { + this.robotIndex = robotIndex; + this.state = state; + this.name = robotName; + this.teamName = robotName; + this.shortName = robotName; + this.veryShortName = robotName; + this.robotScoreSnapshot = new ScoreSnapshot(robotName); + } + + /** + * {@inheritDoc} + */ + public XmlReader.Element readXml(XmlReader reader) { + return reader.expect("robot", "r", new XmlReader.Element() { + public IXmlSerializable read(final XmlReader reader) { + final RobotSnapshot snapshot = new RobotSnapshot(); + + reader.expect("id", new XmlReader.Attribute() { + public void read(String value) { + snapshot.robotIndex = Integer.parseInt(value); + + // allows loading of minimalistic XML, which robot names for subsequent turns + Map context = reader.getContext(); + + if (context.containsKey(value)) { + String n = (String) context.get(value); + + if (snapshot.shortName == null) { + snapshot.name = n; + } + if (snapshot.shortName == null) { + snapshot.shortName = n; + } + if (snapshot.teamName == null) { + snapshot.teamName = n; + } + if (snapshot.veryShortName == null) { + snapshot.veryShortName = n; + } + } + } + }); + + reader.expect("name", new XmlReader.Attribute() { + public void read(String value) { + snapshot.name = value; + Map context = reader.getContext(); + + context.put(Integer.toString(snapshot.robotIndex), value); + if (snapshot.shortName == null) { + snapshot.shortName = value; + } + if (snapshot.teamName == null) { + snapshot.teamName = value; + } + if (snapshot.veryShortName == null) { + snapshot.veryShortName = value; + } + } + }); + + reader.expect("sName", new XmlReader.Attribute() { + public void read(String value) { + snapshot.shortName = value; + } + }); + + reader.expect("vsName", new XmlReader.Attribute() { + public void read(String value) { + snapshot.veryShortName = value; + } + }); + + reader.expect("teamName", new XmlReader.Attribute() { + public void read(String value) { + snapshot.teamName = value; + } + }); + + reader.expect("state", "s", new XmlReader.Attribute() { + public void read(String value) { + snapshot.state = RobotState.valueOf(value); + } + }); + + reader.expect("isDroid", new XmlReader.Attribute() { + public void read(String value) { + snapshot.isDroid = Boolean.valueOf(value); + } + }); + + reader.expect("bodyColor", new XmlReader.Attribute() { + public void read(String value) { + snapshot.bodyColor = (Long.valueOf(value.toUpperCase(), 16).intValue()); + } + }); + + reader.expect("gunColor", new XmlReader.Attribute() { + public void read(String value) { + snapshot.gunColor = Long.valueOf(value.toUpperCase(), 16).intValue(); + } + }); + + reader.expect("radarColor", new XmlReader.Attribute() { + public void read(String value) { + snapshot.radarColor = Long.valueOf(value.toUpperCase(), 16).intValue(); + } + }); + + reader.expect("scanColor", new XmlReader.Attribute() { + public void read(String value) { + snapshot.scanColor = Long.valueOf(value.toUpperCase(), 16).intValue(); + } + }); + + reader.expect("energy", "e", new XmlReader.Attribute() { + public void read(String value) { + snapshot.energy = Double.parseDouble(value); + } + }); + + reader.expect("velocity", "v", new XmlReader.Attribute() { + public void read(String value) { + snapshot.velocity = Double.parseDouble(value); + } + }); + + reader.expect("gunHeat", "h", new XmlReader.Attribute() { + public void read(String value) { + snapshot.gunHeat = Double.parseDouble(value); + } + }); + + reader.expect("bodyHeading", "b", new XmlReader.Attribute() { + public void read(String value) { + snapshot.bodyHeading = Double.parseDouble(value); + } + }); + + reader.expect("gunHeading", "g", new XmlReader.Attribute() { + public void read(String value) { + snapshot.gunHeading = Double.parseDouble(value); + } + }); + + reader.expect("radarHeading", "r", new XmlReader.Attribute() { + public void read(String value) { + snapshot.radarHeading = Double.parseDouble(value); + } + }); + + reader.expect("x", new XmlReader.Attribute() { + public void read(String value) { + snapshot.x = Double.parseDouble(value); + } + }); + + reader.expect("y", new XmlReader.Attribute() { + public void read(String value) { + snapshot.y = Double.parseDouble(value); + } + }); + + reader.expect("out", new XmlReader.Attribute() { + public void read(String value) { + if (value != null && value.length() != 0) { + snapshot.outputStreamSnapshot = value; + } + } + }); + + final XmlReader.Element element = (new ScoreSnapshot()).readXml(reader); + + reader.expect("score", "sc", new XmlReader.Element() { + public IXmlSerializable read(XmlReader reader) { + snapshot.robotScoreSnapshot = (IScoreSnapshot) element.read(reader); + return (ScoreSnapshot) snapshot.robotScoreSnapshot; + } + }); + + return snapshot; + } + }); + } + + /** + * Class used for serializing an Arc2D.double. + * The purpose of this class is to overcome various serialization problems with Arc2D to cope with bug in Java 6: + * Bug ID: 6522514. + * + * @author Pavel Savara + */ + private static class SerializableArc implements Serializable { + private static final long serialVersionUID = 1L; + + public final double x; + public final double y; + public final double w; + public final double h; + public final double start; + public final double extent; + public final int type; + + public SerializableArc(Arc2D.Double arc) { + x = arc.getX(); + y = arc.getY(); + w = arc.getWidth(); + h = arc.getHeight(); + start = arc.getAngleStart(); + extent = arc.getAngleExtent(); + type = arc.getArcType(); + } + + public Arc2D create() { + return new Arc2D.Double(x, y, w, h, start, extent, type); + } + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/ScoreSnapshot.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/ScoreSnapshot.java new file mode 100644 index 0000000..77c65bb --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/ScoreSnapshot.java @@ -0,0 +1,562 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.snapshot; + + +import net.sf.robocode.battle.peer.RobotStatistics; +import net.sf.robocode.serialization.IXmlSerializable; +import net.sf.robocode.serialization.XmlReader; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.serialization.XmlWriter; +import robocode.control.snapshot.IScoreSnapshot; + +import java.io.IOException; +import java.io.Serializable; + + +/** + * A snapshot of a score at a specific time instant in a battle. + * The snapshot contains a snapshot of the score data at that specific time. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + * + * @since 1.6.1 + */ +final class ScoreSnapshot implements Serializable, IXmlSerializable, IScoreSnapshot { + + private static final long serialVersionUID = 1L; + + /** The name of the contestant, i.e. a robot or team */ + private String name; + + /** The total score */ + private double totalScore; + + /** The total survival score */ + private double totalSurvivalScore; + + /** The total last survivor score */ + private double totalLastSurvivorBonus; + + /** The total bullet damage score */ + private double totalBulletDamageScore; + + /** The total bullet kill bonus */ + private double totalBulletKillBonus; + + /** The total ramming damage score */ + private double totalRammingDamageScore; + + /** The total ramming kill bonus */ + private double totalRammingKillBonus; + + /** The total number of first places */ + private int totalFirsts; + + /** The total number of second places */ + private int totalSeconds; + + /** The total number of third places */ + private int totalThirds; + + /** The current score */ + private double currentScore; + + /** The current survival score */ + private double currentSurvivalScore; + + /** The current survival bonus */ + private double currentSurvivalBonus; + + /** The current bullet damage score */ + private double currentBulletDamageScore; + + /** The current bullet kill bonus */ + private double currentBulletKillBonus; + + /** The current ramming damage score */ + private double currentRammingDamageScore; + + /** The current ramming kill bonus */ + private double currentRammingKillBonus; + + /** + * Creates a snapshot of a score that must be filled out with data later. + */ + public ScoreSnapshot() {} + + /** + * Creates a snapshot of a score. + * + * @param score the contestant's score to take a snapshot of. + * @param contestantName the name of the contestant. + */ + ScoreSnapshot(String contestantName, RobotStatistics score) { + this.name = contestantName; + totalScore = score.getTotalScore(); + totalSurvivalScore = score.getTotalSurvivalScore(); + totalLastSurvivorBonus = score.getTotalLastSurvivorBonus(); + totalBulletDamageScore = score.getTotalBulletDamageScore(); + totalBulletKillBonus = score.getTotalBulletKillBonus(); + totalRammingDamageScore = score.getTotalRammingDamageScore(); + totalRammingKillBonus = score.getTotalRammingKillBonus(); + totalFirsts = score.getTotalFirsts(); + totalSeconds = score.getTotalSeconds(); + totalThirds = score.getTotalThirds(); + currentScore = score.getCurrentScore(); + currentBulletDamageScore = score.getCurrentBulletDamageScore(); + currentSurvivalScore = score.getCurrentSurvivalScore(); + currentSurvivalBonus = score.getCurrentSurvivalBonus(); + currentBulletKillBonus = score.getCurrentBulletKillBonus(); + currentRammingDamageScore = score.getCurrentRammingDamageScore(); + currentRammingKillBonus = score.getCurrentRammingKillBonus(); + } + + /** + * Creates a snapshot of a score based on two sets of scores that are added together. + * + * @param contestantName the name of the contestant. + * @param score1 the contestant's first set of scores to base this snapshot on. + * @param score2 the contestant's second set of scores that must be added to the first set of scores. + */ + ScoreSnapshot(String contestantName, IScoreSnapshot score1, IScoreSnapshot score2) { + this.name = contestantName; + totalScore = score1.getTotalScore() + score2.getTotalScore(); + totalSurvivalScore = score1.getTotalSurvivalScore() + score2.getTotalSurvivalScore(); + totalLastSurvivorBonus = score1.getTotalLastSurvivorBonus() + score2.getTotalLastSurvivorBonus(); + totalBulletDamageScore = score1.getTotalBulletDamageScore() + score2.getTotalBulletDamageScore(); + totalBulletKillBonus = score1.getTotalBulletKillBonus() + score2.getTotalBulletKillBonus(); + totalRammingDamageScore = score1.getTotalRammingDamageScore() + score2.getTotalRammingDamageScore(); + totalRammingKillBonus = score1.getTotalRammingKillBonus() + score2.getTotalRammingKillBonus(); + totalFirsts = score1.getTotalFirsts() + score2.getTotalFirsts(); + totalSeconds = score1.getTotalSeconds() + score2.getTotalSeconds(); + totalThirds = score1.getTotalThirds() + score2.getTotalThirds(); + currentScore = score1.getCurrentScore() + score2.getCurrentScore(); + currentSurvivalScore = score1.getCurrentSurvivalScore() + score2.getCurrentSurvivalScore(); + currentBulletDamageScore = score1.getCurrentBulletDamageScore() + score2.getCurrentBulletDamageScore(); + currentBulletKillBonus = score1.getCurrentBulletKillBonus() + score2.getCurrentBulletKillBonus(); + currentRammingDamageScore = score1.getCurrentRammingDamageScore() + score2.getCurrentRammingDamageScore(); + currentRammingKillBonus = score1.getCurrentBulletKillBonus() + score2.getCurrentBulletKillBonus(); + } + + @Override + public String toString() { + return this.totalScore + "/" + this.currentScore; + } + + /** + * {@inheritDoc} + */ + public String getName() { + return name; + } + + /** + * {@inheritDoc} + */ + public double getTotalScore() { + return totalScore; + } + + /** + * {@inheritDoc} + */ + public double getTotalSurvivalScore() { + return totalSurvivalScore; + } + + /** + * {@inheritDoc} + */ + public double getTotalLastSurvivorBonus() { + return totalLastSurvivorBonus; + } + + /** + * {@inheritDoc} + */ + public double getTotalBulletDamageScore() { + return totalBulletDamageScore; + } + + /** + * {@inheritDoc} + */ + public double getTotalBulletKillBonus() { + return totalBulletKillBonus; + } + + /** + * {@inheritDoc} + */ + public double getTotalRammingDamageScore() { + return totalRammingDamageScore; + } + + /** + * {@inheritDoc} + */ + public double getTotalRammingKillBonus() { + return totalRammingKillBonus; + } + + /** + * {@inheritDoc} + */ + public int getTotalFirsts() { + return totalFirsts; + } + + /** + * {@inheritDoc} + */ + public int getTotalSeconds() { + return totalSeconds; + } + + /** + * {@inheritDoc} + */ + public int getTotalThirds() { + return totalThirds; + } + + /** + * {@inheritDoc} + */ + public double getCurrentScore() { + return currentScore; + } + + /** + * {@inheritDoc} + */ + public double getCurrentSurvivalScore() { + return currentSurvivalScore; + } + + /** + * {@inheritDoc} + */ + public double getCurrentSurvivalBonus() { + return currentSurvivalBonus; + } + + /** + * {@inheritDoc} + */ + public double getCurrentBulletDamageScore() { + return currentBulletDamageScore; + } + + /** + * {@inheritDoc} + */ + public double getCurrentBulletKillBonus() { + return currentBulletKillBonus; + } + + /** + * {@inheritDoc} + */ + public double getCurrentRammingDamageScore() { + return currentRammingDamageScore; + } + + /** + * {@inheritDoc} + */ + public double getCurrentRammingKillBonus() { + return currentRammingKillBonus; + } + + /** + * {@inheritDoc} + */ + public int compareTo(Object obj) { + if (obj instanceof IScoreSnapshot) { + IScoreSnapshot scoreSnapshot = (IScoreSnapshot) obj; + + double myScore = getTotalScore() + getCurrentScore(); + double hisScore = scoreSnapshot.getTotalScore() + scoreSnapshot.getCurrentScore(); + + if (myScore < hisScore) { + return -1; + } + if (myScore > hisScore) { + return 1; + } + } + return 0; + } + + /** + * {@inheritDoc} + */ + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException { + writer.startElement(options.shortAttributes ? "sc" : "score"); { + if (!options.skipNames) { + writer.writeAttribute("name", name); + } + if (!options.skipTotal) { + writer.writeAttribute(options.shortAttributes ? "t" : "totalScore", totalScore, options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "tss" : "totalSurvivalScore", totalSurvivalScore, + options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "tls" : "totalLastSurvivorBonus", totalLastSurvivorBonus, + options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "tbd" : "totalBulletDamageScore", totalBulletDamageScore, + options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "tbk" : "totalBulletKillBonus", totalBulletKillBonus, + options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "trd" : "totalRammingDamageScore", + totalRammingDamageScore, options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "trk" : "totalRammingKillBonus", totalRammingKillBonus, + options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "t1" : "totalFirsts", totalFirsts); + writer.writeAttribute(options.shortAttributes ? "t2" : "totalSeconds", totalSeconds); + writer.writeAttribute(options.shortAttributes ? "t3" : "totalThirds", totalThirds); + } + writer.writeAttribute(options.shortAttributes ? "c" : "currentScore", currentScore, options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "ss" : "currentSurvivalScore", currentSurvivalScore, + options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "bd" : "currentBulletDamageScore", currentBulletDamageScore, + options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "bk" : "currentBulletKillBonus", currentBulletKillBonus, + options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "rd" : "currentRammingDamageScore", + currentRammingDamageScore, options.trimPrecision); + writer.writeAttribute(options.shortAttributes ? "rk" : "currentRammingKillBonus", currentRammingKillBonus, + options.trimPrecision); + if (!options.skipVersion) { + writer.writeAttribute("ver", serialVersionUID); + } + + } + writer.endElement(); + } + + // allows loading of minimalistic XML + ScoreSnapshot(String contestantName) { + this.name = contestantName; + } + + /** + * {@inheritDoc} + */ + public XmlReader.Element readXml(XmlReader reader) { + return reader.expect("score", "sc", new XmlReader.Element() { + public IXmlSerializable read(XmlReader reader) { + final ScoreSnapshot snapshot = new ScoreSnapshot(); + + reader.expect("name", new XmlReader.Attribute() { + public void read(String value) { + snapshot.name = value; + } + }); + reader.expect("totalScore", "t", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalScore = Double.parseDouble(value); + } + }); + reader.expect("totalSurvivalScore", "tss", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalSurvivalScore = Double.parseDouble(value); + } + }); + reader.expect("totalLastSurvivorBonus", "tls", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalLastSurvivorBonus = Double.parseDouble(value); + } + }); + reader.expect("totalBulletDamageScore", "tbd", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalBulletDamageScore = Double.parseDouble(value); + } + }); + reader.expect("totalBulletKillBonus", "tbk", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalBulletKillBonus = Double.parseDouble(value); + } + }); + reader.expect("totalRammingDamageScore", "trd", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalRammingDamageScore = Double.parseDouble(value); + } + }); + reader.expect("totalRammingKillBonus", "trk", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalRammingKillBonus = Double.parseDouble(value); + } + }); + reader.expect("totalFirsts", "t1", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalFirsts = Integer.parseInt(value); + } + }); + reader.expect("totalSeconds", "t2", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalSeconds = Integer.parseInt(value); + } + }); + reader.expect("totalThirds", "t3", new XmlReader.Attribute() { + public void read(String value) { + snapshot.totalThirds = Integer.parseInt(value); + } + }); + reader.expect("currentScore", "c", new XmlReader.Attribute() { + public void read(String value) { + snapshot.currentScore = Double.parseDouble(value); + } + }); + reader.expect("currentSurvivalScore", "ss", new XmlReader.Attribute() { + public void read(String value) { + snapshot.currentSurvivalScore = Double.parseDouble(value); + } + }); + reader.expect("currentBulletDamageScore", "bd", new XmlReader.Attribute() { + public void read(String value) { + snapshot.currentBulletDamageScore = Double.parseDouble(value); + } + }); + reader.expect("currentBulletKillBonus", "bk", new XmlReader.Attribute() { + public void read(String value) { + snapshot.currentBulletKillBonus = Double.parseDouble(value); + } + }); + reader.expect("currentRammingDamageScore", "rd", new XmlReader.Attribute() { + public void read(String value) { + snapshot.currentRammingDamageScore = Double.parseDouble(value); + } + }); + reader.expect("currentRammingKillBonus", "rk", new XmlReader.Attribute() { + public void read(String value) { + snapshot.currentRammingKillBonus = Double.parseDouble(value); + } + }); + return snapshot; + } + }); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + + temp = Double.doubleToLongBits(currentBulletDamageScore); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(currentBulletKillBonus); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(currentRammingDamageScore); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(currentRammingKillBonus); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(currentScore); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(currentSurvivalBonus); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(currentSurvivalScore); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + temp = Double.doubleToLongBits(totalBulletDamageScore); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(totalBulletKillBonus); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + totalFirsts; + temp = Double.doubleToLongBits(totalLastSurvivorBonus); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(totalRammingDamageScore); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(totalRammingKillBonus); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(totalScore); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + totalSeconds; + temp = Double.doubleToLongBits(totalSurvivalScore); + result = prime * result + (int) (temp ^ (temp >>> 32)); + result = prime * result + totalThirds; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ScoreSnapshot other = (ScoreSnapshot) obj; + + if (Double.doubleToLongBits(currentBulletDamageScore) != Double.doubleToLongBits(other.currentBulletDamageScore)) { + return false; + } + if (Double.doubleToLongBits(currentBulletKillBonus) != Double.doubleToLongBits(other.currentBulletKillBonus)) { + return false; + } + if (Double.doubleToLongBits(currentRammingDamageScore) + != Double.doubleToLongBits(other.currentRammingDamageScore)) { + return false; + } + if (Double.doubleToLongBits(currentRammingKillBonus) != Double.doubleToLongBits(other.currentRammingKillBonus)) { + return false; + } + if (Double.doubleToLongBits(currentScore) != Double.doubleToLongBits(other.currentScore)) { + return false; + } + if (Double.doubleToLongBits(currentSurvivalBonus) != Double.doubleToLongBits(other.currentSurvivalBonus)) { + return false; + } + if (Double.doubleToLongBits(currentSurvivalScore) != Double.doubleToLongBits(other.currentSurvivalScore)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (Double.doubleToLongBits(totalBulletDamageScore) != Double.doubleToLongBits(other.totalBulletDamageScore)) { + return false; + } + if (Double.doubleToLongBits(totalBulletKillBonus) != Double.doubleToLongBits(other.totalBulletKillBonus)) { + return false; + } + if (totalFirsts != other.totalFirsts) { + return false; + } + if (Double.doubleToLongBits(totalLastSurvivorBonus) != Double.doubleToLongBits(other.totalLastSurvivorBonus)) { + return false; + } + if (Double.doubleToLongBits(totalRammingDamageScore) != Double.doubleToLongBits(other.totalRammingDamageScore)) { + return false; + } + if (Double.doubleToLongBits(totalRammingKillBonus) != Double.doubleToLongBits(other.totalRammingKillBonus)) { + return false; + } + if (Double.doubleToLongBits(totalScore) != Double.doubleToLongBits(other.totalScore)) { + return false; + } + if (totalSeconds != other.totalSeconds) { + return false; + } + if (Double.doubleToLongBits(totalSurvivalScore) != Double.doubleToLongBits(other.totalSurvivalScore)) { + return false; + } + if (totalThirds != other.totalThirds) { + return false; + } + return true; + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/TurnSnapshot.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/TurnSnapshot.java new file mode 100644 index 0000000..bba2b48 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/battle/snapshot/TurnSnapshot.java @@ -0,0 +1,297 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle.snapshot; + + +import net.sf.robocode.battle.Battle; +import net.sf.robocode.battle.peer.BulletPeer; +import net.sf.robocode.battle.peer.RobotPeer; +import net.sf.robocode.serialization.IXmlSerializable; +import net.sf.robocode.serialization.XmlReader; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.serialization.XmlWriter; +import robocode.control.snapshot.*; + +import java.io.IOException; +import java.util.*; + + +/** + * A snapshot of a battle turn at a specific time instant in a battle. + * The snapshot contains a snapshot of the battle turn data at that specific time. + * + * @author Flemming N. Larsen (original) + * @author Pavel Savara (contributor) + * + * @since 1.6.1 + */ +public final class TurnSnapshot implements java.io.Serializable, IXmlSerializable, ITurnSnapshot { + + private static final long serialVersionUID = 1L; + + /** List of snapshots for the robots participating in the battle */ + private List robots; + + /** List of snapshots for the bullets that are currently on the battlefield */ + private List bullets; + + /** Current TPS (turns per second) */ + private int tps; + + /** Current round in the battle */ + private int round; + + /** Current turn in the battle round */ + private int turn; + + /** + * Creates a snapshot of a battle turn that must be filled out with data later. + */ + public TurnSnapshot() {} + + /** + * Creates a snapshot of a battle turn. + * + * @param battle the battle to make a snapshot of. + * @param battleRobots the robots participating in the battle. + * @param battleBullets the current bullet on the battlefield. + * @param readoutText {@code true} if the output text from the robots must be included in the snapshot; + * {@code false} otherwise. + */ + public TurnSnapshot(Battle battle, List battleRobots, List battleBullets, boolean readoutText) { + robots = new ArrayList(); + bullets = new ArrayList(); + + for (RobotPeer robotPeer : battleRobots) { + robots.add(new RobotSnapshot(robotPeer, readoutText)); + } + + for (BulletPeer bulletPeer : battleBullets) { + bullets.add(new BulletSnapshot(bulletPeer)); + } + + tps = battle.getTPS(); + turn = battle.getTime(); + round = battle.getRoundNum(); + } + + @Override + public String toString() { + return this.round + "/" + turn + " (" + this.robots.size() + ")"; + } + + /** + * {@inheritDoc} + */ + public IRobotSnapshot[] getRobots() { + return robots.toArray(new IRobotSnapshot[robots.size()]); + } + + /** + * {@inheritDoc} + */ + public IBulletSnapshot[] getBullets() { + return bullets.toArray(new IBulletSnapshot[bullets.size()]); + } + + /** + * {@inheritDoc} + */ + public int getTPS() { + return tps; + } + + /** + * {@inheritDoc} + */ + public int getRound() { + return round; + } + + /** + * {@inheritDoc} + */ + public int getTurn() { + return turn; + } + + /** + * {@inheritDoc} + */ + public IScoreSnapshot[] getSortedTeamScores() { + List copy = new ArrayList(Arrays.asList(getIndexedTeamScores())); + + Collections.sort(copy); + Collections.reverse(copy); + return copy.toArray(new IScoreSnapshot[copy.size()]); + } + + /** + * {@inheritDoc} + */ + public IScoreSnapshot[] getIndexedTeamScores() { + // team scores are computed on demand from team scores to not duplicate data in the snapshot + + List results = new ArrayList(); + + // noinspection ForLoopReplaceableByForEach + for (int i = 0; i < robots.size(); i++) { + results.add(null); + } + for (IRobotSnapshot robot : robots) { + final int contestantIndex = robot.getContestantIndex(); + final IScoreSnapshot snapshot = results.get(contestantIndex); + + IScoreSnapshot score = (snapshot == null) + ? robot.getScoreSnapshot() + : new ScoreSnapshot(robot.getTeamName(), snapshot, robot.getScoreSnapshot()); + + results.set(contestantIndex, score); + } + List scores = new ArrayList(); + + for (IScoreSnapshot scoreSnapshot : results) { + if (scoreSnapshot != null) { + scores.add(scoreSnapshot); + } + } + + return scores.toArray(new IScoreSnapshot[scores.size()]); + } + + public void stripDetails(SerializableOptions options) { + for (IRobotSnapshot r : getRobots()) { + ((RobotSnapshot) r).stripDetails(options); + } + } + + /** + * {@inheritDoc} + */ + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException { + writer.startElement(options.shortAttributes ? "t" : "turn"); { + writer.writeAttribute(options.shortAttributes ? "ro" : "round", round); + writer.writeAttribute(options.shortAttributes ? "tu" : "turn", turn); + if (!options.skipVersion) { + writer.writeAttribute("ver", serialVersionUID); + } + + writer.startElement(options.shortAttributes ? "rs" : "robots"); { + SerializableOptions op = options; + + if (turn == 0) { + op = new SerializableOptions(options); + op.skipNames = false; + } + for (IRobotSnapshot r : robots) { + final RobotSnapshot rs = (RobotSnapshot) r; + + if (!options.skipExploded || rs.getState() != RobotState.DEAD) { + rs.writeXml(writer, op); + } else { + boolean writeFirstExplosionFrame = false; + + for (IBulletSnapshot b : bullets) { + if (b.isExplosion() && b.getFrame() == 0 && b.getVictimIndex() == r.getRobotIndex()) { + writeFirstExplosionFrame = true; + break; + } + } + if (writeFirstExplosionFrame) { + rs.writeXml(writer, op); + } + } + } + } + writer.endElement(); + + writer.startElement(options.shortAttributes ? "bs" : "bullets"); { + for (IBulletSnapshot b : bullets) { + final BulletSnapshot bs = (BulletSnapshot) b; + final BulletState state = bs.getState(); + + if (!options.skipExploded + || (state != BulletState.EXPLODED && state != BulletState.INACTIVE + && (bs.getFrame() == 0 || state == BulletState.MOVING))) { + bs.writeXml(writer, options); + } + } + } + writer.endElement(); + } + writer.endElement(); + } + + /** + * {@inheritDoc} + */ + public XmlReader.Element readXml(final XmlReader reader) { + return reader.expect("turn", "t", new XmlReader.Element() { + public IXmlSerializable read(final XmlReader reader) { + final TurnSnapshot snapshot = new TurnSnapshot(); + + reader.expect("turn", "tu", new XmlReader.Attribute() { + public void read(String value) { + snapshot.turn = Integer.parseInt(value); + } + }); + reader.expect("round", "ro", new XmlReader.Attribute() { + public void read(String value) { + snapshot.round = Integer.parseInt(value); + } + }); + + reader.expect("robots", "rs", new XmlReader.ListElement() { + public IXmlSerializable read(XmlReader reader) { + snapshot.robots = new ArrayList(); + // prototype + return new RobotSnapshot(); + } + + public void add(IXmlSerializable child) { + snapshot.robots.add((RobotSnapshot) child); + } + + public void close() { + // allows loading of minimalistic XML, which skips dead robots, but GUI expects them + Map context = reader.getContext(); + Integer robotCount = (Integer) context.get("robots"); + boolean[] present = new boolean[robotCount]; + + for (IRobotSnapshot robot : snapshot.robots) { + present[robot.getRobotIndex()] = true; + } + for (int i = 0; i < robotCount; i++) { + if (!present[i]) { + String name = (String) context.get(Integer.toString(i)); + + snapshot.robots.add(new RobotSnapshot(name, i, RobotState.DEAD)); + } + } + } + }); + + reader.expect("bullets", "bs", new XmlReader.ListElement() { + public IXmlSerializable read(XmlReader reader) { + snapshot.bullets = new ArrayList(); + // prototype + return new BulletSnapshot(); + } + + public void add(IXmlSerializable child) { + snapshot.bullets.add((BulletSnapshot) child); + } + + public void close() {} + }); + + return snapshot; + } + }); + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattlePlayer.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattlePlayer.java new file mode 100644 index 0000000..3872b12 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattlePlayer.java @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.recording; + + +import net.sf.robocode.battle.BaseBattle; +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.battle.events.BattleEventDispatcher; +import net.sf.robocode.battle.snapshot.RobotSnapshot; +import net.sf.robocode.settings.ISettingsManager; +import robocode.BattleResults; +import robocode.control.events.*; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + +import java.util.List; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (original) + */ +public final class BattlePlayer extends BaseBattle { + + private final RecordManager recordManager; + private boolean[] paint; + + public BattlePlayer(ISettingsManager properties, IBattleManager battleManager, RecordManager recordManager, BattleEventDispatcher eventDispatcher) { // NO_UCD (unused code) + super( + properties, battleManager, eventDispatcher); + this.recordManager = recordManager; + } + + @Override + protected void initializeBattle() { + super.initializeBattle(); + + recordManager.prepareInputStream(); + + battleRules = recordManager.recordInfo.battleRules; + paint = new boolean[recordManager.recordInfo.robotCount]; + eventDispatcher.onBattleStarted(new BattleStartedEvent(battleRules, recordManager.recordInfo.robotCount, true)); + if (isPaused) { + eventDispatcher.onBattlePaused(new BattlePausedEvent()); + } + } + + @Override + protected void finalizeBattle() { + boolean aborted = recordManager.recordInfo.results == null || isAborted(); + + eventDispatcher.onBattleFinished(new BattleFinishedEvent(aborted)); + + if (!aborted) { + final List res = recordManager.recordInfo.results; + + eventDispatcher.onBattleCompleted( + new BattleCompletedEvent(battleRules, res.toArray(new BattleResults[res.size()]))); + } + + super.finalizeBattle(); + + cleanup(); + } + + @Override + protected void initializeRound() { + super.initializeRound(); + + final ITurnSnapshot snapshot = recordManager.readSnapshot(currentTime); + + if (snapshot != null) { + eventDispatcher.onRoundStarted(new RoundStartedEvent(snapshot, getRoundNum())); + } + } + + @Override + protected void finalizeRound() { + super.finalizeRound(); + + eventDispatcher.onRoundEnded(new RoundEndedEvent(getRoundNum(), getTime(), totalTurns)); + } + + @Override + protected void initializeTurn() { + super.initializeTurn(); + + eventDispatcher.onTurnStarted(new TurnStartedEvent()); + } + + @Override + protected void finalizeTurn() { + final ITurnSnapshot snapshot = recordManager.readSnapshot(currentTime); + + if (snapshot != null) { + final IRobotSnapshot[] robots = snapshot.getRobots(); + + for (int i = 0; i < robots.length; i++) { + RobotSnapshot robot = (RobotSnapshot) robots[i]; + + robot.setPaintEnabled(paint[i]); + } + eventDispatcher.onTurnEnded(new TurnEndedEvent(snapshot)); + } + + super.finalizeTurn(); + } + + @Override + protected boolean isRoundOver() { + final boolean end = getTime() >= recordManager.recordInfo.turnsInRounds[getRoundNum()] - 1; + + if (end) { + if (recordManager.recordInfo.turnsInRounds.length > getRoundNum() + && recordManager.recordInfo.turnsInRounds[getRoundNum()] == 0) { + isAborted = true; + } + } + return (isAborted || end); + } + + @Override + public void cleanup() { + super.cleanup(); + recordManager.cleanupStreams(); + } + + public void setPaintEnabled(int robotIndex, boolean enable) { + sendCommand(new EnableRobotPaintCommand(robotIndex, enable)); + } + + private class EnableRobotPaintCommand extends RobotCommand { + final boolean enablePaint; + + EnableRobotPaintCommand(int robotIndex, boolean enablePaint) { + super(robotIndex); + this.enablePaint = enablePaint; + } + + public void execute() { + paint[robotIndex] = enablePaint; + } + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattleRecordInfo.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattleRecordInfo.java new file mode 100644 index 0000000..9bab5c2 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattleRecordInfo.java @@ -0,0 +1,330 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.recording; + + +import net.sf.robocode.battle.BattleProperties; +import net.sf.robocode.security.HiddenAccess; +import net.sf.robocode.serialization.IXmlSerializable; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.serialization.XmlReader; +import net.sf.robocode.serialization.XmlWriter; +import robocode.BattleResults; +import robocode.BattleRules; + +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (original) + */ +class BattleRecordInfo implements Serializable, IXmlSerializable { + private static final long serialVersionUID = 1L; + + int robotCount; + int roundsCount; + BattleRules battleRules; + Integer[] turnsInRounds; + List results; + + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException { + writer.startElement("recordInfo"); { + writer.writeAttribute("robotCount", robotCount); + writer.writeAttribute("roundsCount", roundsCount); + if (!options.skipVersion) { + writer.writeAttribute("ver", serialVersionUID); + } + writer.startElement("rules"); { + writer.writeAttribute("battlefieldWidth", battleRules.getBattlefieldWidth()); + writer.writeAttribute("battlefieldHeight", battleRules.getBattlefieldHeight()); + writer.writeAttribute("numRounds", battleRules.getNumRounds()); + writer.writeAttribute("gunCoolingRate", battleRules.getGunCoolingRate(), options.trimPrecision); + writer.writeAttribute("inactivityTime", battleRules.getInactivityTime()); + writer.writeAttribute("ver", serialVersionUID); + } + writer.endElement(); + + writer.startElement("rounds"); { + for (int n : turnsInRounds) { + writer.startElement("turns"); { + writer.writeAttribute("value", Integer.toString(n)); + } + writer.endElement(); + } + } + writer.endElement(); + + if (results != null) { + writer.startElement("results"); { + for (BattleResults result : results) { + new BattleResultsWrapper(result).writeXml(writer, options); + } + } + writer.endElement(); + } + } + writer.endElement(); + } + + public XmlReader.Element readXml(XmlReader reader) { + return reader.expect("recordInfo", new XmlReader.Element() { + public IXmlSerializable read(XmlReader reader) { + final BattleRecordInfo recordInfo = new BattleRecordInfo(); + + reader.expect("robotCount", new XmlReader.Attribute() { + public void read(String value) { + recordInfo.robotCount = Integer.parseInt(value); + } + }); + reader.expect("roundsCount", new XmlReader.Attribute() { + public void read(String value) { + recordInfo.roundsCount = Integer.parseInt(value); + } + }); + + new BattleRulesWrapper(recordInfo).readXml(reader); + + reader.expect("rounds", new XmlReader.ListElement() { + final ArrayList ints = new ArrayList(); + + public IXmlSerializable read(XmlReader reader) { + // prototype + return new IntValue("turns"); + } + + public void add(IXmlSerializable child) { + ints.add(((IntValue) child).intValue); + } + + public void close() { + recordInfo.turnsInRounds = new Integer[ints.size()]; + ints.toArray(recordInfo.turnsInRounds); + } + }); + + reader.expect("results", new XmlReader.ListElement() { + + public IXmlSerializable read(XmlReader reader) { + recordInfo.results = new ArrayList(); + // prototype + return new BattleResultsWrapper(); + } + + public void add(IXmlSerializable child) { + recordInfo.results.add((BattleResults) child); + } + + public void close() {} + }); + return recordInfo; + } + }); + } + + private class IntValue implements IXmlSerializable { + private IntValue(String name) { + this.name = name; + } + private final String name; + private int intValue; + + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException {} + + public XmlReader.Element readXml(XmlReader reader) { + return reader.expect(name, new XmlReader.Element() { + public IXmlSerializable read(XmlReader reader) { + final IntValue recordInfo = new IntValue(name); + + reader.expect("value", new XmlReader.Attribute() { + public void read(String value) { + recordInfo.intValue = Integer.parseInt(value); + } + }); + return recordInfo; + } + }); + } + } + + + /** + * This class is used for wrapping a robocode.BattleResults object and provides + * methods for XML serialization that are hidden from the BattleResults class, + * which is a part of the public Robot API for Robocode. + * + * @author Flemming N. Larsen (original) + */ + private class BattleResultsWrapper extends BattleResults implements IXmlSerializable { + + private static final long serialVersionUID = BattleResults.serialVersionUID; + + public BattleResultsWrapper() { + super(null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + + private BattleResultsWrapper(BattleResults results) { + super(results.getTeamLeaderName(), results.getRank(), results.getScore(), results.getSurvival(), + results.getLastSurvivorBonus(), results.getBulletDamage(), results.getBulletDamageBonus(), + results.getRamDamage(), results.getRamDamageBonus(), results.getFirsts(), results.getSeconds(), + results.getThirds()); + } + + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException { + writer.startElement("result"); { + writer.writeAttribute("teamLeaderName", teamLeaderName); + writer.writeAttribute("rank", rank); + writer.writeAttribute("score", score, options.trimPrecision); + writer.writeAttribute("survival", survival, options.trimPrecision); + writer.writeAttribute("lastSurvivorBonus", lastSurvivorBonus, options.trimPrecision); + writer.writeAttribute("bulletDamage", bulletDamage, options.trimPrecision); + writer.writeAttribute("bulletDamageBonus", bulletDamageBonus, options.trimPrecision); + writer.writeAttribute("ramDamage", ramDamage, options.trimPrecision); + writer.writeAttribute("ramDamageBonus", ramDamageBonus, options.trimPrecision); + writer.writeAttribute("firsts", firsts); + writer.writeAttribute("seconds", seconds); + writer.writeAttribute("thirds", thirds); + if (!options.skipVersion) { + writer.writeAttribute("ver", serialVersionUID); + } + } + writer.endElement(); + } + + public XmlReader.Element readXml(XmlReader reader) { + return reader.expect("result", new XmlReader.Element() { + public IXmlSerializable read(XmlReader reader) { + final BattleResultsWrapper rules = new BattleResultsWrapper(); + + reader.expect("teamLeaderName", new XmlReader.Attribute() { + public void read(String value) { + rules.teamLeaderName = value; + } + }); + + reader.expect("rank", new XmlReader.Attribute() { + public void read(String value) { + rules.rank = Integer.parseInt(value); + } + }); + reader.expect("score", new XmlReader.Attribute() { + public void read(String value) { + rules.score = Double.parseDouble(value); + } + }); + reader.expect("survival", new XmlReader.Attribute() { + public void read(String value) { + rules.survival = Double.parseDouble(value); + } + }); + reader.expect("lastSurvivorBonus", new XmlReader.Attribute() { + public void read(String value) { + rules.lastSurvivorBonus = Double.parseDouble(value); + } + }); + reader.expect("bulletDamage", new XmlReader.Attribute() { + public void read(String value) { + rules.bulletDamage = Double.parseDouble(value); + } + }); + reader.expect("bulletDamageBonus", new XmlReader.Attribute() { + public void read(String value) { + rules.bulletDamageBonus = Double.parseDouble(value); + } + }); + reader.expect("ramDamage", new XmlReader.Attribute() { + public void read(String value) { + rules.ramDamage = Double.parseDouble(value); + } + }); + reader.expect("ramDamageBonus", new XmlReader.Attribute() { + public void read(String value) { + rules.ramDamageBonus = Double.parseDouble(value); + } + }); + reader.expect("firsts", new XmlReader.Attribute() { + public void read(String value) { + rules.firsts = Integer.parseInt(value); + } + }); + reader.expect("seconds", new XmlReader.Attribute() { + public void read(String value) { + rules.seconds = Integer.parseInt(value); + } + }); + reader.expect("thirds", new XmlReader.Attribute() { + public void read(String value) { + rules.thirds = Integer.parseInt(value); + } + }); + + return rules; + } + }); + } + } + + + private static class BattleRulesWrapper implements IXmlSerializable { + BattleRulesWrapper(BattleRecordInfo recinfo) { + this.recinfo = recinfo; + } + + final BattleProperties props = new BattleProperties(); + final BattleRecordInfo recinfo; + + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException {} + + public XmlReader.Element readXml(XmlReader reader) { + return reader.expect("rules", + new XmlReader.ElementClose() { + public IXmlSerializable read(XmlReader reader) { + + reader.expect("battlefieldWidth", new XmlReader.Attribute() { + public void read(String value) { + props.setBattlefieldWidth(Integer.parseInt(value)); + } + }); + reader.expect("battlefieldHeight", new XmlReader.Attribute() { + public void read(String value) { + props.setBattlefieldHeight(Integer.parseInt(value)); + } + }); + + reader.expect("numRounds", new XmlReader.Attribute() { + public void read(String value) { + props.setNumRounds(Integer.parseInt(value)); + } + }); + reader.expect("inactivityTime", new XmlReader.Attribute() { + public void read(String value) { + props.setInactivityTime(Integer.parseInt(value)); + } + }); + reader.expect("gunCoolingRate", new XmlReader.Attribute() { + public void read(String value) { + props.setGunCoolingRate(Double.parseDouble(value)); + } + }); + + return BattleRulesWrapper.this; + } + + public void close() { + recinfo.battleRules = HiddenAccess.createRules(props.getBattlefieldWidth(), + props.getBattlefieldHeight(), props.getNumRounds(), props.getGunCoolingRate(), + props.getInactivityTime(), props.getHideEnemyNames(), props.getSentryBorderSize()); + } + }); + } + } + +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattleRecorder.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattleRecorder.java new file mode 100644 index 0000000..f7ad6cc --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/BattleRecorder.java @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.recording; + + +import net.sf.robocode.battle.events.BattleEventDispatcher; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.settings.ISettingsManager; +import robocode.BattleResults; +import robocode.control.events.*; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Calendar; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (original) + */ +class BattleRecorder { + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss"); + + private final RecordManager recordmanager; + private final ISettingsManager properties; + private BattleObserver battleObserver; + + BattleRecorder(RecordManager recordmanager, ISettingsManager properties) { + this.recordmanager = recordmanager; + this.properties = properties; + } + + void attachRecorder(BattleEventDispatcher battleEventDispatcher) { + if (battleObserver != null) { + battleObserver.dispose(); + } + battleObserver = new BattleObserver(battleEventDispatcher); + } + + void detachRecorder() { + if (battleObserver != null) { + battleObserver.dispose(); + } + } + + private class BattleObserver extends BattleAdaptor { + private final BattleEventDispatcher dispatcher; + + private int currentTurn; + private int currentRound; + + public BattleObserver(BattleEventDispatcher dispatcher) { + this.dispatcher = dispatcher; + dispatcher.addListener(this); + } + + public void dispose() { + dispatcher.removeListener(this); + recordmanager.cleanupStreams(); + } + + @Override + public void onBattleStarted(BattleStartedEvent event) { + recordmanager.cleanupStreams(); + recordmanager.createRecordInfo(event.getBattleRules(), event.getRobotsCount()); + + currentRound = 0; + currentTurn = 0; + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + recordmanager.cleanupStreams(); + } + + @Override + public void onBattleCompleted(BattleCompletedEvent event) { + recordmanager.updateRecordInfoResults(Arrays.asList(event.getIndexedResults())); + + if (properties.getOptionsCommonEnableAutoRecording()) { + writeAutoRecord(event); + } + } + + @Override + public void onRoundStarted(RoundStartedEvent event) { + currentRound = event.getRound(); + currentTurn = 0; + recordmanager.writeTurn(event.getStartSnapshot(), currentRound, currentTurn); + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + currentTurn = event.getTurnSnapshot().getTurn(); + recordmanager.writeTurn(event.getTurnSnapshot(), currentRound, currentTurn); + } + + private void writeAutoRecord(BattleCompletedEvent event) { + try { + final BattleResults[] results = event.getIndexedResults(); + StringBuilder name = new StringBuilder(); + + name.append(FileUtil.getBattlesDir().getCanonicalPath()); + name.append(File.separator); + + Calendar calendar = Calendar.getInstance(); + + name.append(dateFormat.format(calendar.getTime())); + name.append('-'); + for (BattleResults r : results) { + String teamLeaderName = r.getTeamLeaderName(); + + if (teamLeaderName.contains("*")) { // Development version of robot indicated with * in name + teamLeaderName = teamLeaderName.replace("*", ""); // Remove the star (*) + } + name.append(teamLeaderName); + name.append('-'); + } + name.setLength(name.length() - 1); + if (properties.getOptionsCommonAutoRecordingXML()) { + name.append(".xml.zip"); + recordmanager.saveRecord(name.toString(), BattleRecordFormat.XML_ZIP, new SerializableOptions(true)); + } else { + name.append(".zip.br"); + recordmanager.saveRecord(name.toString(), BattleRecordFormat.BINARY_ZIP, + new SerializableOptions(true)); + } + } catch (IOException e) { + Logger.logError(e); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/RecordManager.java b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/RecordManager.java new file mode 100644 index 0000000..82afc32 --- /dev/null +++ b/代码/workspace_robo4/robocode.battle/src/main/java/net/sf/robocode/recording/RecordManager.java @@ -0,0 +1,448 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.recording; + + +import net.sf.robocode.battle.events.BattleEventDispatcher; +import net.sf.robocode.battle.snapshot.TurnSnapshot; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import static net.sf.robocode.io.Logger.logError; +import net.sf.robocode.serialization.IXmlSerializable; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.serialization.XmlReader; +import net.sf.robocode.serialization.XmlWriter; +import net.sf.robocode.settings.ISettingsManager; +import robocode.BattleResults; +import robocode.BattleRules; +import robocode.control.snapshot.ITurnSnapshot; + +import java.io.*; +import java.nio.charset.Charset; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + + +/** + * @author Pavel Savara (original) + */ +public class RecordManager implements IRecordManager { + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss"); + + private final ISettingsManager properties; + + private File tempFile; + private BattleRecorder recorder; + + BattleRecordInfo recordInfo; + private FileOutputStream fileWriteStream; + private BufferedOutputStream bufferedWriteStream; + private ObjectOutputStream objectWriteStream; + + private FileInputStream fileReadStream; + private BufferedInputStream bufferedReadStream; + private ObjectInputStream objectReadStream; + + public RecordManager(ISettingsManager properties) { // NO_UCD (unused code) + this.properties = properties; + recorder = new BattleRecorder(this, properties); + } + + protected void finalize() throws Throwable { + try { + cleanup(); + } finally { + super.finalize(); + } + } + + private void cleanup() { + cleanupStreams(); + if (tempFile != null && tempFile.exists()) { + if (tempFile.delete() == false) { + Logger.logError("Could not delete temp file"); + } + tempFile = null; + } + recordInfo = null; + } + + void cleanupStreams() { + FileUtil.cleanupStream(objectWriteStream); + objectWriteStream = null; + FileUtil.cleanupStream(bufferedWriteStream); + bufferedWriteStream = null; + FileUtil.cleanupStream(fileWriteStream); + fileWriteStream = null; + + FileUtil.cleanupStream(objectReadStream); + objectReadStream = null; + FileUtil.cleanupStream(bufferedReadStream); + bufferedReadStream = null; + FileUtil.cleanupStream(fileReadStream); + fileReadStream = null; + } + + public void attachRecorder(BattleEventDispatcher battleEventDispatcher) { + recorder.attachRecorder(battleEventDispatcher); + } + + public void detachRecorder() { + recorder.detachRecorder(); + } + + private void createTempFile() { + try { + if (tempFile == null) { + tempFile = File.createTempFile("robocode-battle-records", ".tmp"); + tempFile.deleteOnExit(); + } else { + if (!tempFile.delete()) { + Logger.logError("Could not delete temp file"); + } + if (!tempFile.createNewFile()) { + throw new Error("Temp file creation failed"); + } + } + } catch (IOException e) { + logError(e); + throw new Error("Temp file creation failed", e); + } + } + + void prepareInputStream() { + try { + fileReadStream = new FileInputStream(tempFile); + bufferedReadStream = new BufferedInputStream(fileReadStream); + objectReadStream = new ObjectInputStream(bufferedReadStream); + } catch (FileNotFoundException e) { + logError(e); + fileReadStream = null; + bufferedReadStream = null; + objectReadStream = null; + } catch (IOException e) { + logError(e); + fileReadStream = null; + bufferedReadStream = null; + objectReadStream = null; + } + } + + ITurnSnapshot readSnapshot(int currentTime) { + if (objectReadStream == null) { + return null; + } + try { + // TODO implement seek to currentTime, warn you. turns don't have same size in bytes + return (ITurnSnapshot) objectReadStream.readObject(); + } catch (EOFException e) { + logError(e); + return null; + } catch (Exception e) { + logError(e); + return null; + } + } + + public void loadRecord(String recordFilename, BattleRecordFormat format) { + FileInputStream fis = null; + BufferedInputStream bis = null; + ZipInputStream zis = null; + ObjectInputStream ois = null; + InputStream xis = null; + + FileOutputStream fos = null; + BufferedOutputStream bos = null; + ObjectOutputStream oos = null; + + try { + createTempFile(); + fis = new FileInputStream(recordFilename); + bis = new BufferedInputStream(fis, 1024 * 1024); + + if (format == BattleRecordFormat.BINARY) { + ois = new ObjectInputStream(bis); + } else if (format == BattleRecordFormat.BINARY_ZIP) { + zis = new ZipInputStream(bis); + zis.getNextEntry(); + ois = new ObjectInputStream(zis); + } else if (format == BattleRecordFormat.XML_ZIP) { + zis = new ZipInputStream(bis); + zis.getNextEntry(); + xis = zis; + } else if (format == BattleRecordFormat.XML) { + xis = bis; + } + if (format == BattleRecordFormat.BINARY || format == BattleRecordFormat.BINARY_ZIP) { + recordInfo = (BattleRecordInfo) ois.readObject(); + if (recordInfo.turnsInRounds != null) { + fos = new FileOutputStream(tempFile); + bos = new BufferedOutputStream(fos, 1024 * 1024); + oos = new ObjectOutputStream(bos); + + for (int i = 0; i < recordInfo.turnsInRounds.length; i++) { + for (int j = recordInfo.turnsInRounds[i] - 1; j >= 0; j--) { + try { + ITurnSnapshot turn = (ITurnSnapshot) ois.readObject(); + + oos.writeObject(turn); + } catch (ClassNotFoundException e) { + logError(e); + } + } + } + } + } else { + final RecordRoot root = new RecordRoot(); + + fos = new FileOutputStream(tempFile); + bos = new BufferedOutputStream(fos, 1024 * 1024); + root.oos = new ObjectOutputStream(bos); + XmlReader.deserialize(xis, root); + if (root.lastException != null) { + logError(root.lastException); + } + recordInfo = root.recordInfo; + } + } catch (IOException e) { + logError(e); + createTempFile(); + recordInfo = null; + } catch (ClassNotFoundException e) { + if (e.getMessage().contains("robocode.recording.BattleRecordInfo")) { + Logger.logError("Sorry, backward compatibility with record from version 1.6 is not provided."); + } else { + logError(e); + } + createTempFile(); + recordInfo = null; + } finally { + FileUtil.cleanupStream(oos); + FileUtil.cleanupStream(bos); + FileUtil.cleanupStream(fos); + FileUtil.cleanupStream(ois); + FileUtil.cleanupStream(zis); + FileUtil.cleanupStream(bis); + FileUtil.cleanupStream(fis); + } + } + + private static class RecordRoot implements IXmlSerializable { + + public RecordRoot() { + me = this; + } + + public ObjectOutputStream oos; + public IOException lastException; + public final RecordRoot me; + public BattleRecordInfo recordInfo; + + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException {} + + public XmlReader.Element readXml(XmlReader reader) { + return reader.expect("record", new XmlReader.Element() { + public IXmlSerializable read(final XmlReader reader) { + + final XmlReader.Element element = (new BattleRecordInfo()).readXml(reader); + + reader.expect("recordInfo", new XmlReader.ElementClose() { + public IXmlSerializable read(XmlReader reader) { + recordInfo = (BattleRecordInfo) element.read(reader); + return recordInfo; + } + + public void close() { + reader.getContext().put("robots", recordInfo.robotCount); + } + }); + + reader.expect("turns", new XmlReader.ListElement() { + public IXmlSerializable read(XmlReader reader) { + // prototype + return new TurnSnapshot(); + } + + public void add(IXmlSerializable child) { + try { + me.oos.writeObject(child); + } catch (IOException e) { + me.lastException = e; + } + } + + public void close() {} + }); + + return me; + } + }); + } + } + + public void saveRecord(String recordFilename, BattleRecordFormat format, SerializableOptions options) { + FileOutputStream fos = null; + BufferedOutputStream bos = null; + ZipOutputStream zos = null; + ObjectOutputStream oos = null; + OutputStreamWriter osw = null; + XmlWriter xwr = null; + + FileInputStream fis = null; + BufferedInputStream bis = null; + ObjectInputStream ois = null; + + final boolean isbin = format == BattleRecordFormat.BINARY || format == BattleRecordFormat.BINARY_ZIP; + final boolean isxml = format == BattleRecordFormat.XML || format == BattleRecordFormat.XML_ZIP; + Calendar calendar = Calendar.getInstance(); + + try { + fos = new FileOutputStream(recordFilename); + bos = new BufferedOutputStream(fos, 1024 * 1024); + + if (format == BattleRecordFormat.BINARY) { + oos = new ObjectOutputStream(bos); + } else if (format == BattleRecordFormat.BINARY_ZIP) { + zos = new ZipOutputStream(bos); + zos.putNextEntry(new ZipEntry(dateFormat.format(calendar.getTime()) + "-robocode.br")); + oos = new ObjectOutputStream(zos); + } else if (format == BattleRecordFormat.XML) { + final Charset utf8 = Charset.forName("UTF-8"); + + osw = new OutputStreamWriter(bos, utf8); + xwr = new XmlWriter(osw, true); + } else if (format == BattleRecordFormat.XML_ZIP) { + final Charset utf8 = Charset.forName("UTF-8"); + + zos = new ZipOutputStream(bos); + zos.putNextEntry(new ZipEntry(dateFormat.format(calendar.getTime()) + "-robocode.xml")); + + osw = new OutputStreamWriter(zos, utf8); + xwr = new XmlWriter(osw, false); + } + + if (isbin) { + oos.writeObject(recordInfo); + } else if (isxml) { + xwr.startDocument(); + xwr.startElement("record"); + xwr.writeAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); + if (options.shortAttributes) { + xwr.writeAttribute("xsi:noNamespaceSchemaLocation", "battleRecordS.xsd"); + } else { + xwr.writeAttribute("xsi:noNamespaceSchemaLocation", "battleRecord.xsd"); + } + recordInfo.writeXml(xwr, options); + xwr.startElement("turns"); + } + + if (recordInfo.turnsInRounds != null) { + fis = new FileInputStream(tempFile); + bis = new BufferedInputStream(fis, 1024 * 1024); + ois = new ObjectInputStream(bis); + + for (int i = 0; i < recordInfo.turnsInRounds.length; i++) { + if (recordInfo.turnsInRounds[i] > 0) { + for (int j = 0; j <= recordInfo.turnsInRounds[i] - 1; j++) { + try { + TurnSnapshot turn = (TurnSnapshot) ois.readObject(); + + if (j != turn.getTurn()) { + throw new Error("Something rotten"); + } + + if (isbin) { + turn.stripDetails(options); + oos.writeObject(turn); + } else if (isxml) { + turn.writeXml(xwr, options); + } + } catch (ClassNotFoundException e) { + logError(e); + } + } + if (isbin) { + oos.flush(); + } else if (isxml) { + osw.flush(); + } + bos.flush(); + fos.flush(); + } + } + if (isxml) { + xwr.endElement(); // turns + xwr.endElement(); // record + osw.flush(); + } + } + + } catch (IOException e) { + logError(e); + recorder = new BattleRecorder(this, properties); + createTempFile(); + } finally { + FileUtil.cleanupStream(ois); + FileUtil.cleanupStream(bis); + FileUtil.cleanupStream(fis); + FileUtil.cleanupStream(oos); + FileUtil.cleanupStream(zos); + FileUtil.cleanupStream(bos); + FileUtil.cleanupStream(fos); + FileUtil.cleanupStream(osw); + } + } + + public boolean hasRecord() { + return recordInfo != null; + } + + void createRecordInfo(BattleRules rules, int numRobots) { + try { + createTempFile(); + + fileWriteStream = new FileOutputStream(tempFile); + bufferedWriteStream = new BufferedOutputStream(fileWriteStream, 1024 * 1024); + objectWriteStream = new ObjectOutputStream(bufferedWriteStream); + } catch (IOException e) { + logError(e); + } + + recordInfo = new BattleRecordInfo(); + recordInfo.robotCount = numRobots; + recordInfo.battleRules = rules; + recordInfo.turnsInRounds = new Integer[rules.getNumRounds()]; + for (int i = 0; i < rules.getNumRounds(); i++) { + recordInfo.turnsInRounds[i] = 0; + } + } + + void updateRecordInfoResults(List results) { + recordInfo.results = results; + } + + void writeTurn(ITurnSnapshot turn, int round, int time) { + try { + if (time != recordInfo.turnsInRounds[round]) { + throw new Error("Something rotten"); + } + if (time == 0) { + objectWriteStream.reset(); + } + recordInfo.turnsInRounds[round]++; + recordInfo.roundsCount = round + 1; + objectWriteStream.writeObject(turn); + } catch (IOException e) { + logError(e); + } + } +} diff --git a/代码/workspace_robo4/robocode.content/.classpath b/代码/workspace_robo4/robocode.content/.classpath new file mode 100644 index 0000000..5da7d76 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/.classpath @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/.project b/代码/workspace_robo4/robocode.content/.project new file mode 100644 index 0000000..ce0efca --- /dev/null +++ b/代码/workspace_robo4/robocode.content/.project @@ -0,0 +1,18 @@ + + + robocode.content + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.samples + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/代码/workspace_robo4/robocode.content/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.content/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.content/pom.xml b/代码/workspace_robo4/robocode.content/pom.xml new file mode 100644 index 0000000..911d916 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + robocode.content + Robocode Content + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.samples + ${project.version} + + + net.sf.robocode + robocode.api + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + prepare-package + + copy + + + + + org.eclipse.jdt.core.compiler + ecj + 4.4 + jar + false + ${project.build.directory}/classes/compilers + ecj.jar + + + false + false + true + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + diff --git a/代码/workspace_robo4/robocode.content/robocode.content.iml b/代码/workspace_robo4/robocode.content/robocode.content.iml new file mode 100644 index 0000000..ecbc7a1 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/robocode.content.iml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/ReadMe.html b/代码/workspace_robo4/robocode.content/src/main/resources/ReadMe.html new file mode 100644 index 0000000..347ead6 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/ReadMe.html @@ -0,0 +1,233 @@ + + + + + + + + + + +

ReadMe for Robocode

+

Updated 06-Mar-2013 by Flemming N. Larsen

+

Robocode Home Page: http://robocode.sourceforge.net/

+

TABLE OF CONTENTS

+
    +
  1. What is Robocode?
  2. +
  3. History of Robocode
  4. +
  5. System Requirements
  6. +
  7. Getting Started
  8. +
  9. Robocode API
  10. +
  11. Robocode Repository
  12. +
  13. Community
  14. +
  15. Challenges
  16. +
  17. Competition
  18. +
  19. Command Line
  20. +
  21. Links
  22. +
  23. Reporting Defects
  24. +
  25. Feature Requests
  26. +
  27. Versions
  28. +
  29. News
  30. +
  31. How to contribute
  32. +
+

1. WHAT IS ROBOCODE?

+

Robocode is a programming game where the goal is to code a robot battle tank to compete against other robots in a battle arena. So the name Robocode is a short for "Robot code". The player is the programmer of the robot, who will have no direct influence on the game. Instead, the player must write the AI of the robot telling it how to behave and react on events occurring in the battle arena. Battles are running in real-time and on-screen.

+

The motto of Robocode is: Build the best, destroy the rest!

+

Besides being a programming game, Robocode is used for learning how to program, primarily in the Java language, but other languages like C# and Scala are becoming popular as well.

+

Schools and universities are using Robocode as part of teaching how to program, but also for studying artificial intelligence (AI). The concept of Robocode is easy to understand, and a fun way to learn how to program.

+

Robocode offers complete development environment, and comes with its own installer, built-in robot editor and Java compiler. Robocode only pre-requires that a JVM (Java Virtual Machine) to exist already on the system where Robocode is going to be installed. Hence, everything a robot developer needs to get started is provided with the main Robocode distribution file (robocode-xxx-setup.jar). Robocode also supports developing robots using external IDEs like e.g. Eclipse, IntelliJ IDEA, NetBeans, Visual Studio etc., which supports the developer much better than the robot editor in Robocode.

+

The fact that Robocode runs on the Java platform makes it possible to run it on any operating system with Java pre-installed, meaning that it will be able to run on Windows, Linux, Mac OS, but also UNIX and variants of UNIX. Note that Java 6 or newer must be installed on the system before Robocode is able to run. See the System Requirements for more information.

+

Be aware that many users of Robocode (aka Robocoders) find Robocode to be very fun, but also very addictive. :-)

+

Robocode comes free of charge and is being developed as a spare-time project where no money is involved. The developers of Robocode are developing on Robocode because they think it is fun, and because they improve themselves as developers this way.

+

Robocode is an Open Source project, which means that all sources are open to everybody. In addition, Robocode is provided under the terms of EPL (Eclipse Public License).

+

2. HISTORY OF ROBOCODE

+

The Robocode game was originally started by Mathew A. Nelson as a personal endeavor in late 2000 and became a professional one when he brought it to IBM, in the form of an AlphaWorks download, in July 2001.

+

IBM was interested in Robocode, as they saw an opportunity to promote Robocode as a fun way to get started with learning how to program in Java. IBM wrote lots of articles about Robocode, e.g. like Rock 'em, sock 'em Robocode! from AlphaWorks / developerWorks at IBM, a series of articles like Secrets from the Robocode masters, and "Robocode Rumble / RoboLeague".

+

The inspiration for creating Robocode came from Robot Battle, a programming game written by Brad Schick in 1992, which should still be alive. Robot Battle was, in turn, inspired by RobotWar, an Apple II+ game from the early 1980s.

+

The articles from IBM and the Robocode community behind the RoboWiki made Robocode very popular as programming game, and for many years Robocode has been used for education and research at schools and universities all over the world.

+

In the beginning of 2005, Mathew convinced IBM to release Robocode as Open Source on SourceForge. At this point, the development of Robocode had somewhat stopped. The community around Robocode began to develop their own versions of Robocode with bug fixes and new features, e.g. the OpenSourceRobocode/Contributions and later on the two projects, RobocodeNG and Robocode 2006, by Flemming N. Larsen.

+

Eventually, Flemming took over the Robocode project at SourceForge as administrator and developer in July 2006 to continue the original Robocode game. The RobocodeNG project was dropped, but Robocode 2006 was merged into the official Robocode version 1.1 containing lots of improvements. Since then, lots of new versions of Robocode have been released with more and more features and contributions from the community.

+

In May 2007, the RoboRumble client got built into Robocode. RoboRumble is widely used by the Robocode community for creating up-to-date robot ranking lists for the 1-to-1, Melee, Team, and Twin Dual competitions.

+

Since May 2010 a .NET plugin is provided for Robocode using a .NET / Java bridge, which makes it possible to develop robots for .NET beside developing robots in Java. This part was made by Pavel Savara, who is a major Robocode contributor.

+

3. SYSTEM REQUIREMENTS

+

In order to run Robocode, Java 6 Standard Edition (SE) or a newer version of Java must be installed on your system. Both the Java Runtime Environment (JRE) and the Java Developer Kit (JDK) can be used. Note that the JRE does not include the standard Java compiler (javac), but the JDK does. However, Robocode comes with a built-in compiler (ECJ). Hence, it is sufficient running Robocode on the JRE.

+

Also note that it is important that these environment variables have been set up prior to running Robocode:

+
    +
  • JAVA_HOME must be setup to point at the home directory for Java (JDK or JRE).
    Windows example: JAVA_HOME=C:\Program Files\Java\jdk1.6.0_41
    UNIX, Linux, Mac OS example: JAVA_HOME=/usr/local/jdk1.6.0_41

  • +
  • PATH must include the path to the bin of the Java home directory (JAVA_HOME) that includes java.exe for starting the Java virtual Machine (JVM).
    Windows example: PATH=%PATH%;%JAVA_HOME%
    UNIX, Linux, Mac OS example: PATH=${PATH}:${JAVA_HOME}/bin

  • +
+

You can read more details from here:

+ +

If you want to program robots in .NET or control Robocode from a .NET application, you need to install the Robocode .NET API plug-in on top of Robocode. The plug-in is installed by double-clicking the robocode.dotnet-xxx-setup.jar the same way as Robocode itself is installed.

+

4. GETTING STARTED

+

Most documentation about Robocode is provided thru the RoboWiki, which contains the official documentation about Robocode, but which also hosts the community around Robocode. It is highly recommended to read the articles on the RoboWiki for getting started with Robocode. These articles are provided from here:

+ +

You should read about the anatomy of a robot, the game physics, scoring etc.

+

To learn more about developing robots for .NET, these articles are a good starting point:

+ +

5. ROBOCODE API

+

The Robocode API is provided as HTML pages for both the Java and .NET platform.

+ +

The Robocode API actually consists of 3 different APIs.

+
    +
  • Robot API: Within the Java package robocode and .NET namespace Robocode.
    The Robot API is used for developing robots, and is the only part of the API that robots are allowed to access.

  • +
  • Robot Interfaces: Within the Java package robocode.robotinterfaces and .NET namespace Robocode.RobotInterfaces.
    The Robot Interfaces are used for developing new robot types with a different API that the standard Robot API.
    Note: The game rules and robot behaviors cannot be changed.

  • +
  • Control API: Within the Java package robocode.control and .NET namespace Robocode.Control.
    The Control API is used for letting another application start up battles with selected robots in Robocode and retrieve the results. It is also possible to get snapshots of robots and bullets (like position, heading, energy level etc.) at a specific time in a battle.

  • +
+

6. ROBOCODE REPOSITORY

+

If you want to try out new robots than the sample robots that come with Robocode, you should visit the Robocode Repository.

+

Robots are available under the Bots section of the repository.

+

The Robocode Repository is developed and maintained by David Lynn as a project independently of the Robocode project.

+

7. COMMUNITY

+

The community around Robocode is using the RoboWiki as communication channel. At the RoboWiki, people share new ideas, code snippets, algorithms, strategies, and lots of other stuff about Robocode. New official documentation from the developers of Robocode will be put at the RoboWiki as well.

+

On the RoboWiki, these strategies are provided:

+ +

The code snippets are also provided on the RoboWiki:

+ +

8. CHALLENGES

+

A good way to improve you self as a robot developer is to try out some real challenges. On the RoboWiki, two famous challenges exist for testing/studying a robots movement, targeting, and gun abilities:

+ +

9. COMPETITION

+

If you want to challenge your robot(s) and yourself as robot developer, the RoboRumble@Home is the best way to do it. RoboRumble is the ultimate collaborative effort to have a live, up-to-date ranking of Robocode bots. It uses the power of available Robocoders' computers to distribute the effort of running battles and building the rankings.

+

RoboRumble is actually 3 different rumbles:

+
    +
  • RoboRumble (aka 1v1): One robot versus another robot - both picked at random. These two robots a alone on the battle field.
  • +
  • MeleeRumble: Ten robots picked at random all battle against each other..
  • +
  • TeamRumble: One team versus another team - both picked at random. Each team consists of five or less robots.
  • +
+

In order to get started with RoboRumble, you should read this page:

+ +

Note that the RoboRumble@Home client is built into Robocode and can be started using the batch/shell/command files:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
WindowsUNIX / LinuxMac OS
RoboRumbleroborumble.batroborumble.shroborumble.command
MeleeRumblemeleerumble.batmeleerumble.shmeleerumble.command
TeamRumbleteamrumble.batteamrumble.shteamrumble.command
+

Two other competitions exists which are:

+
    +
  • Twin Duel: Two teams battle on an 800x800 field. Each team consists of two robots (twins).
  • +
  • Hat League: Two teams not knowing each other are paired together at random (like drawing names from a hat). Each team consists of two robots. These two teams must work together and defeat two other teams that have also been picked at random.
  • +
+

10. COMMAND LINE

+

It is possible to specify options and predefined properties from the command-line when running Robocode. The usage of these can be listed by writing this from a command prompt or shell:

+
robocode -help
+

For example, it is possible to:

+
    +
  • disable the graphical user interface (GUI).
  • +
  • disable security that is specific to Robocode (but does not override the security that comes with the JVM).
  • +
  • enable/disable the debugging mode, useful when debugging robots.
  • +
  • play a battle based on an existing Robocode .battle file.
  • +
  • replay a recorded battle visually.
  • +
  • save the results of battles in a comma-separated file.
  • +
+

You can read more details here:

+ + +

Links relevant to Robocode are provided on the home page of Robocode:

+ +

Other links are provided from the RoboWiki - especially for challenges and competitions:

+ +

The is also a Wikipedia page available about Robocode, which provides good links to movement and targeting strategies, competitions, and other sites about Robocode:

+ +

12. REPORTING DEFECTS

+

If you discover a defect (bug) in Robocode you are encouraged to report the issue as soon as you discover it - the sooner the better.

+

A bug report should be reported on the Bugs page on the SourceForge site for Robocode. Each bug report will be prioritized among other bug reports depending on its impact on the game.

+

It will be a great help if you describe how to see or which steps to do in order to reproduce the defect. You are very welcome to provide a screen shot, source code or anything else that will show the bug. It is also a very good idea to write which system and version of Robocode and Java you are using.

+

If you are a registered user at SourceForge (register here) you will be able to add a "monitor" on your bug report. This way you will be able to receive notifications when someone add comments to your report, but will also be able to better track the current status of the bug, e.g. when the bug is fixed and with which version of Robocode the fix is available.

+

If you are a developer yourself, and have a good idea of how the bug could be fixed, you are more than welcome to do so. By fixing the bug, you will become a contributor of Robocode yourself. You can learn more about how to contribute here. Note that we accept bug fixes under the terms of EPL.

+

13. FEATURE REQUESTS

+

If you got an idea for a new feature or improvement for Robocode, you are very welcome to share your idea by summiting a feature request.

+

A feature request should be put on the Feature Requests on the SourceForge site for Robocode. Each feature request will be prioritized among other feature requests.

+

It will be a great help if you describe your idea in detail, and how you think it could be implemented into Robocode. For example, will it be possible to extend an existing feature with your idea?

+

If you are a registered user at SourceForge (register here) you will be able to add a "monitor" on your request. This way you will be able to receive notifications when someone add comments to your request entry, but will also be able to better track the current status of your entry, e.g. when the feature has been implemented and with which version of Robocode it will be available.

+

If you are a developer yourself, and have a good idea of how the feature could be implemented, you are more than welcome to do so if the feature is being accepted. By implementing the feature, you will become a contributor of Robocode yourself. You can learn more about how to contribute here. Note that we accept implementations under the terms of EPL.

+

14. VERSIONS

+

Robocode is continuously under development, and you should be aware that three different release types exist for Robocode:

+
    +
  • Alpha version is an unofficial "snapshot" version of Robocode that is under development and not feature complete yet. It is normally provided for the person that has put a bug report or feature request on the tracker for Robocode, which needs to be verified. Alpha versions are not meant to be redistributed at all.

  • +
  • Beta version is an official release that is considered feature complete, and which intended for everybody to try out and test regarding all new features and changes, but which is also considered "unstable", and might contain some unwanted side-effects due to the changes made to this version compared to the last final version of Robocode. Defects or undesired behaviors should be reported as soon as they are discovered so the issues can be fixed before the final release. Everybody is encouraged to take part in the testing Beta versions of Robocode.

  • +
  • Final version is (as it says) the final version of a specific and official release of Robocode, and where new features and bug fixes have been tested. Note, that the release will not state "final" on the distribution files for Robocode like it is the case for Alpha and Beta versions.

  • +
+

15. NEWS

+

News about Robocode is put on the blog spot for Robocode. Here it is possible subscribe to a RSS feed to receive news about Robocode.

+ +

You can also follow Robocode on Twitter and Facebook here:

+ +

The RoboWiki can be followed on Twitter as well:

+ +

16. HOW TO CONTRIBUTE

+

If you want to contribute to Robocode with e.g. a new feature or bug fix, you should read the Developers Guide for building Robocode.

+

Note that we accept code changes under the terms of EPL.

+

There exist no or little documentation about the internals of Robocode, and the code base will need to be examined by a contributor in order to get an insight of how Robocode is implemented. Thus, it required a skilled Java developer to figure out how Robocode is put together.

+

Robocode is divided into several modules. You can read Pavel Savara's blog to get a good overview of Robocode here:

+ +

Help for Robocode internals can be provided through the Robocode Developers Discussion Group where you can register yourself, and start up a new topic. This is the best way of getting information and asking about details for the internals in Robocode.

+

If a contribution is a somewhat small change to involves under 10 files, then the preferred way is to provide the contribution as a patch file that can be applied to the existing Robocode sources. Otherwise, you can be granted a Subversion branch for your work, where you can commit your changes. Later, this branch needs to be merged into the trunk be the administrators of Robocode and tested carefully. Additional work might be done by other Robocode developers to finalize the work.

+ + diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/ReadMe.txt b/代码/workspace_robo4/robocode.content/src/main/resources/ReadMe.txt new file mode 100644 index 0000000..1fe94cc --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/ReadMe.txt @@ -0,0 +1,471 @@ +## ReadMe for Robocode + +Updated 06-Mar-2013 by Flemming N. Larsen + +Robocode Home Page: +[http://robocode.sourceforge.net/](http://robocode.sourceforge.net/) + +### TABLE OF CONTENTS + +1. [What is Robocode?](#what-is-robocode) +2. [History of Robocode](#history-of-robocode) +3. [System Requirements](#system-requirements) +4. [Getting Started](#getting-started) +5. [Robocode API](#robocode-api) +6. [Robocode Repository](#robocode-repository) +7. [Community](#community) +8. [Challenges](#challenges) +9. [Competition](#competition) +10. [Command Line](#command-line) +11. [Links](#links) +12. [Reporting Defects](#reporting-defects) +13. [Feature Requests](#feature-requests) +14. [Versions](#versions) +15. [News](#news) +16. [How to contribute](#how-to-contribute) + +### 1. WHAT IS ROBOCODE? + +Robocode is a programming game where the goal is to code a robot battle +tank to compete against other robots in a battle arena. So the name +Robocode is a short for "Robot code". The player is the programmer of +the robot, who will have no direct influence on the game. Instead, the +player must write the AI of the robot telling it how to behave and +react on events occurring in the battle arena. Battles are running in +real-time and on-screen. + +**The motto of Robocode is: Build the best, destroy the rest!** + +Besides being a programming game, Robocode is used for learning how to +program, primarily in the Java language, but other languages like C# +and Scala are becoming popular as well. + +Schools and universities are using Robocode as part of teaching how to +program, but also for studying artificial intelligence (AI). The +concept of Robocode is easy to understand, and a fun way to learn how +to program. + +Robocode offers complete development environment, and comes with its +own installer, built-in robot editor and Java compiler. Robocode only +pre-requires that a JVM (Java Virtual Machine) to exist already on the +system where Robocode is going to be installed. Hence, everything a +robot developer needs to get started is provided with the main Robocode +distribution file (`robocode-xxx-setup.jar`). Robocode also supports +developing robots using external IDEs like e.g. +[Eclipse](http://www.eclipse.org/downloads/), +[IntelliJ IDEA](http://www.jetbrains.com/idea/), +[NetBeans](http://netbeans.org/), +[Visual Studio](http://msdn.microsoft.com/en-gb/vstudio/) etc., which +supports the developer much better than the robot editor in Robocode. + +The fact that Robocode runs on the Java platform makes it possible to +run it on any operating system with Java pre-installed, meaning that it +will be able to run on Windows, Linux, Mac OS, but also UNIX and +variants of UNIX. Note that Java 6 or newer must be installed on the +system before Robocode is able to run. See the [System +Requirements](#system-requirements) for more information. + +Be aware that many users of Robocode (aka Robocoders) find Robocode to +be very fun, but also very addictive. :-) + +Robocode comes free of charge and is being developed as a spare-time +project where no money is involved. The developers of Robocode are +developing on Robocode because they think it is fun, and because they +improve themselves as developers this way. + +Robocode is an Open Source project, which means that all sources are +open to everybody. In addition, Robocode is provided under the terms of +[EPL](http://www.eclipse.org/legal/epl-v10.html) (Eclipse Public +License). + +### 2. HISTORY OF ROBOCODE + +The Robocode game was originally started by **Mathew A. Nelson** as a +personal endeavor in late 2000 and became a professional one when he +brought it to IBM, in the form of an AlphaWorks download, in July 2001. + +IBM was interested in Robocode, as they saw an opportunity to promote +Robocode as a fun way to get started with learning how to program in +Java. IBM wrote lots of articles about Robocode, e.g. like +[Rock 'em, sock 'em Robocode!](http://www.ibm.com/developerworks/java/library/j-robocode/) +from AlphaWorks / developerWorks at IBM, a series of articles like +[Secrets from the Robocode masters](http://www.ibm.com/developerworks/java/library/j-robotips/), +and "Robocode Rumble / RoboLeague". + +The inspiration for creating Robocode came from +[Robot Battle](http://www.robotbattle.com/history.php), a programming +game written by Brad Schick in 1992, which should still be alive. Robot +Battle was, in turn, inspired by +[RobotWar](http://www.robotbattle.com/history.php), an Apple II+ game +from the early 1980s. + +The articles from IBM and the Robocode community behind the RoboWiki made +Robocode very popular as programming game, and for many years Robocode has been +used for education and research at schools and universities all over the world. + +In the beginning of 2005, Mathew convinced IBM to release Robocode as +**Open Source** on SourceForge. At this point, the development of Robocode had +somewhat stopped. The community around Robocode began to develop their own +versions of Robocode with bug fixes and new features, e.g. the +[OpenSourceRobocode/Contributions](http://old.robowiki.net/robowiki?OpenSourceRobocode/Contributions) +and later on the two projects, +[RobocodeNG and Robocode 2006](http://old.robowiki.net/robowiki?RobocodeNG/Archive), by **Flemming N. Larsen**. + +Eventually, Flemming took over the Robocode project at SourceForge as +administrator and developer in July 2006 to continue the original Robocode game. +The RobocodeNG project was dropped, but Robocode 2006 was merged into the +official Robocode version 1.1 containing lots of improvements. Since then, +lots of new versions of Robocode have been released with more and more features +and contributions from the community. + +In May 2007, the [RoboRumble](http://robowiki.net/wiki/RoboRumble) client got +built into Robocode. RoboRumble is widely used by the Robocode community for +creating up-to-date robot ranking lists for the 1-to-1, Melee, Team, and +Twin Dual competitions. + +Since May 2010 a **.NET plugin** is provided for Robocode using a .NET / Java +bridge, which makes it possible to develop robots for .NET beside developing +robots in Java. This part was made by **Pavel Savara**, who is a major Robocode +contributor. + +### 3. SYSTEM REQUIREMENTS + +In order to run Robocode, Java 6 Standard Edition (SE) or a newer +version of Java must be installed on your system. Both the Java Runtime +Environment (JRE) and the Java Developer Kit (JDK) can be used. Note +that the JRE does not include the standard Java compiler (javac), but +the JDK does. However, Robocode comes with a built-in compiler (ECJ). +Hence, it is sufficient running Robocode on the JRE. + +Also note that it is important that these environment variables have +been set up prior to running Robocode: + +- `JAVA_HOME` must be setup to point at the home directory for Java + (JDK or JRE). + Windows example: `JAVA_HOME=C:\Program Files\Java\jdk1.6.0_41` + UNIX, Linux, Mac OS example: `JAVA_HOME=/usr/local/jdk1.6.0_41` + +- `PATH` must include the path to the `bin` of the Java home + directory (`JAVA_HOME`) that includes `java.exe` for starting the + Java virtual Machine (JVM). + Windows example: `PATH=%PATH%;%JAVA_HOME%` + UNIX, Linux, Mac OS example: `PATH=${PATH}:${JAVA_HOME}/bin` + +You can read more details from here: + +- [System Requirements](http://robowiki.net/wiki/Robocode/System_Requirements) + +If you want to program robots in .NET or control Robocode from a .NET +application, you need to install the Robocode .NET API plug-in on top of +Robocode. The plug-in is installed by double-clicking the +`robocode.dotnet-xxx-setup.jar` the same way as Robocode itself is +installed. + +### 4. GETTING STARTED + +Most documentation about Robocode is provided thru the +[RoboWiki](http://robowiki.net), which contains the official +documentation about Robocode, but which also hosts the community around +Robocode. It is highly recommended to read the articles on the RoboWiki +for getting started with Robocode. These articles are provided from +here: + +- [Getting Started](http://robowiki.net/wiki/Robocode/Getting_Started) + +You should read about the anatomy of a robot, the game physics, scoring +etc. + +To learn more about developing robots for .NET, these articles are a +good starting point: + +- [Create a .NET robot with Visual Studio](http://robowiki.net/wiki/Robocode/.NET/Create_a_.NET_robot_with_Visual_Studio) +- [Debug a .NET robot with Visual Studio](http://robowiki.net/wiki/Robocode/.NET/Debug_a_.NET_robot_in_Visual_Studio) + +### 5. ROBOCODE API + +The Robocode API is provided as HTML pages for both the Java and .NET +platform. + +- [Java Robot API](http://robocode.sourceforge.net/docs/robocode/) +- [Java Control API](http://robocode.sourceforge.net/docs/robocode/index.html?robocode/control/package-summary.html) +- [.NET Robot API](http://robocode.sourceforge.net/docs/robocode.dotnet/Index.html) +- [.NET Control API](http://robocode.sourceforge.net/docs/robocode.dotnet.control/Index.html) + +The Robocode API actually consists of 3 different APIs. + +- **Robot API**: Within the Java package `robocode` and .NET namespace + `Robocode`. + The Robot API is used for developing robots, and is the only part of + the API that robots are allowed to access. + +- **Robot Interfaces**: Within the Java package + `robocode.robotinterfaces` and .NET namespace + `Robocode.RobotInterfaces`. + The Robot Interfaces are used for developing new robot types with a + different API that the standard Robot API. + **Note:** *The game rules and robot behaviors cannot be changed.* + +- **Control API**: Within the Java package `robocode.control` and .NET + namespace `Robocode.Control`. + The Control API is used for letting another application start up + battles with selected robots in Robocode and retrieve the results. + It is also possible to get snapshots of robots and bullets (like + position, heading, energy level etc.) at a specific time in a battle. + +### 6. ROBOCODE REPOSITORY + +If you want to try out new robots than the sample robots that come with +Robocode, you should visit the [Robocode +Repository](http://robocoderepository.com/). + +Robots are available under the +[Bots](http://robocoderepository.com/Categories.jsp) section of the +repository. + +The Robocode Repository is developed and maintained by David Lynn as a +project independently of the Robocode project. + +### 7. COMMUNITY + +The community around Robocode is using the RoboWiki as communication +channel. At the RoboWiki, people share new ideas, code snippets, +algorithms, strategies, and lots of other stuff about Robocode. New +official documentation from the developers of Robocode will be put at +the RoboWiki as well. + +On the RoboWiki, these strategies are provided: + +- [Radar](http://robowiki.net/wiki/Radar) +- [Movement](http://robowiki.net/wiki/Category:Movement) +- [Targeting](http://robowiki.net/wiki/Category:Targeting) + +The code snippets are also provided on the RoboWiki: + +- [Code Snippets](http://robowiki.net/wiki/Category:Code_Snippets) + +### 8. CHALLENGES + +A good way to improve you self as a robot developer is to try out some +real challenges. On the RoboWiki, two famous challenges exist for +testing/studying a robots movement, targeting, and gun abilities: + +- [Movement Challenge](http://robowiki.net/wiki/Movement_Challenge_(original)) +- [Targeting Challenge](http://robowiki.net/wiki/Targeting_Challenge_(original)) +- [RoboRumble Gun Challenge](hhttp://robowiki.net/wiki/RoboRumble_Gun_Challenge) + +### 9. COMPETITION + +If you want to challenge your robot(s) and yourself as robot developer, +the [RoboRumble@Home](http://robowiki.net/wiki/RoboRumble) is the best +way to do it. RoboRumble is the ultimate collaborative effort to have a +live, up-to-date ranking of Robocode bots. It uses the power of +available Robocoders' computers to distribute the effort of running +battles and building the rankings. + +RoboRumble is actually 3 different rumbles: + +- **RoboRumble** (aka 1v1): One robot versus another robot - both + picked at random. These two robots a alone on the battle field. +- **MeleeRumble**: Ten robots picked at random all battle against + each other.. +- **TeamRumble**: One team versus another team - both picked at + random. Each team consists of five or less robots. + +In order to get started with RoboRumble, you should read this page: + +- [Starting With RoboRumble](http://robowiki.net/wiki/RoboRumble/Starting_With_RoboRumble) + +Note that the RoboRumble@Home client is built into Robocode and can +be started using the batch/shell/command files: + +| | Windows | UNIX / Linux | Mac OS | +|-----------------+-------------------+------------------+-----------------------| +| **RoboRumble** | `roborumble.bat` | `roborumble.sh` | `roborumble.command` | +| **MeleeRumble** | `meleerumble.bat` | `meleerumble.sh` | `meleerumble.command` | +| **TeamRumble** | `teamrumble.bat` | `teamrumble.sh` | `teamrumble.command` | + +Two other competitions exists which are: + +- [Twin Duel](http://robowiki.net/wiki/Twin_Duel): Two teams + battle on an 800x800 field. Each team consists of two robots + (twins). +- [Hat League](http://robowiki.net/wiki/Hat_League): Two teams not + knowing each other are paired together at random (like drawing + names from a hat). Each team consists of two robots. These two + teams must work together and defeat two other teams that have also + been picked at random. + +### 10. COMMAND LINE + +It is possible to specify options and predefined properties from the +command-line when running Robocode. The usage of these can be listed by +writing this from a command prompt or shell: + + robocode -help + +For example, it is possible to: + +- disable the graphical user interface (GUI). +- disable security that is specific to Robocode (but does not + override the security that comes with the JVM). +- enable/disable the debugging mode, useful when debugging robots. +- play a battle based on an existing Robocode .battle file. +- replay a recorded battle visually. +- save the results of battles in a comma-separated file. + +You can read more details here: + +- [Console Usage](http://robowiki.net/w/index.php?title=Robocode/Console_Usage) + +### 11. LINKS + +Links relevant to Robocode are provided on the home page of Robocode: + +- [Home Page of Robocode](http://robocode.sourceforge.net/) + +Other links are provided from the RoboWiki - especially for challenges +and competitions: + +- [RoboWiki](http://robowiki.net/) + +The is also a Wikipedia page available about Robocode, which provides +good links to movement and targeting strategies, competitions, and other +sites about Robocode: + +- [Robocode on Wikipedia](http://en.wikipedia.org/wiki/Robocode) + +### 12. REPORTING DEFECTS + +If you discover a defect (bug) in Robocode you are encouraged to report +the issue as soon as you discover it - the sooner the better. + +A bug report should be reported on the [Bugs](http://http://sourceforge.net/p/robocode/bugs//p/robocode/bugs/) +page on the SourceForge site for Robocode. Each bug report will be +prioritized among other bug reports depending on its impact on the game. + +It will be a great help if you describe how to see or which steps to do +in order to reproduce the defect. You are very welcome to provide a +screen shot, source code or anything else that will show the bug. It is +also a very good idea to write which system and version of Robocode and +Java you are using. + +If you are a registered user at SourceForge (register +[here](http://sourceforge.net/account/registration/)) you will be able +to add a "monitor" on your bug report. This way you will be able to +receive notifications when someone add comments to your report, but will +also be able to better track the current status of the bug, e.g. when +the bug is fixed and with which version of Robocode the fix is +available. + +If you are a developer yourself, and have a good idea of how the bug +could be fixed, you are more than welcome to do so. By fixing the bug, +you will become a contributor of Robocode yourself. You can learn more +about how to contribute [here](#how-to-contribute). Note that we accept +bug fixes under the terms of +[EPL](http://www.eclipse.org/legal/epl-v10.html). + +### 13. FEATURE REQUESTS + +If you got an idea for a new feature or improvement for Robocode, you +are very welcome to share your idea by summiting a feature request. + +A feature request should be put on the +[Feature Requests](http://sourceforge.net/p/robocode/feature-requests/) +on the SourceForge site for Robocode. Each feature request will be +prioritized among other feature requests. + +It will be a great help if you describe your idea in detail, and how you +think it could be implemented into Robocode. For example, will it be +possible to extend an existing feature with your idea? + +If you are a registered user at SourceForge (register +[here](http://sourceforge.net/account/registration/)) you will be able +to add a "monitor" on your request. This way you will be able to receive +notifications when someone add comments to your request entry, but will +also be able to better track the current status of your entry, e.g. when +the feature has been implemented and with which version of Robocode it +will be available. + +If you are a developer yourself, and have a good idea of how the feature +could be implemented, you are more than welcome to do so if the feature +is being accepted. By implementing the feature, you will become a +contributor of Robocode yourself. You can learn more about how to +contribute [here](#how-to-contribute). Note that we accept +implementations under the terms of +[EPL](http://www.eclipse.org/legal/epl-v10.html). + +### 14. VERSIONS + +Robocode is continuously under development, and you should be aware that +three different release types exist for Robocode: + +- **Alpha** version is an unofficial "snapshot" version of Robocode + that is under development and not feature complete yet. It is + normally provided for the person that has put a bug report or + feature request on the tracker for Robocode, which needs to be + verified. Alpha versions are not meant to be redistributed at all. + +- **Beta** version is an official release that is considered feature + complete, and which intended for everybody to try out and test + regarding all new features and changes, but which is also + considered "unstable", and might contain some unwanted side-effects + due to the changes made to this version compared to the last final + version of Robocode. Defects or undesired behaviors should be + reported as soon as they are discovered so the issues can be fixed + before the final release. Everybody is encouraged to take part in + the testing Beta versions of Robocode. + +- **Final** version is (as it says) the final version of a specific + and official release of Robocode, and where new features and bug + fixes have been tested. Note, that the release will not state + "final" on the distribution files for Robocode like it is the case + for Alpha and Beta versions. + +### 15. NEWS + +News about Robocode is put on the blog spot for Robocode. Here it +is possible subscribe to a RSS feed to receive news about Robocode. + +- [Robocode News](http://robo-code.blogspot.com/) + +You can also follow Robocode on Twitter and Facebook here: + +- [Twitter for Robocode](http://twitter.com/robocode) +- [Robocode on Facebook](http://www.facebook.com/group.php?gid=129627130234) + +The RoboWiki can be followed on Twitter as well: + +- [Twitter for RoboRumble](http://twitter.com/robowiki) + +### 16. HOW TO CONTRIBUTE + +If you want to contribute to Robocode with e.g. a new feature or bug +fix, you should read the [Developers Guide for building +Robocode.](http://robowiki.net/wiki/Robocode/Developers_Guide_for_building_Robocode) + +Note that we accept code changes under the terms of +[EPL](http://www.eclipse.org/legal/epl-v10.html). + +There exist no or little documentation about the internals of Robocode, +and the code base will need to be examined by a contributor in order to +get an insight of how Robocode is implemented. Thus, it required a +skilled Java developer to figure out how Robocode is put together. + +Robocode is divided into several modules. You can read Pavel Savara's +blog to get a good overview of Robocode here: + +- [Robocode modules](http://zamboch.blogspot.com/2009/06/robocode-modules-as-in-version-17.html) + +Help for Robocode internals can be provided through the [Robocode +Developers Discussion Group](https://groups.google.com/forum/?fromgroups#!forum/robocode-developers) +where you can register yourself, and start up a new topic. This is the best +way of getting information and asking about details for the internals in +Robocode. + +If a contribution is a somewhat small change to involves under 10 files, +then the preferred way is to provide the contribution as a patch file +that can be applied to the existing Robocode sources. Otherwise, you can +be granted a Subversion branch for your work, where you can commit your +changes. Later, this branch needs to be merged into the trunk be the +administrators of Robocode and tested carefully. Additional work might +be done by other Robocode developers to finalize the work. \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/battles/intro.battle b/代码/workspace_robo4/robocode.content/src/main/resources/battles/intro.battle new file mode 100644 index 0000000..8bcded0 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/battles/intro.battle @@ -0,0 +1,8 @@ +#Battle Properties +robocode.battleField.width=800 +robocode.battleField.height=600 +robocode.battle.numRounds=1 +robocode.battle.gunCoolingRate=0.1 +robocode.battle.rules.inactivityTime=450 +robocode.battle.selectedRobots=sample.Tracker,sample.SittingDuck +robocode.battle.initialPositions=(50,50,0),(?,?,?) \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/battles/sample.battle b/代码/workspace_robo4/robocode.content/src/main/resources/battles/sample.battle new file mode 100644 index 0000000..2be49ab --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/battles/sample.battle @@ -0,0 +1,8 @@ +#Battle Properties +robocode.battleField.width=800 +robocode.battleField.height=600 +robocode.battle.numRounds=10 +robocode.battle.gunCoolingRate=0.1 +robocode.battle.rules.inactivityTime=450 +robocode.battle.hideEnemyNames=true +robocode.battle.selectedRobots=sample.Corners,sample.Fire,sample.MyFirstRobot,sample.SittingDuck,sample.Walls diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/compilers/CompilerTest.java b/代码/workspace_robo4/robocode.content/src/main/resources/compilers/CompilerTest.java new file mode 100644 index 0000000..057737d --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/compilers/CompilerTest.java @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +public class CompilerTest { + public static void main(String args[]) { + System.out.println("Compiler operational"); + } +} diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocode.png b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocode.png new file mode 100644 index 0000000000000000000000000000000000000000..99b0d5b7a52090568d08ba99242da7281f175746 GIT binary patch literal 3918 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeMeleeRumble.desktop b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeMeleeRumble.desktop new file mode 100644 index 0000000..2b6a8cf --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeMeleeRumble.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=Robocode MeleeRumble +GenericName=Ranking system of Robocode bots +Comment=Run MeleeRumble battles for the LiteRumble +Icon=roborumble +Exec=robocode-MeleeRumble +Categories=Game;StrategyGame; \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeRoboRumble.desktop b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeRoboRumble.desktop new file mode 100644 index 0000000..f366fdf --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeRoboRumble.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=Robocode RoboRumble +GenericName=Ranking system of Robocode bots +Comment=Run RoboRumble battles for the LiteRumble +Icon=roborumble +Exec=robocode-RoboRumble +Categories=Game;StrategyGame; diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeRobocode.desktop b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeRobocode.desktop new file mode 100644 index 0000000..89c34f6 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeRobocode.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=Robocode +GenericName=Tank AI programming game for Java and .NET +Comment=Build the best - destroy the rest! +Icon=robocode +Exec=robocode-Robocode +Categories=Game;StrategyGame; diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeTeamRumble.desktop b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeTeamRumble.desktop new file mode 100644 index 0000000..d0f1e25 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeTeamRumble.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=Robocode TeamRumble +GenericName=Ranking system of Robocode bots +Comment=Run TeamRumble battles for the LiteRumble +Icon=roborumble +Exec=robocode-TeamRumble +Categories=Game;StrategyGame; \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeTwinDuel.desktop b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeTwinDuel.desktop new file mode 100644 index 0000000..564090b --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/robocodeTwinDuel.desktop @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Version=1.0 +Name=Robocode TwinDuel +GenericName=Ranking system of Robocode bots +Comment=Run TwinDuel battles for the LiteRumble +Icon=roborumble +Exec=robocode-TwinDuel +Categories=Game;StrategyGame; \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/desktop/roborumble.png b/代码/workspace_robo4/robocode.content/src/main/resources/desktop/roborumble.png new file mode 100644 index 0000000000000000000000000000000000000000..f1560d15acaa753cf5b06cc5c58bf4d9295c6c4b GIT binary patch literal 3401 zcmV-P4Yu-$P)00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D02*{fSaefwW^{L9 za%BKeVQFr3E>1;MAa*k@H7+qRNAp5A000cQNkl|`x*$lfFVE-Py|BQg(B8gTdB*SBBD|k5NnG%qEu;ZpIUrx zw009Mgn6eX(|PkcZ{|&3UxG6|!(<@&`Tl#qd(OS*`+@Km{=yr~ojX@oS65S0Q~vYY zg?aPlty{Nl+qP{^PEN=~{_fiXZEfw%n>UAqgp`z&)YsRO$>jO-=c}r!%0Hgv0B5#t z-Abp^larG_{P4q(k&!cJ&gAFkFI~D+e#LBthK9zLEnC9E!otJDckI~F+uQr>*|Yoi z@Avoj~5T)EQC%?%ODfC?ZJ zKR-Wj8Z9j?4LL9v47|U6`}R$nHZ5GZ5DCkFS-C)e)YsQX!$G^0g^td{X0wBWgM(SD z#H7U3@bJnKVVOu2$>Bi94Gj&Qot@yAmX?-$31wluP?ZcJ(h*e3J%6= z^o||rTyB1VU%9bS9o@U7xmhR_f=GSm&VBv$*B35aaB*=_=5Rn$H#Rm#5THtAWF+X0 zSH#U`vG9FrN=ijUSc|23%VO;gb=7ultyV5a($s{RaPZ*42M->6{`u$73Hp^1h=g0B z`WUW=04&F@BVsO>iweAvFE>9szl7n}uzICfo}mI~3!7L={5AfSgpg?v6A^R=m|DJ3NZMF91&`!t##E5K0@Y2M7xYTl+QWax5T zEfd$QZJIx)OHHMH?V6UH>>9B+H#ZluM&{<`=1{+UT}1*rhwgsq(j}1L*s)^}fIkqx z^z&So%u;K~R2^(5{OvU1`^%~~KVGsc)5Xu)ZqGuEcaejcX=||nb%=|NMT3HrD=RCZ zBKf+Cgq@w;jT<+fK7BekIEWqf@}e=kErNZFIKl3Mtp-^>E5!M_L!E^0hY6F{)s8fo zMQk={S0^Bcy=JCGsi~P+SrOsk)z#JK&!0ba>Xez8nS5Qv0Ib#1(>r|lFh*=wS65zM zp0l$v+1ZiiO$*u{R7$ii+-_f$y=re7;qY$4!!v|mt`qh|YV6fiZP!v45Umm;IaDeY zHfdmB;NioEmoHx?5{Xz-abm!o(1mzB9&$iyhkQLeJg8JR8ja>kbq%LD^S6=qRXjTs?A>~NHZ5D7z{`V62E1lpg6X=@QNH#Q&UmHz`(%Ot5+)_0RS@r6zcBoPESu4i^Y#0JsQ4t zt)jBh-^(kFOe%A*Yk0@7e$DDM_NHi-k-M84iS%pe0Et9GC$P7-haT3hT?-p4Ur~{e zi2=s5xw#oMC@(KZCa?^M2_bsAy9Y5CQQlrb9<+#HE4r(pBZ=(fM8Ze5wzlXzh#SBb zDAQ9Q2hcYzF0Qn+6uN{Q5xtd_l^c~xp}3HK4cFez&VlS;>Poh9Bsn8`^c;`}2LtRn z43&H##Y1N1FikOri;9ZimLX+if&+l#8z4%+37oOFx3M8QI5^td+aUoQH8I7MMtT`= zZ5MB0)chG8)m7$@bGWQ;UBf`NK(YLm? zGMP+WU0u8hcZoJC5{cl|+S}V9?%xuyv9STQ&~}lk@=pSQ%+e($CSp5RtXLuQWY8i! z5(d-l+qcKZ#~T|Py}Z1@8ANYnWQ4Y}e*OAc5xorH08WPgYA3-fZ14vke1PajM@KOe zP!ROW4I4H*Cq7kDok26FhhB9DISS2uK6+ShQ#n92hDyE3!fengoKY_JX7Cl$Vv| zQbECVb=8ER@N7l-*|WW9;Sz}?BO^oBK+qgbOiXZiuc@hlSy0ZSgnxscs!H6l#n(Jt zUhA_aa>6{Z)ZUPm&=7MTfTfbE=FsDFF17Q5G<#Kg@rP0jI8!6 z)#g+guX+^B_$7-c&Ciw=Wl1 zN&$xhR|5@bYHBJ?0CQAT^_DCNv9}v9E|l)AoG!{o=+eBbsqFO09DYY`jzm=66TM?J zjP;De?xTAqFqwQlA7@q^y$&|(%?3sqT`g&tyaS-!oag9`1G+iN@DHBR_Gk?iS zf1Z`mEfjR0IQg+eA_xmDV6zImJq3}R&W?5*&pSIiQHPe67M$Fb^Vd>DucxPHYhx1@ z5z)X7eoBRV&ob0|>?ycm6Zzm=O zuUu)9NLs6^isIwCTAHt1xgxHqNn!YL!@`nNQv;byC>X|A(RIL{ty;AzGb;;&Y5dDC zPaipQGa=@uxTv$yJ93hej>bj*;OBWVGW_q)pFes0_}cI=zV?g7Wr+#=q~v%S?GrcW zN)M{fwr#<|!D(q}d-v|enNZPl07Dday?XWP(}{_pp&>CZt&Q#_jE$*`=HB-6{*g{C zqIrEWKK}CM%e$kaBO@dI=g-&k`Q-ur*>u`78ub>{G1=86H6x>~t!;2{@Z`ypvZrW( z{09G5$nIorZrxqepn?)r&4xpwEyt3yNIK6!He`gPb<`RWP-h>MPX;=~D@m4btU zcsyQxZEas>`VVy1887Dto-S+#V`zBz^{ZFo4<5XKVyk^rrKYP zU|;F)2MGr*Uc|4Xs`8~32H1hTygUkp5)cp&$>9_h6*V+AUCQDAM5D}jyL7scc&RCf z{>69SUA}Z_P$;++84d+su(kZo*?Nj%``pF$SWHxBM@MsWGo~^cgMujZ8=z*~5)L^s zGP0tgqPSQ9W78yQ80IBUVvoJZN2%n)NeQDLcRwAwcX#mWyA6%anf&V^fj8|erDW@A z=dBMMx9nyGCMPHR(CG#S2FjUhXdr=sfe_-wix+EaYs)JtS|yU(@!V;5$0;xJKRjK& zVKXn43Jgzel!x?PxiT(8*Ra zcAKUtHd9foPnir4Lj!fFNWO-$0e_*Tr3GK$;o-q%vvG8c3Jnzzt-o?1PC>6E%W335 z+&JZC2iM)U36v9Zz7(Vm`Dds33SZ7n3m2J1A{aF|Ejv--ghcmbH0n8e1$c6D`$ z#p0BdR0@&!&Z0$XZ+!pT@L1~&G&D41e;|UUR~Q + +Eclipse Public License - Version 1.0 + + + + + +

Eclipse Public License - v 1.0

+

THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.

+

1. DEFINITIONS

+

"Contribution" means:

+

a) in the case of the initial Contributor, the initial code and +documentation distributed under this Agreement, and

+

b) in the case of each subsequent Contributor:

+

i) changes to the Program, and

+

ii) additions to the Program;

+

where such changes and/or additions to the Program originate from +and are distributed by that particular Contributor. A Contribution 'originates' +from a Contributor if it was added to the Program by such Contributor itself or +anyone acting on such Contributor's behalf. Contributions do not include +additions to the Program which: (i) are separate modules of software distributed +in conjunction with the Program under their own license agreement, and (ii) are +not derivative works of the Program.

+

"Contributor" means any person or entity that distributes the Program.

+

"Licensed Patents" mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program.

+

"Program" means the Contributions distributed in accordance with this +Agreement.

+

"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors.

+

2. GRANT OF RIGHTS

+

a) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free copyright license to +reproduce, prepare derivative works of, publicly display, publicly perform, +distribute and sublicense the Contribution of such Contributor, if any, and such +derivative works, in source code and object code form.

+

b) Subject to the terms of this Agreement, each Contributor hereby +grants Recipient a non-exclusive, worldwide, royalty-free patent license under +Licensed Patents to make, use, sell, offer to sell, import and otherwise +transfer the Contribution of such Contributor, if any, in source code and object +code form. This patent license shall apply to the combination of the +Contribution and the Program if, at the time the Contribution is added by the +Contributor, such addition of the Contribution causes such combination to be +covered by the Licensed Patents. The patent license shall not apply to any other +combinations which include the Contribution. No hardware per se is licensed +hereunder.

+

c) Recipient understands that although each Contributor grants the +licenses to its Contributions set forth herein, no assurances are provided by +any Contributor that the Program does not infringe the patent or other +intellectual property rights of any other entity. Each Contributor disclaims any +liability to Recipient for claims brought by any other entity based on +infringement of intellectual property rights or otherwise. As a condition to +exercising the rights and licenses granted hereunder, each Recipient hereby +assumes sole responsibility to secure any other intellectual property rights +needed, if any. For example, if a third party patent license is required to +allow Recipient to distribute the Program, it is Recipient's responsibility to +acquire that license before distributing the Program.

+

d) Each Contributor represents that to its knowledge it has +sufficient copyright rights in its Contribution, if any, to grant the copyright +license set forth in this Agreement.

+

3. REQUIREMENTS

+

A Contributor may choose to distribute the Program in object code form under +its own license agreement, provided that:

+

a) it complies with the terms and conditions of this Agreement; +and

+

b) its license agreement:

+

i) effectively disclaims on behalf of all Contributors all +warranties and conditions, express and implied, including warranties or +conditions of title and non-infringement, and implied warranties or conditions +of merchantability and fitness for a particular purpose;

+

ii) effectively excludes on behalf of all Contributors all +liability for damages, including direct, indirect, special, incidental and +consequential damages, such as lost profits;

+

iii) states that any provisions which differ from this Agreement +are offered by that Contributor alone and not by any other party; and

+

iv) states that source code for the Program is available from such +Contributor, and informs licensees how to obtain it in a reasonable manner on or +through a medium customarily used for software exchange.

+

When the Program is made available in source code form:

+

a) it must be made available under this Agreement; and

+

b) a copy of this Agreement must be included with each copy of the +Program.

+

Contributors may not remove or alter any copyright notices contained within +the Program.

+

Each Contributor must identify itself as the originator of its Contribution, +if any, in a manner that reasonably allows subsequent Recipients to identify the +originator of the Contribution.

+

4. COMMERCIAL DISTRIBUTION

+

Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, if +a Contributor includes the Program in a commercial product offering, such +Contributor ("Commercial Contributor") hereby agrees to defend and indemnify +every other Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and other legal +actions brought by a third party against the Indemnified Contributor to the +extent caused by the acts or omissions of such Commercial Contributor in +connection with its distribution of the Program in a commercial product +offering. The obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In order +to qualify, an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial Contributor to +control, and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may participate in +any such claim at its own expense.

+

For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If that +Commercial Contributor then makes performance claims, or offers warranties +related to Product X, those performance claims and warranties are such +Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a court +requires any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages.

+

5. NO WARRANTY

+

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON +AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS +OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each +Recipient is solely responsible for determining the appropriateness of using and +distributing the Program and assumes all risks associated with its exercise of +rights under this Agreement , including but not limited to the risks and costs +of program errors, compliance with applicable laws, damage to or loss of data, +programs or equipment, and unavailability or interruption of operations.

+

6. DISCLAIMER OF LIABILITY

+

EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

+

7. GENERAL

+

If any provision of this Agreement is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of the +remainder of the terms of this Agreement, and without further action by the +parties hereto, such provision shall be reformed to the minimum extent necessary +to make such provision valid and enforceable.

+

If Recipient institutes patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Program itself +(excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted under +Section 2(b) shall terminate as of the date such litigation is filed.

+

All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue and +survive.

+

Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to time. +No one other than the Agreement Steward has the right to modify this Agreement. +The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation +may assign the responsibility to serve as the Agreement Steward to a suitable +separate entity. Each new version of the Agreement will be given a +distinguishing version number. The Program (including Contributions) may always +be distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to distribute the Program (including its Contributions) +under the new version. Except as expressly stated in Sections 2(a) and 2(b) +above, Recipient receives no rights or licenses to the intellectual property of +any Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted under +this Agreement are reserved.

+

This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial in +any resulting litigation.

diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.bat b/代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.bat new file mode 100644 index 0000000..49fef2c --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.bat @@ -0,0 +1,9 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +java -Xmx1024M -cp libs/robocode.jar;libs/roborumble.jar;libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/meleerumble.txt \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.command b/代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.command new file mode 100644 index 0000000..f5ac342 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.command @@ -0,0 +1,13 @@ +#!/bin/sh +################################################################################ +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +################################################################################ + +pwd=`pwd` +cd "${0%/*}" +java -Xdock:icon=roborumble.ico -Xdock:name=MeleeRumble -Xmx1024M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/meleerumble.txt +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.sh b/代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.sh new file mode 100644 index 0000000..e6714a1 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/meleerumble.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +pwd=`pwd` +cd "${0%/*}" +java -Xmx1024M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/meleerumble.txt +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/robocode.bat b/代码/workspace_robo4/robocode.content/src/main/resources/robocode.bat new file mode 100644 index 0000000..cdb3c2a --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/robocode.bat @@ -0,0 +1,9 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +java -Xmx512M -cp libs/robocode.jar robocode.Robocode %* \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/robocode.command b/代码/workspace_robo4/robocode.content/src/main/resources/robocode.command new file mode 100644 index 0000000..3065355 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/robocode.command @@ -0,0 +1,13 @@ +#!/bin/sh +################################################################################ +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +################################################################################ + +pwd=`pwd` +cd "${0%/*}" +java -Xdock:icon=robocode.ico -Xdock:name=Robocode -Xmx512M -cp libs/robocode.jar robocode.Robocode $* +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/robocode.ico b/代码/workspace_robo4/robocode.content/src/main/resources/robocode.ico new file mode 100644 index 0000000000000000000000000000000000000000..8c469e67c675f43cf369da4a75a653a87391f7b8 GIT binary patch literal 370070 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/robocode.sh b/代码/workspace_robo4/robocode.content/src/main/resources/robocode.sh new file mode 100644 index 0000000..81ca7de --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/robocode.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +pwd=`pwd` +cd "${0%/*}" +java -Xmx512M -cp libs/robocode.jar robocode.Robocode $* +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.bat b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.bat new file mode 100644 index 0000000..e056ed9 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.bat @@ -0,0 +1,9 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +java -Xmx512M -cp libs/robocode.jar;libs/roborumble.jar;libs/codesize-1.1.jar; roborumble.RoboRumbleAtHome ./roborumble/roborumble.txt \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.command b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.command new file mode 100644 index 0000000..27f9f4b --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.command @@ -0,0 +1,13 @@ +#!/bin/sh +################################################################################ +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +################################################################################ + +pwd=`pwd` +cd "${0%/*}" +java -Xdock:icon=roborumble.ico -Xdock:name=RoboRumble -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/roborumble.txt +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.ico b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.ico new file mode 100644 index 0000000000000000000000000000000000000000..927ba6e4f14330fee367bc922e4ac6f3941bc752 GIT binary patch literal 32038 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.sh b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.sh new file mode 100644 index 0000000..b0a4050 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +pwd=`pwd` +cd "${0%/*}" +java -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/roborumble.txt +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/meleerumble.txt b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/meleerumble.txt new file mode 100644 index 0000000..969673d --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/meleerumble.txt @@ -0,0 +1,244 @@ +#=============================================================================== +# meleerumble.txt - Configuration file for MeleeRumble (melee battles) +#=============================================================================== + +#------------------------------------------------------------------------------- +# User property. It's highly recommendable that you change this to use your name +#------------------------------------------------------------------------------- + +# USER The user name used when uploading the results to the RoboRumble +# server. Hence, you should replace 'Put_Your_Name_Here' with your +# name, which could be the initials you use for your robot(s). + +USER=Put_Your_Name_Here + +#------------------------------------------------------------------------------- +# Exclude filter used for excluding participants. Use with care! +#------------------------------------------------------------------------------- + +# EXCLUDE A comma separated list of all the participants you want to exclude +# from the competition. Excluded participants will not be downloaded +# or take part in battles. This way you can exclude participants that +# cannot be downloaded due to web servers that are down or hanging, +# the repository is down, robots/teams that crashes for some reason or +# cause other trouble. +# +# You can use the filename wildcards * and ? in the filter. Example: +# +# EXCLUDE=xyz.*v1.?, *Nano* + +EXCLUDE= + +#------------------------------------------------------------------------------- +# Properties for controlling the rumble. Use YES or NOT +#------------------------------------------------------------------------------- + +# DOWNLOAD Download data like participants, missing robots, rating files etc. +# from Internet if these have not been downloaded for 2 hours. +# +# EXECUTE Execute battles. Battles files are first created and old battles +# files are deleted before the battles are executed. +# +# UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL +# property. +# +# ITERATE If set to NOT, the rumble will only execute battles once. +# If set to YES, the rumble will restart with new battles every time +# the battles have been executed, and it will run infinitely until +# terminated. + +DOWNLOAD=YES +EXECUTE=YES +UPLOAD=YES +ITERATE=YES + +# MELEE Must be set if this rumble is meant for melee battles. +# +# TEAMS Must be set if this rumble is meant for team battles. +# This flag is necessary, as jar files for robot teams are different +# from jar files for ordinary robots. + +# MELEE=YES as this property file is meant for melee battles. +# TEAM=NOT, as this property file is not meant for team battles. + +# Do not modify these properties! + +MELEE=YES +TEAMS=NOT + +#------------------------------------------------------------------------------ +# Properties for the battle engine +#------------------------------------------------------------------------------ + +# FIELDL Battlefield width measured in pixels. +# FIELDH Battlefield height measured in pixels. +# +# NUMBATTLES Number of battles performed per rumble. +# ROUNDS Number of rounds per battle. +# +# MELEEBOTS Number of robots that participate in a melee battle. + +# These are standard values for the MeleeRumble. Do not modify these properties! + +FIELDL=1000 +FIELDH=1000 +NUMBATTLES=3 +ROUNDS=35 +MELEEBOTS=10 + +# INPUT Input battles file that is generated by the rumble automatically. +# The rumble uses this file for selecting which robots that must +# battle against each other. +# +# OUTPUT Battle results file, which is the output of running the rumble. + +INPUT=./roborumble/temp/battlesmelee.txt +OUTPUT=./roborumble/files/resultsmelee.txt + +#------------------------------------------------------------------------------- +# Properties for retrieving robots from Internet +#------------------------------------------------------------------------------- + +# BOTSREP The robot repository where downloaded robots are put. +# +# TEMP Directory containing all temporary files for RoboRumble. + +BOTSREP=./robots/ +TEMP=./roborumble/temp/ + +#------------------------------------------------------------------------------- +# Properties for updating participants from Internet +#------------------------------------------------------------------------------- + +# PARTICIPANTSURL +# URL to the web page containing all participants of the competition, +# which will be used for updating the participants file specified with +# the PARTICIPANTSFILE property. +# +# PARTICIPANTSFILE +# File containing all the participants for the competition. +# +# STARTAG Tag marking the start and end of the participants on the web page +# pointed to with the PARTICIPANTSURL property. +# +# UPDATEBOTSURL +# URL used for removing old participants, which is used for updating +# the participants file specified with the PARTICIPANTSFILE property. + +PARTICIPANTSURL=http://robowiki.net/wiki/RoboRumble/Participants/Melee&action=raw +PARTICIPANTSFILE=./roborumble/files/participmelee.txt + +STARTAG=pre + +UPDATEBOTSURL=http://literumble.appspot.com/RemoveOldParticipant + +#------------------------------------------------------------------------------- +# Properties to control the way battles are run +#------------------------------------------------------------------------------- + +# RUNONLY If left black or set to GENERAL, a new battle file is created where +# robots from the participants file are paired at random. The number +# of robot pairs will match number of battles defined the NUMBATTLES +# property. +# +# If set to MINI, a new battle file is created similar to the one +# for GENERAL, but it will only contains robots that are MiniBots, +# which has a code size < 1500 bytes (calculated by the codesize tool). +# +# If set to MICRO, a new battle file is created similar to the one +# for GENERAL, but it will only contains robots that are MicroBots, +# which has a code size < 750 bytes (calculated by the codesize tool). +# +# If set to NANO, a new battle file is created similar to the one for +# GENERAL, but it will only contains robots that are NanoBots, which +# has a code size < 250 bytes (calculated by the codesize tool). +# +# If set to SERVER (recommended), a new battle file is created which +# will first of all contain priority battles for robots that that has +# priority over other robots until they have fought a specific number +# of battles specified by the BATTLESPERBOT property. The number of +# battles fought by the individual robots are extracted from the +# rating files, which are downloaded from the server if the DOWNLOAD +# property is set to YES. When no more priority battles are left, +# robots from the participants file are paired at random similar to +# GENERAL. +# +# BATTLESPERBOT +# The number of battles a robot has to fight before it will no longer +# have priority over other robots in battles. Prioritizing a robot +# makes its rating more reliable faster as its number of fought +# battles increases faster than when it is not prioritized. +# +# PRIORITYBATTLESFILE +# The priority battles file that is generated automatically by the +# rumble when the RUNONLY property is set to SERVER. + +RUNONLY=SERVER + +BATTLESPERBOT=2000 + +PRIORITYBATTLESFILE=./roborumble/temp/prioritymelee.txt + +#------------------------------------------------------------------------------- +# Properties for uploading the results to the server +#------------------------------------------------------------------------------- + +# RESULTSURL +# URL used for uploading the results to the server. +# +# BATTLESNUMFILE +# File containing the number of battles fought by the robots, which is +# returned by the server when results are uploaded to the server. + +RESULTSURL=http://literumble.appspot.com/UploadedResults + +BATTLESNUMFILE=./roborumble/temp/meleebattlesnumber.txt + +#------------------------------------------------------------------------------- +# Properties for related competitions +#------------------------------------------------------------------------------- + +# Related competitions are competitions where participants are a subset of the +# participants in the general competition. +# +# The MiniBots (code size < 1500) are participants of the MiniRumble. +# The MicroBots (code size < 750) are participants of the MicroRumble. +# The NanoBots (code size < 250) are participants of the NanoRumble. + +# Do not modify these properties! + +MINIBOTS=minimeleerumble +MICROBOTS=micromeleerumble +NANOBOTS=nanomeleerumble + +# CODESIZEFILE: +# The code size file that is generated automatically by the rumble in +# order determine the code size of each individual robot. + +CODESIZEFILE=./roborumble/files/codesizemelee.txt + +#------------------------------------------------------------------------------- +# Properties for URLs and file names for the rating files to download +#------------------------------------------------------------------------------- + +# RATINGS.URL: +# URL to where ratings files are located on Internet. +# +# RATINGS.GENERAL: +# File name for the rating file of the general MeleeRumble. +# +# RATINGS.MINIBOTS: +# File name for the rating file of the Melee MiniRumble. +# +# RATINGS.MICROBOTS: +# File name for the rating file of the Melee MicroRumble. +# +# RATINGS.NANOBOTS: +# File name for the rating file of the Melee NanoRumble. + +RATINGS.URL=http://literumble.appspot.com/RatingsFile + +RATINGS.GENERAL=./roborumble/temp/ratings_m_roborumble.txt +RATINGS.MINIBOTS=./roborumble/temp/ratings_m_minirumble.txt +RATINGS.MICROBOTS=./roborumble/temp/ratings_m_microrumble.txt +RATINGS.NANOBOTS=./roborumble/temp/ratings_m_nanorumble.txt diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/roborumble.properties b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/roborumble.properties new file mode 100644 index 0000000..1df0dea --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/roborumble.properties @@ -0,0 +1,6 @@ +# Connection timeout in milliseconds +connection.open.timeout=10000 +# Connection read timeout in milliseconds +connection.read.timeout=10000 +# Download session timeout +download.session.timeout=10000 diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/roborumble.txt b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/roborumble.txt new file mode 100644 index 0000000..ae45516 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/roborumble.txt @@ -0,0 +1,241 @@ +#=============================================================================== +# roborumble.txt - Configuration file for RoboRumble (1v1 battles) +#=============================================================================== + +#------------------------------------------------------------------------------- +# Username. It's highly recommendable that you change this to use your name +#------------------------------------------------------------------------------- + +# USER The username used when uploading the results to the RoboRumble +# server. Hence, you should replace 'Put_Your_Name_Here' with your +# name, which could be the initials you use for your robot(s). + +USER=Put_Your_Name_Here + +#------------------------------------------------------------------------------- +# Exclude filter used for excluding participants. Use with care! +#------------------------------------------------------------------------------- + +# EXCLUDE A comma separated list of all the participants you want to exclude +# from the competition. Excluded participants will not be downloaded +# or take part in battles. This way you can exclude participants that +# cannot be downloaded due to web servers that are down or hanging, +# the repository is down, robots/teams that crashes for some reason or +# cause other trouble. +# +# You can use the filename wildcards * and ? in the filter. Example: +# +# EXCLUDE=xyz.*v1.?, *Nano* + +EXCLUDE= + +#------------------------------------------------------------------------------- +# Properties for controlling the rumble. Use YES or NOT +#------------------------------------------------------------------------------- + +# DOWNLOAD Download data like participants, missing robots, rating files etc. +# from Internet if these have not been downloaded for 2 hours. +# +# EXECUTE Execute battles. Battles files are first created and old battles +# files are deleted before the battles are executed. +# +# UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL +# property. +# +# ITERATE If set to NOT, the rumble will only execute battles once. +# If set to YES, the rumble will restart with new battles every time +# the battles have been executed, and it will run infinitely until +# terminated. + +DOWNLOAD=YES +EXECUTE=YES +UPLOAD=YES +ITERATE=YES + +# MELEE Must be set if this rumble is meant for melee battles. +# +# TEAMS Must be set if this rumble is meant for team battles. +# This flag is necessary, as jar files for robot teams are different +# from jar files for ordinary robots. + +# MELEE=NOT as this property file is not meant for melee battles. +# TEAM=NOT, as this property file is not meant for team battles. + +# Do not modify these properties! + +MELEE=NOT +TEAMS=NOT + +#------------------------------------------------------------------------------ +# Properties for the battle engine +#------------------------------------------------------------------------------ + +# FIELDL Battlefield width measured in pixels. +# FIELDH Battlefield height measured in pixels. +# +# NUMBATTLES Number of battles performed per rumble. +# ROUNDS Number of rounds per battle. + +# These are standard values for the RoboRumble. Do not modify these properties! + +FIELDL=800 +FIELDH=600 +NUMBATTLES=50 +ROUNDS=35 + +# INPUT Input battles file that is generated by the rumble automatically. +# The rumble uses this file for selecting which robots that must +# battle against each other. +# +# OUTPUT Battle results file, which is the output of running the rumble. + +INPUT=./roborumble/temp/battles1v1.txt +OUTPUT=./roborumble/files/results1v1.txt + +#------------------------------------------------------------------------------- +# Properties for retrieving robots from Internet +#------------------------------------------------------------------------------- + +# BOTSREP The robot repository where downloaded robots are put. +# +# TEMP Directory containing all temporary files for RoboRumble. + +BOTSREP=./robots/ +TEMP=./roborumble/temp/ + +#------------------------------------------------------------------------------- +# Properties for updating participants from Internet +#------------------------------------------------------------------------------- + +# PARTICIPANTSURL +# URL to the web page containing all participants of the competition, +# which will be used for updating the participants file specified with +# the PARTICIPANTSFILE property. +# +# PARTICIPANTSFILE +# File containing all the participants for the competition. +# +# STARTAG Tag marking the start and end of the participants on the web page +# pointed to with the PARTICIPANTSURL property. +# +# UPDATEBOTSURL +# URL used for removing old participants, which is used for updating +# the participants file specified with the PARTICIPANTSFILE property. + +PARTICIPANTSURL=http://robowiki.net/wiki/RoboRumble/Participants?action=raw +PARTICIPANTSFILE=./roborumble/files/particip1v1.txt + +STARTAG=pre + +UPDATEBOTSURL=http://literumble.appspot.com/RemoveOldParticipant + +#------------------------------------------------------------------------------- +# Properties to control the way battles are run +#------------------------------------------------------------------------------- + +# RUNONLY If left black or set to GENERAL, a new battle file is created where +# robots from the participants file are paired at random. The number +# of robot pairs will match number of battles defined the NUMBATTLES +# property. +# +# If set to MINI, a new battle file is created similar to the one +# for GENERAL, but it will only contains robots that are MiniBots, +# which has a code size < 1500 bytes (calculated by the codesize tool). +# +# If set to MICRO, a new battle file is created similar to the one +# for GENERAL, but it will only contains robots that are MicroBots, +# which has a code size < 750 bytes (calculated by the codesize tool). +# +# If set to NANO, a new battle file is created similar to the one for +# GENERAL, but it will only contains robots that are NanoBots, which +# has a code size < 250 bytes (calculated by the codesize tool). +# +# If set to SERVER (recommended), a new battle file is created which +# will first of all contain priority battles for robots that that has +# priority over other robots until they have fought a specific number +# of battles specified by the BATTLESPERBOT property. The number of +# battles fought by the individual robots are extracted from the +# rating files, which are downloaded from the server if the DOWNLOAD +# property is set to YES. When no more priority battles are left, +# robots from the participants file are paired at random similar to +# GENERAL. +# +# BATTLESPERBOT +# The number of battles a robot has to fight before it will no longer +# have priority over other robots in battles. Prioritizing a robot +# makes its rating more reliable faster as its number of fought +# battles increases faster than when it is not prioritized. +# +# PRIORITYBATTLESFILE +# The priority battles file that is generated automatically by the +# rumble when the RUNONLY property is set to SERVER. + +RUNONLY=SERVER + +BATTLESPERBOT=2000 + +PRIORITYBATTLESFILE=./roborumble/temp/priority1v1.txt + +#------------------------------------------------------------------------------- +# Properties for uploading the results to the server +#------------------------------------------------------------------------------- + +# RESULTSURL +# URL used for uploading the results to the server. +# +# BATTLESNUMFILE +# File containing the number of battles fought by the robots, which is +# returned by the server when results are uploaded to the server. + +RESULTSURL=http://literumble.appspot.com/UploadedResults + +BATTLESNUMFILE=./roborumble/temp/battlesnumber.txt + +#------------------------------------------------------------------------------- +# Properties for related competitions +#------------------------------------------------------------------------------- + +# Related competitions are competitions where participants are a subset of the +# participants in the general competition. +# +# The MiniBots (code size < 1500) are participants of the MiniRumble. +# The MicroBots (code size < 750) are participants of the MicroRumble. +# The NanoBots (code size < 250) are participants of the NanoRumble. + +# Do not modify these properties! + +MINIBOTS=minirumble +MICROBOTS=microrumble +NANOBOTS=nanorumble + +# CODESIZEFILE: +# The code size file that is generated automatically by the rumble in +# order determine the code size of each individual robot. + +CODESIZEFILE=./roborumble/files/codesize1v1.txt + +#------------------------------------------------------------------------------- +# Properties for URLs and file names for the rating files to download +#------------------------------------------------------------------------------- + +# RATINGS.URL: +# URL to where ratings files are located on Internet. +# +# RATINGS.GENERAL: +# File name for the rating file of the general RoboRumble. +# +# RATINGS.MINIBOTS: +# File name for the rating file of the MiniRumble. +# +# RATINGS.MICROBOTS: +# File name for the rating file of the MicroRumble. +# +# RATINGS.NANOBOTS: +# File name for the rating file of the NanoRumble. + +RATINGS.URL=http://literumble.appspot.com/RatingsFile + +RATINGS.GENERAL=./roborumble/temp/ratings_roborumble.txt +RATINGS.MINIBOTS=./roborumble/temp/ratings_minirumble.txt +RATINGS.MICROBOTS=./roborumble/temp/ratings_microrumble.txt +RATINGS.NANOBOTS=./roborumble/temp/ratings_nanorumble.txt diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/teamrumble.txt b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/teamrumble.txt new file mode 100644 index 0000000..cf6262f --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/teamrumble.txt @@ -0,0 +1,203 @@ +#=============================================================================== +# teamrumble.txt - Configuration file for TeamRumble (team battles) +#=============================================================================== + +#------------------------------------------------------------------------------- +# User property. It's highly recommendable that you change this to use your name +#------------------------------------------------------------------------------- + +# USER The user name used when uploading the results to the RoboRumble +# server. Hence, you should replace 'Put_Your_Name_Here' with your +# name, which could be the initials you use for your robot(s). + +USER=Put_Your_Name_Here + +#------------------------------------------------------------------------------- +# Exclude filter used for excluding participants. Use with care! +#------------------------------------------------------------------------------- + +# EXCLUDE A comma separated list of all the participants you want to exclude +# from the competition. Excluded participants will not be downloaded +# or take part in battles. This way you can exclude participants that +# cannot be downloaded due to web servers that are down or hanging, +# the repository is down, robots/teams that crashes for some reason or +# cause other trouble. +# +# You can use the filename wildcards * and ? in the filter. Example: +# +# EXCLUDE=xyz.*v1.?, *Nano* + +EXCLUDE= + +#------------------------------------------------------------------------------- +# Properties for controlling the rumble. Use YES or NOT +#------------------------------------------------------------------------------- + +# DOWNLOAD Download data like participants, missing robots, rating files etc. +# from Internet if these have not been downloaded for 2 hours. +# +# EXECUTE Execute battles. Battles files are first created and old battles +# files are deleted before the battles are executed. +# +# UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL +# property. +# +# ITERATE If set to NOT, the rumble will only execute battles once. +# If set to YES, the rumble will restart with new battles every time +# the battles have been executed, and it will run infinitely until +# terminated. + +DOWNLOAD=YES +EXECUTE=YES +UPLOAD=YES +ITERATE=YES + +# MELEE Must be set if this rumble is meant for melee battles. +# +# TEAMS Must be set if this rumble is meant for team battles. +# This flag is necessary, as jar files for robot teams are different +# from jar files for ordinary robots. + +# MELEE=NOT as this property file is not meant for melee battles. +# TEAM=YES, as this property file is meant for team battles. + +# Do not modify these properties! + +MELEE=NOT +TEAMS=YES + +#------------------------------------------------------------------------------ +# Properties for the battle engine +#------------------------------------------------------------------------------ + +# FIELDL Battlefield width measured in pixels. +# FIELDH Battlefield height measured in pixels. +# +# NUMBATTLES Number of battles performed per rumble. +# ROUNDS Number of rounds per battle. + +# These are standard values for the TeamRumble. Do not modify these properties! + +FIELDL=1200 +FIELDH=1200 +NUMBATTLES=10 +ROUNDS=10 + +# INPUT Input battles file that is generated by the rumble automatically. +# The rumble uses this file for selecting which robots that must +# battle against each other. +# +# OUTPUT Battle results file, which is the output of running the rumble. + +INPUT=./roborumble/temp/battlesTeams.txt +OUTPUT=./roborumble/files/resultsTeams.txt + +#------------------------------------------------------------------------------- +# Properties for retrieving robots from Internet +#------------------------------------------------------------------------------- + +# BOTSREP The robot repository where downloaded robots are put. +# +# TEMP Directory containing all temporary files for RoboRumble. + +BOTSREP=./robots/ +TEMP=./roborumble/temp/ + +#------------------------------------------------------------------------------- +# Properties for updating participants from Internet +#------------------------------------------------------------------------------- + +# PARTICIPANTSURL +# URL to the web page containing all participants of the competition, +# which will be used for updating the participants file specified with +# the PARTICIPANTSFILE property. +# +# PARTICIPANTSFILE +# File containing all the participants for the competition. +# +# STARTAG Tag marking the start and end of the participants on the web page +# pointed to with the PARTICIPANTSURL property. +# +# UPDATEBOTSURL +# URL used for removing old participants, which is used for updating +# the participants file specified with the PARTICIPANTSFILE property. + +PARTICIPANTSURL=http://robowiki.net/wiki/RoboRumble/Participants/Teams&action=raw +PARTICIPANTSFILE=./roborumble/files/participTeams.txt + +STARTAG=pre + +UPDATEBOTSURL=http://literumble.appspot.com/RemoveOldParticipant + +#------------------------------------------------------------------------------- +# Properties to control the way battles are run +#------------------------------------------------------------------------------- + +# RUNONLY If left black or set to GENERAL, a new battle file is created where +# robots from the participants file are paired at random. The number +# of robot pairs will match number of battles defined the NUMBATTLES +# property. +# +# If set to SERVER (recommended), a new battle file is created which +# will first of all contain priority battles for robots that that has +# priority over other robots until they have fought a specific number +# of battles specified by the BATTLESPERBOT property. The number of +# battles fought by the individual robots are extracted from the +# rating files, which are downloaded from the server if the DOWNLOAD +# property is set to YES. When no more priority battles are left, +# robots from the participants file are paired at random similar to +# GENERAL. +# +# BATTLESPERBOT +# The number of battles a robot has to fight before it will no longer +# have priority over other robots in battles. Prioritizing a robot +# makes its rating more reliable faster as its number of fought +# battles increases faster than when it is not prioritized. +# +# PRIORITYBATTLESFILE +# The priority battles file that is generated automatically by the +# rumble when the RUNONLY property is set to SERVER. + +RUNONLY=SERVER + +BATTLESPERBOT=200 + +PRIORITYBATTLESFILE=./roborumble/temp/priorityTeams.txt + +#------------------------------------------------------------------------------- +# Properties for uploading the results to the server +#------------------------------------------------------------------------------- + +# RESULTSURL +# URL used for uploading the results to the server. +# +# BATTLESNUMFILE +# File containing the number of battles fought by the robots, which is +# returned by the server when results are uploaded to the server. + +RESULTSURL=http://literumble.appspot.com/UploadedResults + +BATTLESNUMFILE=./roborumble/temp/teambattlesnumber.txt + +#------------------------------------------------------------------------------- +# Properties for URLs and file names for the rating files to download +#------------------------------------------------------------------------------- + +# RATINGS.URL: +# URL to where ratings files are located on Internet. +# +# RATINGS.GENERAL: +# File name for the rating file of the general RoboRumble. +# +# RATINGS.MINIBOTS: +# File name for the rating file of the MiniRumble. +# +# RATINGS.MICROBOTS: +# File name for the rating file of the MicroRumble. +# +# RATINGS.NANOBOTS: +# File name for the rating file of the NanoRumble. + +RATINGS.URL=http://literumble.appspot.com/RatingsFile + +RATINGS.GENERAL=./roborumble/temp/ratings_teamrumble.txt diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/twinduel.txt b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/twinduel.txt new file mode 100644 index 0000000..8fc223b --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/roborumble/twinduel.txt @@ -0,0 +1,203 @@ +#=============================================================================== +# twinduel.txt - Configuration file for TwinDuel (rumble edition) +#=============================================================================== + +#------------------------------------------------------------------------------- +# User property. It's highly recommendable that you change this to use your name +#------------------------------------------------------------------------------- + +# USER The user name used when uploading the results to the RoboRumble +# server. Hence, you should replace 'Put_Your_Name_Here' with your +# name, which could be the initials you use for your robot(s). + +USER=Put_Your_Name_Here + +#------------------------------------------------------------------------------- +# Exclude filter used for excluding participants. Use with care! +#------------------------------------------------------------------------------- + +# EXCLUDE A comma separated list of all the participants you want to exclude +# from the competition. Excluded participants will not be downloaded +# or take part in battles. This way you can exclude participants that +# cannot be downloaded due to web servers that are down or hanging, +# the repository is down, robots/teams that crashes for some reason or +# cause other trouble. +# +# You can use the filename wildcards * and ? in the filter. Example: +# +# EXCLUDE=xyz.*v1.?, *Nano* + +EXCLUDE= + +#------------------------------------------------------------------------------- +# Properties for controlling the rumble. Use YES or NOT +#------------------------------------------------------------------------------- + +# DOWNLOAD Download data like participants, missing robots, rating files etc. +# from Internet if these have not been downloaded for 2 hours. +# +# EXECUTE Execute battles. Battles files are first created and old battles +# files are deleted before the battles are executed. +# +# UPLOAD Upload results to the RoboRumble server specified by the RESULTSURL +# property. +# +# ITERATE If set to NOT, the rumble will only execute battles once. +# If set to YES, the rumble will restart with new battles every time +# the battles have been executed, and it will run infinitely until +# terminated. + +DOWNLOAD=YES +EXECUTE=YES +UPLOAD=YES +ITERATE=YES + +# MELEE Must be set if this rumble is meant for melee battles. +# +# TEAMS Must be set if this rumble is meant for team battles. +# This flag is necessary, as jar files for robot teams are different +# from jar files for ordinary robots. + +# MELEE=NOT as this property file is not meant for melee battles. +# TEAM=YES, as this property file is meant for team battles. + +# Do not modify these properties! + +MELEE=NOT +TEAMS=YES + +#------------------------------------------------------------------------------ +# Properties for the battle engine +#------------------------------------------------------------------------------ + +# FIELDL Battlefield width measured in pixels. +# FIELDH Battlefield height measured in pixels. +# +# NUMBATTLES Number of battles performed per rumble. +# ROUNDS Number of rounds per battle. + +# These are standard values for the TeamRumble. Do not modify these properties! + +FIELDL=800 +FIELDH=800 +NUMBATTLES=10 +ROUNDS=75 + +# INPUT Input battles file that is generated by the rumble automatically. +# The rumble uses this file for selecting which robots that must +# battle against each other. +# +# OUTPUT Battle results file, which is the output of running the rumble. + +INPUT=./roborumble/temp/battlesTwinduel.txt +OUTPUT=./roborumble/files/resultsTwinduel.txt + +#------------------------------------------------------------------------------- +# Properties for retrieving robots from Internet +#------------------------------------------------------------------------------- + +# BOTSREP The robot repository where downloaded robots are put. +# +# TEMP Directory containing all temporary files for RoboRumble. + +BOTSREP=./robots/ +TEMP=./roborumble/temp/ + +#------------------------------------------------------------------------------- +# Properties for updating participants from Internet +#------------------------------------------------------------------------------- + +# PARTICIPANTSURL +# URL to the web page containing all participants of the competition, +# which will be used for updating the participants file specified with +# the PARTICIPANTSFILE property. +# +# PARTICIPANTSFILE +# File containing all the participants for the competition. +# +# STARTAG Tag marking the start and end of the participants on the web page +# pointed to with the PARTICIPANTSURL property. +# +# UPDATEBOTSURL +# URL used for removing old participants, which is used for updating +# the participants file specified with the PARTICIPANTSFILE property. + +PARTICIPANTSURL=http://robowiki.net/wiki/RoboRumble/Participants/TwinDuel +PARTICIPANTSFILE=./roborumble/files/participTwinduel.txt + +STARTAG=pre + +UPDATEBOTSURL=http://literumble.appspot.com/RemoveOldParticipant + +#------------------------------------------------------------------------------- +# Properties to control the way battles are run +#------------------------------------------------------------------------------- + +# RUNONLY If left black or set to GENERAL, a new battle file is created where +# robots from the participants file are paired at random. The number +# of robot pairs will match number of battles defined the NUMBATTLES +# property. +# +# If set to SERVER (recommended), a new battle file is created which +# will first of all contain priority battles for robots that that has +# priority over other robots until they have fought a specific number +# of battles specified by the BATTLESPERBOT property. The number of +# battles fought by the individual robots are extracted from the +# rating files, which are downloaded from the server if the DOWNLOAD +# property is set to YES. When no more priority battles are left, +# robots from the participants file are paired at random similar to +# GENERAL. +# +# BATTLESPERBOT +# The number of battles a robot has to fight before it will no longer +# have priority over other robots in battles. Prioritizing a robot +# makes its rating more reliable faster as its number of fought +# battles increases faster than when it is not prioritized. +# +# PRIORITYBATTLESFILE +# The priority battles file that is generated automatically by the +# rumble when the RUNONLY property is set to SERVER. + +RUNONLY=SERVER + +BATTLESPERBOT=200 + +PRIORITYBATTLESFILE=./roborumble/temp/priorityTwinduel.txt + +#------------------------------------------------------------------------------- +# Properties for uploading the results to the server +#------------------------------------------------------------------------------- + +# RESULTSURL +# URL used for uploading the results to the server. +# +# BATTLESNUMFILE +# File containing the number of battles fought by the robots, which is +# returned by the server when results are uploaded to the server. + +RESULTSURL=http://literumble.appspot.com/UploadedResults + +BATTLESNUMFILE=./roborumble/temp/twinduelbattlesnumber.txt + +#------------------------------------------------------------------------------- +# Properties for URLs and file names for the rating files to download +#------------------------------------------------------------------------------- + +# RATINGS.URL: +# URL to where ratings files are located on Internet. +# +# RATINGS.GENERAL: +# File name for the rating file of the general RoboRumble. +# +# RATINGS.MINIBOTS: +# File name for the rating file of the MiniRumble. +# +# RATINGS.MICROBOTS: +# File name for the rating file of the MicroRumble. +# +# RATINGS.NANOBOTS: +# File name for the rating file of the NanoRumble. + +RATINGS.URL=http://literumble.appspot.com/RatingsFile + +RATINGS.GENERAL=./roborumble/temp/ratings_twinduel.txt diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.bat b/代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.bat new file mode 100644 index 0000000..3d97f1f --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.bat @@ -0,0 +1,9 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +java -Xmx512M -cp libs/robocode.jar;libs/roborumble.jar;libs/codesize-1.1.jar; roborumble.RoboRumbleAtHome ./roborumble/teamrumble.txt \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.command b/代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.command new file mode 100644 index 0000000..c103230 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.command @@ -0,0 +1,13 @@ +#!/bin/sh +################################################################################ +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +################################################################################ + +pwd=`pwd` +cd "${0%/*}" +java -Xdock:icon=roborumble.ico -Xdock:name=TeamRumble -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/teamrumble.txt +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.sh b/代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.sh new file mode 100644 index 0000000..96b6e82 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/teamrumble.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +pwd=`pwd` +cd "${0%/*}" +java -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/teamrumble.txt +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/templates/newjavafile.tpt b/代码/workspace_robo4/robocode.content/src/main/resources/templates/newjavafile.tpt new file mode 100644 index 0000000..b5bbc36 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/templates/newjavafile.tpt @@ -0,0 +1,8 @@ +package $PACKAGE; + +/** + * $CLASSNAME - a class by (your name here) + */ +public class $CLASSNAME +{ +} diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/templates/newjuniorrobot.tpt b/代码/workspace_robo4/robocode.content/src/main/resources/templates/newjuniorrobot.tpt new file mode 100644 index 0000000..c7f0ec8 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/templates/newjuniorrobot.tpt @@ -0,0 +1,54 @@ +package $PACKAGE; +import robocode.*; + +// API help : http://robocode.sourceforge.net/docs/robocode/robocode/JuniorRobot.html + +/** + * $CLASSNAME - a robot by (your name here) + */ +public class $CLASSNAME extends JuniorRobot +{ + /** + * run: $CLASSNAME's default behavior + */ + public void run() { + // Initialization of the robot should be put here + + // Some color codes: blue, yellow, black, white, red, pink, brown, grey, orange... + // Sets these colors (robot parts): body, gun, radar, bullet, scan_arc + setColors(orange, blue, white, yellow, black); + + // Robot main loop + while(true) { + // Replace the next 4 lines with any behavior you would like + ahead(100); + turnGunRight(360); + back(100); + turnGunRight(360); + } + } + + /** + * onScannedRobot: What to do when you see another robot + */ + public void onScannedRobot() { + // Replace the next line with any behavior you would like + fire(1); + } + + /** + * onHitByBullet: What to do when you're hit by a bullet + */ + public void onHitByBullet() { + // Replace the next line with any behavior you would like + back(10); + } + + /** + * onHitWall: What to do when you hit a wall + */ + public void onHitWall() { + // Replace the next line with any behavior you would like + back(20); + } +} diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/templates/newrobot.tpt b/代码/workspace_robo4/robocode.content/src/main/resources/templates/newrobot.tpt new file mode 100644 index 0000000..070e471 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/templates/newrobot.tpt @@ -0,0 +1,56 @@ +package $PACKAGE; +import robocode.*; +//import java.awt.Color; + +// API help : http://robocode.sourceforge.net/docs/robocode/robocode/Robot.html + +/** + * $CLASSNAME - a robot by (your name here) + */ +public class $CLASSNAME extends Robot +{ + /** + * run: $CLASSNAME's default behavior + */ + public void run() { + // Initialization of the robot should be put here + + // After trying out your robot, try uncommenting the import at the top, + // and the next line: + + // setColors(Color.red,Color.blue,Color.green); // body,gun,radar + + // Robot main loop + while(true) { + // Replace the next 4 lines with any behavior you would like + ahead(100); + turnGunRight(360); + back(100); + turnGunRight(360); + } + } + + /** + * onScannedRobot: What to do when you see another robot + */ + public void onScannedRobot(ScannedRobotEvent e) { + // Replace the next line with any behavior you would like + fire(1); + } + + /** + * onHitByBullet: What to do when you're hit by a bullet + */ + public void onHitByBullet(HitByBulletEvent e) { + // Replace the next line with any behavior you would like + back(10); + } + + /** + * onHitWall: What to do when you hit a wall + */ + public void onHitWall(HitWallEvent e) { + // Replace the next line with any behavior you would like + back(20); + } +} diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/theme/editor/Robocode Black Theme.properties b/代码/workspace_robo4/robocode.content/src/main/resources/theme/editor/Robocode Black Theme.properties new file mode 100644 index 0000000..bd627b6 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/theme/editor/Robocode Black Theme.properties @@ -0,0 +1,23 @@ +#Robocode Editor Theme Properties +#Sun Sep 15 22:13:41 CEST 2013 +editor.theme=Robocode Black Theme +editor.font.name=Monospaced +editor.font.size=14 +editor.background.color=000000 +editor.lineNumber.background.color=22222 +editor.lineNumber.text.color=00CC00 +editor.highlighted.line.color=999999 +editor.selected.text.color=993300 +editor.selected.background.color=FFFFFF +editor.text.style.normal=Plain +editor.text.color.normal=00FFFF +editor.text.style.keyword=Bold +editor.text.color.keyword=0000FF +editor.text.style.literal=Plain +editor.text.color.literal=FFFF00 +editor.text.style.comment=Italic +editor.text.color.comment=00FF00 +editor.text.style.quoted=Plain +editor.text.color.quoted=FF0000 +editor.text.style.annotation=Plain +editor.text.color.annotation=FF00FF diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/theme/editor/Robocode White Theme.properties b/代码/workspace_robo4/robocode.content/src/main/resources/theme/editor/Robocode White Theme.properties new file mode 100644 index 0000000..0eecd3e --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/theme/editor/Robocode White Theme.properties @@ -0,0 +1,23 @@ +#Robocode Editor Theme Properties +#Wed Jul 31 14:51:10 CEST 2013 +editor.theme=Robocode White Theme +editor.font.name=Monospaced +editor.font.size=14 +editor.background.color=FFFFFF +editor.lineNumber.background.color=EEEEEE +editor.lineNumber.text.color=000000 +editor.highlighted.line.color=FFFFCC +editor.selected.text.color=FFFFFF +editor.selected.background.color=3399FF +editor.text.style.normal=Plain +editor.text.color.normal=000000 +editor.text.style.keyword=Bold +editor.text.color.keyword=0000AF +editor.text.style.literal=Bold +editor.text.color.literal=0000AF +editor.text.style.comment=Plain +editor.text.color.comment=00AF00 +editor.text.style.quoted=Plain +editor.text.color.quoted=7F0000 +editor.text.style.annotation=Plain +editor.text.color.annotation=7F7F7F diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/twinduel.bat b/代码/workspace_robo4/robocode.content/src/main/resources/twinduel.bat new file mode 100644 index 0000000..c5573f2 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/twinduel.bat @@ -0,0 +1,9 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +java -Xmx512M -cp libs/robocode.jar;libs/roborumble.jar;libs/codesize-1.1.jar; roborumble.RoboRumbleAtHome ./roborumble/twinduel.txt \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/twinduel.command b/代码/workspace_robo4/robocode.content/src/main/resources/twinduel.command new file mode 100644 index 0000000..a61c9e8 --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/twinduel.command @@ -0,0 +1,13 @@ +#!/bin/sh +################################################################################ +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +################################################################################ + +pwd=`pwd` +cd "${0%/*}" +java -Xdock:icon=roborumble.ico -Xdock:name=TwinDuel -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/twinduel.txt +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.content/src/main/resources/twinduel.sh b/代码/workspace_robo4/robocode.content/src/main/resources/twinduel.sh new file mode 100644 index 0000000..1669b1b --- /dev/null +++ b/代码/workspace_robo4/robocode.content/src/main/resources/twinduel.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + +pwd=`pwd` +cd "${0%/*}" +java -Xmx512M -cp libs/robocode.jar:libs/roborumble.jar:libs/codesize-1.1.jar roborumble.RoboRumbleAtHome ./roborumble/twinduel.txt +cd "${pwd}" diff --git a/代码/workspace_robo4/robocode.core/.classpath b/代码/workspace_robo4/robocode.core/.classpath new file mode 100644 index 0000000..a5988a2 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.core/.project b/代码/workspace_robo4/robocode.core/.project new file mode 100644 index 0000000..45e2fe1 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/.project @@ -0,0 +1,16 @@ + + + robocode.core + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.core/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..65f3846 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:08 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.core/pom.xml b/代码/workspace_robo4/robocode.core/pom.xml new file mode 100644 index 0000000..b544668 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + robocode.core + Robocode Core + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + + org.picocontainer + picocontainer + 2.14.2 + + + + junit + junit + 4.11 + test + + + + + + maven-resources-plugin + + + copy-resources + validate + + copy-resources + + + ${basedir}/target/classes + + + .. + false + + + versions.md + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.core/robocode.core.iml b/代码/workspace_robo4/robocode.core/robocode.core.iml new file mode 100644 index 0000000..56af730 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/robocode.core.iml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleProperties.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleProperties.java new file mode 100644 index 0000000..c3a76d9 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleProperties.java @@ -0,0 +1,333 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +import robocode.AdvancedRobot; +import robocode.Robot; +import robocode.control.RobotSetup; +import robocode.control.RobotSpecification; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.Properties; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class BattleProperties implements Serializable { + + private static final long serialVersionUID = 1L; + + private final static String + BATTLEFIELD_WIDTH = "robocode.battleField.width", + BATTLEFIELD_HEIGHT = "robocode.battleField.height", + BATTLE_NUMROUNDS = "robocode.battle.numRounds", + BATTLE_GUNCOOLINGRATE = "robocode.battle.gunCoolingRate", + BATTLE_RULES_INACTIVITYTIME = "robocode.battle.rules.inactivityTime", + BATTLE_HIDE_ENEMY_NAMES = "robocode.battle.hideEnemyNames", + BATTLE_SELECTEDROBOTS = "robocode.battle.selectedRobots", + BATTLE_INITIAL_POSITIONS = "robocode.battle.initialPositions", + BATTLE_SENTRY_BORDER_SIZE = "robocode.battle.sentryBorderSize"; + + private int battlefieldWidth = 800; + private int battlefieldHeight = 600; + private int numRounds = 10; + private double gunCoolingRate = 0.1; + private long inactivityTime = 450; + private boolean hideEnemyNames = false; + private int sentryBorderSize = 100; + private String selectedRobots; + private String initialPositions; + + private final Properties props = new Properties(); + + /** + * Gets the battlefieldWidth. + * + * @return Returns a int + */ + public int getBattlefieldWidth() { + return battlefieldWidth; + } + + /** + * Sets the battlefieldWidth. + * + * @param battlefieldWidth The battlefieldWidth to set + */ + public void setBattlefieldWidth(int battlefieldWidth) { + this.battlefieldWidth = battlefieldWidth; + props.setProperty(BATTLEFIELD_WIDTH, "" + battlefieldWidth); + } + + /** + * Gets the battlefieldHeight. + * + * @return Returns a int + */ + public int getBattlefieldHeight() { + return battlefieldHeight; + } + + /** + * Sets the battlefieldHeight. + * + * @param battlefieldHeight The battlefieldHeight to set + */ + public void setBattlefieldHeight(int battlefieldHeight) { + this.battlefieldHeight = battlefieldHeight; + props.setProperty(BATTLEFIELD_HEIGHT, "" + battlefieldHeight); + } + + /** + * Gets the numRounds. + * + * @return Returns a int + */ + public int getNumRounds() { + return numRounds; + } + + /** + * Sets the numRounds. + * + * @param numRounds The numRounds to set + */ + public void setNumRounds(int numRounds) { + this.numRounds = numRounds; + props.setProperty(BATTLE_NUMROUNDS, "" + numRounds); + } + + /** + * Returns the rate at which the gun will cool down, i.e. the amount of heat the gun heat will drop per turn. + *

+ * The gun cooling rate is default 0.1 per turn, but can be changed by the battle setup. + * So don't count on the cooling rate being 0.1! + * + * @return the gun cooling rate + * @see #setGunCoolingRate(double) + * @see Robot#getGunHeat() + * @see Robot#fire(double) + * @see Robot#fireBullet(double) + * @see robocode.BattleRules#getGunCoolingRate() + */ + public double getGunCoolingRate() { + return gunCoolingRate; + } + + /** + * Sets the rate at which the gun will cool down, i.e. the amount of heat the gun heat will drop per turn. + * + * @param gunCoolingRate the new gun cooling rate + * @see #getGunCoolingRate + * @see Robot#getGunHeat() + * @see Robot#fire(double) + * @see Robot#fireBullet(double) + * @see robocode.BattleRules#getGunCoolingRate() + */ + public void setGunCoolingRate(double gunCoolingRate) { + this.gunCoolingRate = gunCoolingRate; + props.setProperty(BATTLE_GUNCOOLINGRATE, "" + gunCoolingRate); + } + + /** + * Returns the allowed inactivity time, where the robot is not taking any action, before will begin to be zapped. + * The inactivity time is measured in turns, and is the allowed time that a robot is allowed to omit taking + * action before being punished by the game by zapping. + *

+ * When a robot is zapped by the game, it will loose 0.1 energy points per turn. Eventually the robot will be + * killed by zapping until the robot takes action. When the robot takes action, the inactivity time counter is + * reset. + *

+ * The allowed inactivity time is per default 450 turns, but can be changed by the battle setup. + * So don't count on the inactivity time being 450 turns! + * + * @return the allowed inactivity time. + * @see robocode.BattleRules#getInactivityTime() + * @see Robot#doNothing() + * @see AdvancedRobot#execute() + */ + public long getInactivityTime() { + return inactivityTime; + } + + /** + * Sets the allowed inactivity time, where the robot is not taking any action, before will begin to be zapped. + * + * @param inactivityTime the new allowed inactivity time. + * @see robocode.BattleRules#getInactivityTime() + * @see Robot#doNothing() + * @see AdvancedRobot#execute() + */ + public void setInactivityTime(long inactivityTime) { + this.inactivityTime = inactivityTime; + props.setProperty(BATTLE_RULES_INACTIVITYTIME, "" + inactivityTime); + } + + /** + * Sets the flag defining if enemy names are hidden for robots during a battle. + * + * @param hideEnemyNames true if the enemy names must be hidden for a robot; false otherwise. + * + * @since 1.7.3 + */ + public void setHideEnemyNames(boolean hideEnemyNames) { + this.hideEnemyNames = hideEnemyNames; + props.setProperty(BATTLE_HIDE_ENEMY_NAMES, "" + hideEnemyNames); + } + + /** + * Returns true if the enemy names are hidden for robots during a battle; false otherwise. + * + * @since 1.7.3 + */ + public boolean getHideEnemyNames() { + return hideEnemyNames; + } + + /** + * Gets the selectedRobots. + * + * @return Returns a String + */ + public String getSelectedRobots() { + return selectedRobots; + } + + /** + * Sets the selectedRobots. + * + * @param selectedRobots The selectedRobots to set + */ + public void setSelectedRobots(String selectedRobots) { + this.selectedRobots = selectedRobots; + props.setProperty(BATTLE_SELECTEDROBOTS, "" + selectedRobots); + } + + /** + * Sets the selectedRobots. + * + * @param robots The robots to set + */ + public void setSelectedRobots(RobotSpecification[] robots) { + StringBuffer robotString = new StringBuffer(); + RobotSpecification robot; + + for (int i = 0; i < robots.length; i++) { + robot = robots[i]; + if (robot == null) { + continue; + } + + robotString.append(robot.getClassName()); + + if (!(robot.getVersion() == null || robot.getVersion().length() == 0)) { + robotString.append(' ').append(robot.getVersion()); + } + + if (i < robots.length - 1) { + robotString.append(','); + } + } + setSelectedRobots(robotString.toString()); + } + + /** + * Gets the initial robot positions and headings. + * + * @return a comma-separated string containing the initial positions and headings as a comma separated string: + * x1,y1,heading1, x2,y2,heading2 + * + * @since 1.7.1.2 + */ + public String getInitialPositions() { + return initialPositions; + } + + /** + * Sets the initial robot positions and headings. + * + * @param positions is the initial positions and headings as a comma separated string: + * x1,y1,heading1, x2,y2,heading2 + * + * @since 1.7.1.2 + */ + public void setInitialPositions(String positions) { + this.initialPositions = positions; + } + + /** + * Sets the initial robot positions and headings. + * + * @param initialSetups is the initial positions and headings as a {@link RobotSetup} array. + * + * @since 1.9.2.0 + */ + public void setInitialPositions(RobotSetup[] initialSetups) { + if (initialSetups == null) { + return; + } + + StringBuilder sb = new StringBuilder(); + + for (RobotSetup setup : initialSetups) { + String x = (setup.getX() == null) ? "?" : "" + setup.getX(); + String y = (setup.getY() == null) ? "?" : "" + setup.getY(); + String heading = (setup.getHeading() == null) ? "?" : "" + setup.getHeading(); + + sb.append('('); + sb.append(x).append(','); + sb.append(y).append(','); + sb.append(heading); + sb.append("),"); + } + + this.initialPositions = sb.toString(); + } + + /** + * Returns the sentry border size for a {@link robocode.BorderSentry BorderSentry}. + * + * @return the border size in units/pixels. + */ + public int getSentryBorderSize() { + return sentryBorderSize; + } + + /** + * Returns the sentry border size for a {@link robocode.BorderSentry BorderSentry}. + * + * @param borderSize is the sentry border size in units/pixels. + */ + public void setSentryBorderSize(int borderSize) { + sentryBorderSize = borderSize; + props.setProperty(BATTLE_SENTRY_BORDER_SIZE, "" + sentryBorderSize); + } + + public void store(FileOutputStream out, String desc) throws IOException { + props.store(out, desc); + } + + public void load(FileInputStream in) throws IOException { + props.load(in); + battlefieldWidth = Integer.parseInt(props.getProperty(BATTLEFIELD_WIDTH, "800")); + battlefieldHeight = Integer.parseInt(props.getProperty(BATTLEFIELD_HEIGHT, "600")); + gunCoolingRate = Double.parseDouble(props.getProperty(BATTLE_GUNCOOLINGRATE, "0.1")); + inactivityTime = Long.parseLong(props.getProperty(BATTLE_RULES_INACTIVITYTIME, "450")); + hideEnemyNames = Boolean.parseBoolean(props.getProperty(BATTLE_HIDE_ENEMY_NAMES, "false")); + numRounds = Integer.parseInt(props.getProperty(BATTLE_NUMROUNDS, "10")); + selectedRobots = props.getProperty(BATTLE_SELECTEDROBOTS, ""); + initialPositions = props.getProperty(BATTLE_INITIAL_POSITIONS, ""); + sentryBorderSize = Integer.parseInt(props.getProperty(BATTLE_SENTRY_BORDER_SIZE, "100")); + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleRankingTableModel.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleRankingTableModel.java new file mode 100644 index 0000000..bf32324 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleRankingTableModel.java @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +import robocode.control.snapshot.IScoreSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + +import javax.swing.table.AbstractTableModel; + + +/** + * This table model extracts the robot ranking from the current battle, + * in order to be displayed by the RankingDialog. + * + * @author Luis Crespo (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + * @author Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh (contributors) + */ +@SuppressWarnings("serial") +public class BattleRankingTableModel extends AbstractTableModel { + + private IScoreSnapshot[] scoreSnapshotList; + + // The sum of the scores gathered by the robots in the actual round + private double currentSum; + + // The sum of the scores gathered by the robots in the previous rounds + private double totalSum; + + /** + * Function for counting the sum of the scores gathered by the robots. + */ + private void countTotalScores() { + currentSum = 0; + totalSum = 0; + + for (IScoreSnapshot score : scoreSnapshotList) { + currentSum += score.getCurrentScore(); + totalSum += score.getTotalScore(); + } + } + + public void updateSource(ITurnSnapshot snapshot) { + if (snapshot != null) { + scoreSnapshotList = snapshot.getSortedTeamScores(); + countTotalScores(); + } else { + scoreSnapshotList = null; + } + } + + public int getColumnCount() { + return 12; + } + + public int getRowCount() { + return scoreSnapshotList == null ? 0 : scoreSnapshotList.length; + } + + @Override + public String getColumnName(int col) { + switch (col) { + case 0: + return "Rank"; + + case 1: + return "Robot Name"; + + case 2: + return " Total Score "; + + case 3: + return " Survival "; + + case 4: + return "Surv Bonus"; + + case 5: + return " Bullet Dmg "; + + case 6: + return " Bullet Bonus "; + + case 7: + return "Ram Dmg * 2"; + + case 8: + return "Ram Bonus"; + + case 9: + return " 1sts "; + + case 10: + return " 2nds "; + + case 11: + return " 3rds "; + + default: + return ""; + } + } + + public Object getValueAt(int row, int col) { + + final IScoreSnapshot statistics = scoreSnapshotList[row]; + + switch (col) { + case 0: + return getPlacementString(row + 1); + + case 1: + return statistics.getName(); + + case 2: { + final double current = statistics.getCurrentScore(); + final double total = statistics.getTotalScore(); + + return (int) (current + 0.5) + " / " + (int) (total + current + 0.5) + " (" + + (int) (current / currentSum * 100) + " / " + (int) ((total + current) / (totalSum + currentSum) * 100) + + "%)"; + } + + case 3: { + final double current = statistics.getCurrentSurvivalScore(); + final double total = statistics.getTotalSurvivalScore(); + + return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); + } + + case 4: + return (int) (statistics.getTotalLastSurvivorBonus() + 0.5); + + case 5: { + final double current = statistics.getCurrentBulletDamageScore(); + final double total = statistics.getTotalBulletDamageScore(); + + return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); + } + + case 6: { + final double current = statistics.getCurrentBulletKillBonus(); + final double total = statistics.getTotalBulletKillBonus(); + + return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); + } + + case 7: { + final double current = statistics.getCurrentRammingDamageScore(); + final double total = statistics.getTotalRammingDamageScore(); + + return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); + } + + case 8: { + final double current = statistics.getCurrentRammingKillBonus(); + final double total = statistics.getTotalRammingKillBonus(); + + return (int) (current + 0.5) + " / " + (int) (total + current + 0.5); + } + + case 9: + return "" + statistics.getTotalFirsts(); + + case 10: + return "" + statistics.getTotalSeconds(); + + case 11: + return "" + statistics.getTotalThirds(); + + default: + return ""; + } + } + + private static String getPlacementString(int i) { + String result = "" + i; + + if (i > 3 && i < 20) { + result += "th"; + } else if (i % 10 == 1) { + result += "st"; + } else if (i % 10 == 2) { + result += "nd"; + } else if (i % 10 == 3) { + result += "rd"; + } else { + result += "th"; + } + return result; + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleResultsTableModel.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleResultsTableModel.java new file mode 100644 index 0000000..1d3159f --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/BattleResultsTableModel.java @@ -0,0 +1,253 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +import net.sf.robocode.io.Logger; +import robocode.BattleResults; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.text.DateFormat; +import java.text.NumberFormat; +import java.util.Date; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + * @author Nathaniel Troutman (contributor) + * @author Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh (contributors) + */ +@SuppressWarnings("serial") +public class BattleResultsTableModel extends javax.swing.table.AbstractTableModel { + private String title; + private final BattleResults[] results; + private final int numRounds; + + // The sum of the scores gathered by the robots. + private final double totalScore; + + public BattleResultsTableModel(BattleResults[] results, int numRounds) { + this.results = results; + this.numRounds = numRounds; + totalScore = countTotalScore(); + } + + /** + * Function for counting the sum of the scores gathered by the robots. + * + * @return The sum. + */ + private double countTotalScore() { + + double totalScore = 0; + + for (BattleResults result : results) { + totalScore += result.getScore(); + } + + return totalScore; + } + + public int getColumnCount() { + return 12; + } + + @Override + public String getColumnName(int col) { + switch (col) { + case 0: + return "Rank"; + + case 1: + return "Robot Name"; + + case 2: + return " Total Score "; + + case 3: + return "Survival"; + + case 4: + return "Surv Bonus"; + + case 5: + return "Bullet Dmg"; + + case 6: + return "Bullet Bonus"; + + case 7: + return "Ram Dmg * 2"; + + case 8: + return "Ram Bonus"; + + case 9: + return " 1sts "; + + case 10: + return " 2nds "; + + case 11: + return " 3rds "; + + default: + return ""; + } + } + + public int getRowCount() { + return results.length; + } + + public String getTitle() { + if (title == null) { + int round = numRounds; + + title = "Results for " + round + " round"; + if (round > 1) { + title += 's'; + } + } + return title; + } + + public Object getValueAt(int row, int col) { + + BattleResults statistics = results[row]; + + switch (col) { + case 0: { + int place = row + 1; + + while (place < getRowCount() && statistics.getScore() == results[place].getScore()) { + place++; + } + return getPlacementString(place); + } + + case 1: + return statistics.getTeamLeaderName(); + + case 2: + String percent = ""; + + if (totalScore != 0) { + percent = " (" + NumberFormat.getPercentInstance().format(statistics.getScore() / totalScore) + ")"; + } + return "" + (int) (statistics.getScore() + 0.5) + percent; + + case 3: + return "" + (int) (statistics.getSurvival() + 0.5); + + case 4: + return "" + (int) (statistics.getLastSurvivorBonus() + 0.5); + + case 5: + return "" + (int) (statistics.getBulletDamage() + 0.5); + + case 6: + return "" + (int) (statistics.getBulletDamageBonus() + 0.5); + + case 7: + return "" + (int) (statistics.getRamDamage() + 0.5); + + case 8: + return "" + (int) (statistics.getRamDamageBonus() + 0.5); + + case 9: + return "" + statistics.getFirsts(); + + case 10: + return "" + statistics.getSeconds(); + + case 11: + return "" + statistics.getThirds(); + + default: + return ""; + } + } + + // Used for printing to the console only + public void print(PrintStream out) { + out.println(getTitle()); + + for (int col = 1; col < getColumnCount(); col++) { + out.print(getColumnName(col) + "\t"); + } + + out.println(); + + for (int row = 0; row < getRowCount(); row++) { + out.print(getValueAt(row, 0) + ": "); + for (int col = 1; col < getColumnCount(); col++) { + out.print(getValueAt(row, col) + "\t"); + } + out.println(); + } + } + + public void saveToFile(String filename, boolean append) { + try { + PrintStream out = new PrintStream(new FileOutputStream(filename, append)); + + out.println(DateFormat.getDateTimeInstance().format(new Date())); + + out.println(getTitle()); + + for (int col = 0; col < getColumnCount(); col++) { + if (col > 0) { + out.print(','); + } + out.print(getColumnName(col)); + } + + out.println(); + + for (int row = 0; row < getRowCount(); row++) { + for (int col = 0; col < getColumnCount(); col++) { + if (col > 0) { + out.print(','); + } + out.print(getValueAt(row, col)); + } + out.println(); + } + + out.println("$"); + + out.close(); + + } catch (IOException e) { + Logger.logError(e); + } + } + + private static String getPlacementString(int i) { + String result = "" + i; + + if (i > 3 && i < 20) { + result += "th"; + } else if (i % 10 == 1) { + result += "st"; + } else if (i % 10 == 2) { + result += "nd"; + } else if (i % 10 == 3) { + result += "rd"; + } else { + result += "th"; + } + return result; + } + +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/IBattleManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/IBattleManager.java new file mode 100644 index 0000000..76049be --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/battle/IBattleManager.java @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.battle; + + +import robocode.Event; + + +/** + * Used for controlling a robot from the e.g. the UI or RobocodeEngine. + * + * @author Flemming N. Larsen + * + * @since 1.6.1 + */ +public interface IBattleManager extends IBattleManagerBase { + + /** + * Kills the robot. + * + * @param robotIndex the index of the robot to kill. + */ + void killRobot(int robotIndex); + + /** + * Enable or disable the robot paintings. + * + * @param robotIndex the index of the robot that must have its paintings enabled or disabled. + * @param enable {@code true} if paint must be enabled; {@code false} otherwise. + */ + void setPaintEnabled(int robotIndex, boolean enable); + + /** + * Enable or disable the robot paintings using the RobocodeSG coordinate system + * with the y-axis reversed compared to the coordinate system used in Robocode. + * + * @param robotIndex the index of the robot that must use RobocodeSG paintings. + * @param enable {@code true} if RobocodeSG paint coordinate system must be + * enabled when painting the robot; {@code false} otherwise. + */ + void setSGPaintEnabled(int robotIndex, boolean enable); + + /** + * Sends an interactive event for the robot. + * + * @param event the interactive event that has occurred to the robot. + */ + void sendInteractiveEvent(Event event); + + void startNewBattle(BattleProperties battleProperties, boolean waitTillOver, boolean enableCLIRecording); + + void nextTurn(); + + void prevTurn(); + + void pauseBattle(); + + void resumeBattle(); + + void togglePauseResumeBattle(); + + void resumeIfPausedBattle(); // TODO refactor, remove + + void pauseIfResumedBattle(); // TODO refactor, remove + + void restart(); + + void replay(); + + boolean isManagedTPS(); + + void setManagedTPS(boolean value); + + String getBattlePath(); + + String getBattleFilename(); + + void setBattleFilename(String newBattleFilename); + + BattleProperties loadBattleProperties(); + + void saveBattleProperties(); + + BattleProperties getBattleProperties(); + + void setDefaultBattleProperties(); + + void cleanup(); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/cachecleaner/CacheCleaner.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/cachecleaner/CacheCleaner.java new file mode 100644 index 0000000..e14ecdd --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/cachecleaner/CacheCleaner.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.cachecleaner; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.IRepositoryManager; + +import java.io.File; +import java.io.IOException; + + +/** + * Cache cleaner used for cleaning the /robot directory of Robocode, especially + * for RoboRumble + * + * @author AaronR + * @author Flemming N. Larsen (minor optimizations) + */ +public final class CacheCleaner { + private CacheCleaner() {} + + public static void main(String[] args) { + clean(); + } + + public static void clean() { + File roborumbleTempFile = new File("roborumble/temp"); + + deleteFile(roborumbleTempFile.getPath()); + deleteFile(FileUtil.getRobotsDataDir().getPath()); + deleteFile(FileUtil.getRobotDatabaseFile().getPath()); + + FileUtil.createDir(roborumbleTempFile); + + final IRepositoryManager repositoryManager = Container.getComponent(IRepositoryManager.class); + + repositoryManager.reload(true); + + Logger.logMessage("Cleaning done."); + } + + private static void deleteFile(String filename) { + Logger.logMessage("Deleting " + filename + "..."); + try { + recursivelyDelete(new File(filename)); + } catch (IOException ex) { + Logger.logError(ex.getMessage()); + } + } + + private static void recursivelyDelete(File file) throws IOException { + if (file.exists()) { + if (file.isDirectory()) { + final File[] files = file.listFiles(); + + for (File f : files) { + recursivelyDelete(f); + } + } + if (!file.delete()) { + throw new IOException("Failed deleting file: " + file.getPath()); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/BaseModule.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/BaseModule.java new file mode 100644 index 0000000..f3586b0 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/BaseModule.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.core; + + +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public class BaseModule implements IModule { + public void afterLoaded(List allModules) {} +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/Container.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/Container.java new file mode 100644 index 0000000..3b2cba2 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/Container.java @@ -0,0 +1,257 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.core; + + +import net.sf.robocode.io.Logger; + +import org.picocontainer.Characteristics; +import org.picocontainer.MutablePicoContainer; +import org.picocontainer.behaviors.Caching; +import org.picocontainer.behaviors.OptInCaching; +import org.picocontainer.classname.DefaultClassLoadingPicoContainer; + +import java.awt.Toolkit; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.net.URL; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +/** + * Root of loaders. + * + * we have three types of classLoaders. + * 1) System class loader. Is loaded by default and is parent of loaders below. It contains this container class. All content of robot.api module. All general java stuff. + * 2) EngineClassLoader. Is used as isolation of all other robocode modules from system classloader. Anything loaded by engine is loaded there. We use single instance of this loader. + * 3) RobotClassLoader. Is used by robots. It will load every class on robot's private classPath. It blocks malicious attempts of references to robocode engine classes. We use multiple instances of this loader. + * - communication between classes from different classloaders must be done using interfaces or data types from system classLoader + * - this class must not reference any class of EngineClassLoader scope + * + * Dependency injection + * We use PicoContainer as IoC vehicle. We configure it by loading Module class in every .jar or classpath we can find on system classPath + * 1) Container.cache is containing singletons + * 2) Container.factory will create always new instance of component + * + * @author Pavel Savara (original) + */ +public final class Container extends ContainerBase { + + private static final String classPath = System.getProperties().getProperty("robocode.class.path", null); + + public static final MutablePicoContainer cache; + public static final MutablePicoContainer factory; + public static final ClassLoader systemLoader; + public static final ClassLoader engineLoader; // NO_UCD (use private - used by the .NET plug-in) + private static Set known = new HashSet(); + private static final List modules = new ArrayList(); + + static { + instance = new Container(); + systemLoader = Container.class.getClassLoader(); + engineLoader = new EngineClassLoader(systemLoader); + final Thread currentThread = Thread.currentThread(); + + currentThread.setContextClassLoader(engineLoader); + currentThread.setName("Application Thread"); + + // make sure we have AWT before we init security + Toolkit.getDefaultToolkit(); + + cache = new DefaultClassLoadingPicoContainer(engineLoader, new Caching(), null); + factory = new DefaultClassLoadingPicoContainer(engineLoader, new OptInCaching(), cache); + loadModule("net.sf.robocode.api", systemLoader); + final String[] cp = classPath.split(File.pathSeparator); + + // load core first + for (String path : cp) { + if (path.toLowerCase().contains("robocode.core")) { + loadFromPath(path); + } + } + for (String path : cp) { + loadFromPath(path); + } + + if (known.size() < 2) { + Logger.logError("Main modules not loaded, something went wrong. We have only " + known.size() + " modules"); + Logger.logError("Class path: " + classPath); + throw new Error("Main modules not loaded"); + } + + for (IModule module : modules) { + module.afterLoaded(modules); + } + } + + static void init() {} + + private static void loadFromPath(String path) { + try { + File pathf = new File(path).getCanonicalFile(); + + path = pathf.toString(); + final String test = path.toLowerCase(); + + if (pathf.isDirectory()) { + String name = getModuleName(path); + + if (name != null) { + loadModule(name, engineLoader); + } + } else if (test.contains(File.separator + "robocode.") && test.endsWith(".jar")) { + final int i = test.lastIndexOf("robocode.jar"); + + if (i > 0) { + // load other .jar files in location + final File dir = new File(path.substring(0, i)); + + Logger.logMessage("Loading plugins from " + dir.toString()); + loadJars(dir); + } else { + String name = getModuleName(path); + + if (name != null) { + loadModule(name, engineLoader); + } + } + } + } catch (IOException e) { + Logger.logError(e); + } + } + + private static void loadJars(File pathf) { + final File[] files = pathf.listFiles(new FilenameFilter() { + public boolean accept(File dir, String name) { + return name.toLowerCase().startsWith("robocode") && name.toLowerCase().endsWith(".jar"); + } + }); + + for (File file : files) { + loadModule(getModuleName(file.toString()), engineLoader); + } + } + + private static boolean loadModule(String module, ClassLoader loader) { + try { + if (known.contains(module)) { + // Logger.logMessage("already loaded " + module); + return false; + } + Class modClass = loader.loadClass(module + ".Module"); + + final Object moduleInstance = modClass.newInstance(); + + if (moduleInstance instanceof IModule) { + modules.add((IModule) moduleInstance); + } + Logger.logMessage("Loaded " + module); + known.add(module); + return true; + } catch (ClassNotFoundException ignore) {// it is not our module ? + // Logger.logMessage("Can't load " + module); + } catch (IllegalAccessException e) { + Logger.logError(e); + } catch (InstantiationException e) { + Logger.logError(e); + } + return false; + } + + private static String getModuleName(String path) { + final String test = path.toLowerCase(); + + if (test.endsWith("robocode.jar") || test.contains("robocode.api")) { + return null; + } + int i = test.lastIndexOf("robocode."); + + if (i > 0) { + String name = path.substring(i); + + i = name.indexOf(File.separator); + if (i > 0) { + return "net.sf." + name.substring(0, i); + } + i = name.indexOf("-"); + if (i > 0) { + return "net.sf." + name.substring(0, i); + } + return "net.sf." + name; + } + return null; + } + + static URL[] findJars(String allowed) { + List urls = new ArrayList(); + final String classPath = System.getProperty("robocode.class.path", null); + + for (String path : classPath.split(File.pathSeparator)) { + String test = path.toLowerCase(); + + if (test.contains(allowed)) { + if (!test.contains("robocode.jar") && !test.contains("robocode.api") + ) { + urls.add(path); + } + } + } + return convertUrls(urls); + } + + private static URL[] convertUrls(List surls) { + final URL[] urls = new URL[surls.size()]; + + for (int i = 0; i < surls.size(); i++) { + String url = surls.get(i); + File f = new File(url); + + try { + urls[i] = f.getCanonicalFile().toURI().toURL(); + } catch (MalformedURLException e) { + Logger.logError(e); + } catch (IOException e) { + Logger.logError(e); + } + } + return urls; + } + + protected T getBaseComponent(final Class tClass) { + return cache.getComponent(tClass); + } + + public static T getComponent(java.lang.Class tClass) { + return cache.getComponent(tClass); + } + + public static T getComponent(java.lang.Class tClass, String className) { + final List list = cache.getComponents(tClass); + + for (T component : list) { + if (component.getClass().getName().endsWith(className)) { + return component; + } + } + return null; + } + + public static List getComponents(java.lang.Class tClass) { + return cache.getComponents(tClass); + } + + public static T createComponent(java.lang.Class tClass) { + return factory.as(Characteristics.NO_CACHE).getComponent(tClass); + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/EngineClassLoader.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/EngineClassLoader.java new file mode 100644 index 0000000..b796707 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/EngineClassLoader.java @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.core; + + +import java.net.URL; +import java.net.URLClassLoader; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.HashSet; +import java.util.Set; +import java.io.File; + +import net.sf.robocode.io.RobocodeProperties; + + +/** + * @author Pavel Savara (original) + */ +public class EngineClassLoader extends URLClassLoader { + + private static Set exclusions = new HashSet(); + static { + // this will be loaded on system classloader + exclusions.add(EngineClassLoader.class.getName()); + exclusions.add(Container.class.getName()); + exclusions.add(RobocodeMainBase.class.getName()); + + // .NET proxies and their interfaces must be loaded in system class loader in order to call native methods + exclusions.add("net.sf.robocode.host.IHost"); + exclusions.add("net.sf.robocode.host.IHostManager"); + exclusions.add("net.sf.robocode.host.proxies.IHostingRobotProxy"); + exclusions.add("net.sf.robocode.peer.IRobotPeer"); + exclusions.add("net.sf.robocode.repository.IRobotItem"); + exclusions.add("net.sf.robocode.repository.RobotType"); + exclusions.add("net.sf.robocode.host.RobotStatics"); + exclusions.add("net.sf.robocode.peer.BadBehavior"); + exclusions.add("net.sf.robocode.dotnet.host.DotNetHost"); + exclusions.add("net.sf.robocode.dotnet.repository.root.DllRootHelper"); + exclusions.add("net.sf.robocode.dotnet.nhost.ModuleN"); + exclusions.add("net.sf.robocode.host.proxies.__IHostingRobotProxy"); + } + + public EngineClassLoader(ClassLoader parent) { + super(Container.findJars(File.separator + "robocode."), parent); + } + + public synchronized void addURL(URL url) { + super.addURL(url); + } + + public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + + if (RobocodeProperties.isSecurityOff() || name.startsWith("java.lang")) { + return super.loadClass(name, resolve); + } + if (isEngineClass(name)) { + return loadEngineClass(name, resolve); + } + return super.loadClass(name, resolve); + } + + private Class loadEngineClass(String name, boolean resolve) throws ClassNotFoundException { + Class result = findLoadedClass(name); + + if (result == null) { + result = findClass(name); + } + if (resolve) { + resolveClass(result); + } + return result; + } + + private boolean isEngineClass(String name) { + if (name.startsWith("net.sf.robocode") || name.startsWith("robocode.control")) { + if (exclusions.contains(name)) { + return false; + } + // try to find it in engine's classpath + // this is URL, don't change to File.pathSeparator + final String path = name.replace('.', '/').concat(".class"); + + return AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return findResource(path) != null; + } + }); + } + return false; + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/Module.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/Module.java new file mode 100644 index 0000000..ae76ab2 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/Module.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.core; + + +import net.sf.robocode.host.RobotStatics; +import net.sf.robocode.peer.*; +import net.sf.robocode.serialization.RbSerializer; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.settings.SettingsManager; +import net.sf.robocode.version.IVersionManager; +import net.sf.robocode.version.VersionManager; + +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public class Module extends BaseModule { + static { + Container.cache.addComponent(RobocodeMain.class); + Container.cache.addComponent(IVersionManager.class, VersionManager.class); + Container.cache.addComponent(ISettingsManager.class, SettingsManager.class); + } + + @Override + public void afterLoaded(List allModules) { + RbSerializer.register(ExecCommands.class, RbSerializer.ExecCommands_TYPE); + RbSerializer.register(BulletCommand.class, RbSerializer.BulletCommand_TYPE); + RbSerializer.register(TeamMessage.class, RbSerializer.TeamMessage_TYPE); + RbSerializer.register(DebugProperty.class, RbSerializer.DebugProperty_TYPE); + RbSerializer.register(ExecResults.class, RbSerializer.ExecResults_TYPE); + RbSerializer.register(BulletStatus.class, RbSerializer.BulletStatus_TYPE); + RbSerializer.register(RobotStatics.class, RbSerializer.RobotStatics_TYPE); + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMainBase.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMainBase.java new file mode 100644 index 0000000..79e6db4 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/core/RobocodeMainBase.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.core; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import robocode.control.events.IBattleListener; + +import java.io.File; +import java.io.IOException; +import java.lang.Thread.UncaughtExceptionHandler; + + +/** + * There are entrypoints called with reflection from HiddenAccess in robocode.api module, + * they cross classloaders boundaries. + * + * @author Pavel Savara (original) + */ +public abstract class RobocodeMainBase implements Runnable { + public abstract void loadSetup(String[] args); + + public abstract void initForRobocodeEngine(IBattleListener listener); + + public abstract void cleanup(); + + // ----------- + // entrypoints called with reflection from HiddenAccess in robocode.api module + // ----------- + + public static void robocodeMain(Object args) { + // here we cross transition to EngineClassLoader classes using interface which is defined in system classLoader + RobocodeMainBase main = Container.getComponent(RobocodeMainBase.class); + + main.loadSetup((String[]) args); + + // Make sure ALL uncaught exceptions are logged + Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { + public void uncaughtException(Thread t, Throwable e) { + Logger.logError("UncaughtException on thread " + t.getClass(), e); + } + }); + + ThreadGroup group = new ThreadGroup("Robocode thread group"); + + new Thread(group, main, "Robocode main thread").start(); + } + + public static void initContainer() { + // here we cross transition to EngineClassLoader classes using interface which is defined in system classLoader + Container.init(); + } + + public static void cleanupForRobocodeEngine() { + // here we cross transition to EngineClassLoader classes using interface which is defined in system classLoader + RobocodeMainBase main = Container.getComponent(RobocodeMainBase.class); + + main.cleanup(); + } + + public static void initContainerForRobocodeEngine(File robocodeHome, IBattleListener listener) { + try { + if (robocodeHome == null) { + robocodeHome = FileUtil.getCwd(); + } + FileUtil.setCwd(robocodeHome); + + File robotsDir = FileUtil.getRobotsDir(); + + if (robotsDir == null) { + throw new RuntimeException("No valid robot directory is specified"); + } else if (!(robotsDir.exists() && robotsDir.isDirectory())) { + throw new RuntimeException('\'' + robotsDir.getAbsolutePath() + "' is not a valid robot directory"); + } + + } catch (IOException e) { + System.err.println(e); + return; + } + + // here we cross transition to EngineClassLoader classes using interface which is defined in system classLoader + RobocodeMainBase main = Container.getComponent(RobocodeMainBase.class); + + main.initForRobocodeEngine(listener); + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/ICpuManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/ICpuManager.java new file mode 100644 index 0000000..03bc90d --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/ICpuManager.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +/** + * @author Pavel Savara (original) + */ +public interface ICpuManager { + long getCpuConstant(); + + void calculateCpuConstant(); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/IHostManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/IHostManager.java new file mode 100644 index 0000000..8a80d46 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/IHostManager.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import net.sf.robocode.peer.IRobotPeer; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.repository.RobotType; +import robocode.control.RobotSpecification; + +import java.io.PrintStream; + + +/** + * @author Pavel Savara (original) + */ +public interface IHostManager { + + void initSecurity(); + + long getRobotFilesystemQuota(); + + void resetThreadManager(); + + void addSafeThread(Thread safeThread); + + void removeSafeThread(Thread safeThread); + + PrintStream getRobotOutputStream(); + + Object createRobotProxy(RobotSpecification robotSpecification, RobotStatics statics, IRobotPeer peer); + + void cleanup(); + + String[] getReferencedClasses(IRobotItem robotItem); + + RobotType getRobotType(IRobotItem robotItem, boolean resolve, boolean message); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/IRobotClassLoader.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/IRobotClassLoader.java new file mode 100644 index 0000000..245b165 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/IRobotClassLoader.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import robocode.robotinterfaces.IBasicRobot; + + +/** + * @author Pavel Savara (original) + */ +public interface IRobotClassLoader { + Class loadRobotMainClass(boolean resolve) throws ClassNotFoundException; + IBasicRobot createRobotInstance() throws ClassNotFoundException, InstantiationException, IllegalAccessException; + String[] getReferencedClasses(); + void setRobotProxy(Object robotProxy); + void cleanup(); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/RobotStatics.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/RobotStatics.java new file mode 100644 index 0000000..3f1367a --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/host/RobotStatics.java @@ -0,0 +1,319 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.security.HiddenAccess; +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.BattleRules; +import robocode.control.RobotSpecification; + +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public final class RobotStatics implements IRobotStatics, Serializable { + private static final long serialVersionUID = 1L; + + private final String robocodeVersion; + + private final boolean isJuniorRobot; + private final boolean isAdvancedRobot; + private final boolean isTeamRobot; + private final boolean isDroid; + private final boolean isSentryRobot; + + private final boolean isInteractiveRobot; + private final boolean isPaintRobot; + + private final boolean isTeamLeader; + + private final String name; + private final String shortName; + private final String veryShortName; + + private final String fullClassName; + private final String shortClassName; + + private final BattleRules battleRules; + + private final String[] teammates; + private final String teamName; + + private final int robotIndex; + private final int teamIndex; + + public RobotStatics(RobotSpecification robotSpecification, int duplicate, boolean isLeader, BattleRules rules, String teamName, List teamMembers, int robotIndex, int teamIndex) { + IRobotItem robotItem = ((IRobotItem) HiddenAccess.getFileSpecification(robotSpecification)); + + this.robotIndex = robotIndex; + this.teamIndex = teamIndex; + + shortClassName = robotItem.getShortClassName(); + fullClassName = robotItem.getFullClassName(); + if (duplicate >= 0) { + String countString = " (" + (duplicate + 1) + ')'; + + name = robotItem.getUniqueFullClassNameWithVersion() + countString; + shortName = robotItem.getUniqueShortClassNameWithVersion() + countString; + veryShortName = robotItem.getUniqueVeryShortClassNameWithVersion() + countString; + } else { + name = robotItem.getUniqueFullClassNameWithVersion(); + shortName = robotItem.getUniqueShortClassNameWithVersion(); + veryShortName = robotItem.getUniqueVeryShortClassNameWithVersion(); + } + this.robocodeVersion = robotItem.getRobocodeVersion(); + this.isJuniorRobot = robotItem.isJuniorRobot(); + this.isAdvancedRobot = robotItem.isAdvancedRobot(); + this.isTeamRobot = robotItem.isTeamRobot(); + this.isDroid = robotItem.isDroid(); + this.isSentryRobot = robotItem.isSentryRobot(); + this.isInteractiveRobot = robotItem.isInteractiveRobot(); + this.isPaintRobot = robotItem.isPaintRobot(); + this.isTeamLeader = isLeader; + this.battleRules = rules; + + if (teamMembers != null) { + List list = new ArrayList(); + + for (String mate : teamMembers) { + if (!name.equals(mate)) { + list.add(mate); + } + } + teammates = list.toArray(new String[] {}); + this.teamName = teamName; + } else { + teammates = null; + this.teamName = name; + } + } + + private RobotStatics(String robocodeVersion, boolean isJuniorRobot, boolean isInteractiveRobot, boolean isPaintRobot, boolean isAdvancedRobot, + boolean isTeamRobot, boolean isTeamLeader, boolean isDroid, boolean isSentryRobot, String name, String shortName, + String veryShortName, String fullClassName, String shortClassName, BattleRules battleRules, + String[] teammates, String teamName, int robotIndex, int teamIndex) { + + this.robocodeVersion = robocodeVersion; + this.isJuniorRobot = isJuniorRobot; + this.isAdvancedRobot = isAdvancedRobot; + this.isTeamRobot = isTeamRobot; + this.isDroid = isDroid; + this.isSentryRobot = isSentryRobot; + this.isInteractiveRobot = isInteractiveRobot; + this.isPaintRobot = isPaintRobot; + this.isTeamLeader = isTeamLeader; + this.name = name; + this.shortName = shortName; + this.veryShortName = veryShortName; + this.fullClassName = fullClassName; + this.shortClassName = shortClassName; + this.battleRules = battleRules; + this.teammates = teammates; + this.teamName = teamName; + this.robotIndex = robotIndex; + this.teamIndex = teamIndex; + } + + public String getRobocodeVersion() { + return robocodeVersion; + } + + public String getAnnonymousName() { + return "#" + robotIndex; + } + + public boolean isJuniorRobot() { + return isJuniorRobot; + } + + public boolean isAdvancedRobot() { + return isAdvancedRobot; + } + + public boolean isTeamRobot() { + return isTeamRobot; + } + + public boolean isDroid() { + return isDroid; + } + + public boolean isSentryRobot() { + return isSentryRobot; + } + + public boolean isInteractiveRobot() { + return isInteractiveRobot; + } + + public boolean isPaintRobot() { + return isPaintRobot; + } + + public boolean isTeamLeader() { + return isTeamLeader; + } + + public String getName() { + return name; + } + + public String getShortName() { + return shortName; + } + + public String getVeryShortName() { + return veryShortName; + } + + public String getFullClassName() { + return fullClassName; + } + + public String getShortClassName() { + return shortClassName; + } + + public BattleRules getBattleRules() { + return battleRules; + } + + public String[] getTeammates() { + return teammates == null ? null : teammates.clone(); + } + + public String getTeamName() { + return teamName; + } + + public int getRobotIndex() { + return robotIndex; + } + + public int getTeamIndex() { + return teamIndex; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + RobotStatics obj = (RobotStatics) object; + int size = RbSerializer.SIZEOF_TYPEINFO + serializer.sizeOf(obj.robocodeVersion) + + RbSerializer.SIZEOF_BOOL * 9 + serializer.sizeOf(obj.name) + serializer.sizeOf(obj.shortName) + + serializer.sizeOf(obj.veryShortName) + serializer.sizeOf(obj.fullClassName) + + serializer.sizeOf(obj.shortClassName) + RbSerializer.SIZEOF_INT * 6 + RbSerializer.SIZEOF_DOUBLE + + RbSerializer.SIZEOF_LONG; + + if (obj.teammates != null) { + for (String mate : obj.teammates) { + size += serializer.sizeOf(mate); + } + } + size += RbSerializer.SIZEOF_INT; + size += serializer.sizeOf(obj.teamName); + + return size; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + RobotStatics obj = (RobotStatics) object; + + serializer.serialize(buffer, obj.robocodeVersion); + serializer.serialize(buffer, obj.isJuniorRobot); + serializer.serialize(buffer, obj.isInteractiveRobot); + serializer.serialize(buffer, obj.isPaintRobot); + serializer.serialize(buffer, obj.isAdvancedRobot); + serializer.serialize(buffer, obj.isTeamRobot); + serializer.serialize(buffer, obj.isTeamLeader); + serializer.serialize(buffer, obj.isDroid); + serializer.serialize(buffer, obj.isSentryRobot); + serializer.serialize(buffer, obj.name); + serializer.serialize(buffer, obj.shortName); + serializer.serialize(buffer, obj.veryShortName); + serializer.serialize(buffer, obj.fullClassName); + serializer.serialize(buffer, obj.shortClassName); + serializer.serialize(buffer, obj.battleRules.getBattlefieldWidth()); + serializer.serialize(buffer, obj.battleRules.getBattlefieldHeight()); + serializer.serialize(buffer, obj.battleRules.getNumRounds()); + serializer.serialize(buffer, obj.battleRules.getGunCoolingRate()); + serializer.serialize(buffer, obj.battleRules.getInactivityTime()); + serializer.serialize(buffer, obj.battleRules.getHideEnemyNames()); + serializer.serialize(buffer, obj.battleRules.getSentryBorderSize()); + if (obj.teammates != null) { + for (String mate : obj.teammates) { + serializer.serialize(buffer, mate); + } + } + buffer.putInt(-1); + serializer.serialize(buffer, obj.teamName); + serializer.serialize(buffer, obj.robotIndex); + serializer.serialize(buffer, obj.teamIndex); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + + String robocodeVersion = serializer.deserializeString(buffer); + boolean isJuniorRobot = serializer.deserializeBoolean(buffer); + boolean isInteractiveRobot = serializer.deserializeBoolean(buffer); + boolean isPaintRobot = serializer.deserializeBoolean(buffer); + boolean isAdvancedRobot = serializer.deserializeBoolean(buffer); + boolean isTeamRobot = serializer.deserializeBoolean(buffer); + boolean isTeamLeader = serializer.deserializeBoolean(buffer); + boolean isDroid = serializer.deserializeBoolean(buffer); + boolean isSentryRobot = serializer.deserializeBoolean(buffer); + String name = serializer.deserializeString(buffer); + String shortName = serializer.deserializeString(buffer); + String veryShortName = serializer.deserializeString(buffer); + String fullClassName = serializer.deserializeString(buffer); + String shortClassName = serializer.deserializeString(buffer); + + BattleRules battleRules = HiddenAccess.createRules(serializer.deserializeInt(buffer), // battleFieldWidth + serializer.deserializeInt(buffer), // battleFieldHeight + serializer.deserializeInt(buffer), // numOfRounds + serializer.deserializeDouble(buffer), // gunCoolingRate + serializer.deserializeLong(buffer), // inactivityTime + serializer.deserializeBoolean(buffer), // hideEnemyNames + serializer.deserializeInt(buffer)); // sentryBorderSize + + List teammates = new ArrayList(); + Object item = serializer.deserializeString(buffer); + + if (item == null) { + teammates = null; + } + while (item != null) { + if (item instanceof String) { + teammates.add((String) item); + } + item = serializer.deserializeString(buffer); + } + + String teamName = serializer.deserializeString(buffer); + int index = serializer.deserializeInt(buffer); + int contestantIndex = serializer.deserializeInt(buffer); + + return new RobotStatics(robocodeVersion, isJuniorRobot, isInteractiveRobot, isPaintRobot, isAdvancedRobot, + isTeamRobot, isTeamLeader, isDroid, isSentryRobot, name, shortName, veryShortName, fullClassName, + shortClassName, battleRules, teammates.toArray(new String[teammates.size()]), teamName, index, + contestantIndex); + } + } + +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/io/JarJar.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/io/JarJar.java new file mode 100644 index 0000000..720dc88 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/io/JarJar.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.io; + + +/** + * @author Pavel Savara (original) + */ +public class JarJar { + public final static char SEPARATOR_CHAR = '^'; + public final static String SEPARATOR = SEPARATOR_CHAR + "/"; +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/io/URLJarCollector.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/io/URLJarCollector.java new file mode 100644 index 0000000..89727db --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/io/URLJarCollector.java @@ -0,0 +1,176 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.io; + + +import java.net.URLConnection; +import java.net.URL; +import java.net.URLDecoder; +import java.lang.reflect.Field; +import java.util.*; +import java.util.jar.JarFile; +import java.io.File; +import java.io.IOException; + + +/** + * This ugly class is helping with closing of robot .jar files when used with URL, URLConnection and useCaches=true + * It is designed to close JarFiles opened and cached in SUN's JarFileFactory. + * If we are not on SUN's JVM, we fallback to useCaches=false, to not lock the files. + * Collection is now called after reposiotry refresh and after battle ended. + * Collection is disabled/posponed during running battle. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class URLJarCollector { + + private static HashMap fileCache; + private static HashMap urlCache; + private static Field jarFileURL; + private static final boolean sunJVM; + private static boolean enabled; + private static Set urlsToClean = new HashSet(); + + static { + boolean localSunJVM = false; + + try { + final Class jarFactory = ClassLoader.getSystemClassLoader().loadClass( + "sun.net.www.protocol.jar.JarFileFactory"); + final Field fileCacheF = jarFactory.getDeclaredField("fileCache"); + + fileCacheF.setAccessible(true); + fileCache = (HashMap) fileCacheF.get(null); + + final Field urlCacheF = jarFactory.getDeclaredField("urlCache"); + + urlCacheF.setAccessible(true); + urlCache = (HashMap) urlCacheF.get(null); + + final Class jarURLConnection = ClassLoader.getSystemClassLoader().loadClass( + "sun.net.www.protocol.jar.JarURLConnection"); + + jarFileURL = jarURLConnection.getDeclaredField("jarFileURL"); + jarFileURL.setAccessible(true); + + localSunJVM = true; + } catch (ClassNotFoundException ignore) { + Logger.logError(ignore); + } catch (NoSuchFieldException ignore) { + Logger.logError(ignore); + } catch (IllegalAccessException ignore) { + Logger.logError(ignore); + } + sunJVM = localSunJVM; + } + + public static synchronized URLConnection openConnection(URL url) throws IOException { + // Logger.logMessage("Open connection to URL: " + url); + final URLConnection urlConnection = url.openConnection(); + + if (sunJVM) { + registerConnection(urlConnection); + urlConnection.setUseCaches(true); + } else { + urlConnection.setUseCaches(false); + } + return urlConnection; + } + + public static synchronized void enableGc(boolean enabled) { + URLJarCollector.enabled = enabled; + } + + public static synchronized void gc() { + if (sunJVM) { + // Close all JarURLConnections if garbage collection is enabled + if (enabled) { + synchronized (urlsToClean) { + for (URL url : urlsToClean) { + closeJarURLConnection(url); + } + urlsToClean.clear(); + } + } + + // Bug fix [2867326] - Lockup on start if too many bots in robots dir (cont'd). + + // Remove all cache entries to temporary jar cache files created + // for connections using the jarjar protocol that get stuck up. + for (Iterator it = fileCache.keySet().iterator(); it.hasNext();) { + Object urlJarFile = it.next(); + + final JarFile jarFile = (JarFile) fileCache.get(urlJarFile); + + String filename = jarFile.getName(); + + filename = filename.substring(filename.lastIndexOf(File.separatorChar) + 1).toLowerCase(); + + if (filename.startsWith("jar_cache")) { + it.remove(); + synchronized (urlCache) { + urlCache.remove(jarFile); + } + } + } + } + } + + private static void registerConnection(URLConnection conn) { + if (conn != null) { + final String cl = conn.getClass().getName(); + + if (cl.equals("sun.net.www.protocol.jar.JarURLConnection")) { + try { + final URL url = (URL) jarFileURL.get(conn); + + if (!urlsToClean.contains(url)) { + synchronized (urlsToClean) { + urlsToClean.add(url); + } + } + } catch (IllegalAccessException ignore) {} + } + } + } + + // Added due to bug fix [2867326] - Lockup on start if too many bots in robots dir (cont'd). + public synchronized static void closeJarURLConnection(URL url) { + if (url != null) { + for (Iterator it = fileCache.keySet().iterator(); it.hasNext();) { + Object urlJarFile = it.next(); + + final JarFile jarFile = (JarFile) fileCache.get(urlJarFile); + + String urlPath = url.getPath(); + + try { + urlPath = URLDecoder.decode(urlPath, "UTF-8"); + } catch (java.io.UnsupportedEncodingException ignore) {} + + File urlFile = new File(urlPath); + + String jarFileName = jarFile.getName(); + String urlFileName = urlFile.getPath(); + + if (urlFileName.equals(jarFileName)) { + it.remove(); + synchronized (urlCache) { + urlCache.remove(jarFile); + } + try { + jarFile.close(); + } catch (IOException e) { + Logger.logError(e); + } + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BadBehavior.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BadBehavior.java new file mode 100644 index 0000000..502bcb8 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BadBehavior.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.peer; + + +/** + * @author Flemming N. Larsen (original) + */ +public enum BadBehavior { + CANNOT_START, + SKIPPED_TOO_MANY_TURNS, + UNSTOPPABLE, + SECURITY_VIOLATION +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BulletCommand.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BulletCommand.java new file mode 100644 index 0000000..2a0cd54 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BulletCommand.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.peer; + + +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; + +import java.io.Serializable; +import java.nio.ByteBuffer; + + +/** + * @author Pavel Savara (original) + */ +public class BulletCommand implements Serializable { + private static final long serialVersionUID = 1L; + + public BulletCommand(double power, boolean fireAssistValid, double fireAssistAngle, int bulletId) { + this.fireAssistValid = fireAssistValid; + this.fireAssistAngle = fireAssistAngle; + this.bulletId = bulletId; + this.power = power; + } + + private final double power; + private final boolean fireAssistValid; + private final double fireAssistAngle; + private final int bulletId; + + public boolean isFireAssistValid() { + return fireAssistValid; + } + + public int getBulletId() { + return bulletId; + } + + public double getPower() { + return power; + } + + public double getFireAssistAngle() { + return fireAssistAngle; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_DOUBLE + RbSerializer.SIZEOF_BOOL + + RbSerializer.SIZEOF_DOUBLE + RbSerializer.SIZEOF_INT; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + BulletCommand obj = (BulletCommand) object; + + serializer.serialize(buffer, obj.power); + serializer.serialize(buffer, obj.fireAssistValid); + serializer.serialize(buffer, obj.fireAssistAngle); + serializer.serialize(buffer, obj.bulletId); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + double power = buffer.getDouble(); + boolean fireAssistValid = serializer.deserializeBoolean(buffer); + double fireAssistAngle = buffer.getDouble(); + int bulletId = buffer.getInt(); + + return new BulletCommand(power, fireAssistValid, fireAssistAngle, bulletId); + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BulletStatus.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BulletStatus.java new file mode 100644 index 0000000..7fef56f --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/BulletStatus.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.peer; + + +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; + +import java.io.Serializable; +import java.nio.ByteBuffer; + + +/** + * @author Pavel Savara (original) + */ +public class BulletStatus implements Serializable { + private static final long serialVersionUID = 1L; + + public BulletStatus(int bulletId, double x, double y, String victimName, boolean isActive) { + this.bulletId = bulletId; + this.x = x; + this.y = y; + this.isActive = isActive; + this.victimName = victimName; + } + + public final int bulletId; + public final String victimName; + public final boolean isActive; + public final double x; + public final double y; + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + BulletStatus obj = (BulletStatus) object; + + return RbSerializer.SIZEOF_TYPEINFO + RbSerializer.SIZEOF_INT + serializer.sizeOf(obj.victimName) + + RbSerializer.SIZEOF_BOOL + 2 * RbSerializer.SIZEOF_DOUBLE; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + BulletStatus obj = (BulletStatus) object; + + serializer.serialize(buffer, obj.bulletId); + serializer.serialize(buffer, obj.victimName); + serializer.serialize(buffer, obj.isActive); + serializer.serialize(buffer, obj.x); + serializer.serialize(buffer, obj.y); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + int bulletId = buffer.getInt(); + String victimName = serializer.deserializeString(buffer); + boolean isActive = serializer.deserializeBoolean(buffer); + double x = buffer.getDouble(); + double y = buffer.getDouble(); + + return new BulletStatus(bulletId, x, y, victimName, isActive); + } + } + +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/DebugProperty.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/DebugProperty.java new file mode 100644 index 0000000..62ff930 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/DebugProperty.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.peer; + + +import net.sf.robocode.serialization.*; +import robocode.control.snapshot.IDebugProperty; + +import java.io.IOException; +import java.io.Serializable; +import java.nio.ByteBuffer; + + +/** + * @author Pavel Savara (original) + */ +public class DebugProperty implements Serializable, IXmlSerializable, IDebugProperty { + private static final long serialVersionUID = 1L; + + public DebugProperty() {} + + public DebugProperty(String key, String value) { + this.setKey(key); + this.setValue(value); + } + + private String key; + private String value; + + public void writeXml(XmlWriter writer, SerializableOptions options) throws IOException { + writer.startElement("debug"); { + writer.writeAttribute("key", getKey()); + writer.writeAttribute("value", getValue()); + } + writer.endElement(); + } + + public XmlReader.Element readXml(XmlReader reader) { + return reader.expect("debug", new XmlReader.Element() { + public IXmlSerializable read(XmlReader reader) { + final DebugProperty snapshot = new DebugProperty(); + + reader.expect("key", new XmlReader.Attribute() { + public void read(String value) { + snapshot.setKey(value); + } + }); + + reader.expect("value", new XmlReader.Attribute() { + public void read(String value) { + snapshot.setValue(value); + } + }); + + return snapshot; + } + }); + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + DebugProperty obj = (DebugProperty) object; + + return RbSerializer.SIZEOF_TYPEINFO + serializer.sizeOf(obj.key) + serializer.sizeOf(obj.value); + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + DebugProperty obj = (DebugProperty) object; + + serializer.serialize(buffer, obj.key); + serializer.serialize(buffer, obj.value); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + String key = serializer.deserializeString(buffer); + String value = serializer.deserializeString(buffer); + + return new DebugProperty(key, value); + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/ExecCommands.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/ExecCommands.java new file mode 100644 index 0000000..bc089d7 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/ExecCommands.java @@ -0,0 +1,428 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.peer; + + +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.Rules; + +import java.io.Serializable; +import static java.lang.Math.abs; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public final class ExecCommands implements Serializable { + private static final long serialVersionUID = 1L; + public static final int defaultBodyColor = 0xFF29298C; + public static final int defaultGunColor = 0xFF29298C; + public static final int defaultRadarColor = 0xFF29298C; + public static final int defaultScanColor = 0xFF0000FF; + public static final int defaultBulletColor = 0xFFFFFFFF; + + private double bodyTurnRemaining; + private double radarTurnRemaining; + private double gunTurnRemaining; + private double distanceRemaining; + + private boolean isAdjustGunForBodyTurn; + private boolean isAdjustRadarForGunTurn; + private boolean isAdjustRadarForBodyTurn; + private boolean isAdjustRadarForBodyTurnSet; + + private int bodyColor = defaultBodyColor; + private int gunColor = defaultGunColor; + private int radarColor = defaultRadarColor; + private int scanColor = defaultScanColor; + private int bulletColor = defaultBulletColor; + private double maxTurnRate; + private double maxVelocity; + + private boolean moved; + private boolean scan; + private boolean isIORobot; + private boolean isTryingToPaint; + private String outputText; + private List bullets = new ArrayList(); + private List teamMessages = new ArrayList(); + private List debugProperties = new ArrayList(); + private Object graphicsCalls; + + public ExecCommands() { + setMaxVelocity(Double.MAX_VALUE); + setMaxTurnRate(Double.MAX_VALUE); + } + + public ExecCommands(ExecCommands origin, boolean fromRobot) { + bodyTurnRemaining = origin.bodyTurnRemaining; + radarTurnRemaining = origin.radarTurnRemaining; + gunTurnRemaining = origin.gunTurnRemaining; + distanceRemaining = origin.distanceRemaining; + isAdjustGunForBodyTurn = origin.isAdjustGunForBodyTurn; + isAdjustRadarForGunTurn = origin.isAdjustRadarForGunTurn; + isAdjustRadarForBodyTurn = origin.isAdjustRadarForBodyTurn; + isAdjustRadarForBodyTurnSet = origin.isAdjustRadarForBodyTurnSet; + maxTurnRate = origin.maxTurnRate; + maxVelocity = origin.maxVelocity; + copyColors(origin); + if (fromRobot) { + debugProperties = origin.debugProperties; + bullets = origin.bullets; + scan = origin.scan; + moved = origin.moved; + graphicsCalls = origin.graphicsCalls; + outputText = origin.outputText; + teamMessages = origin.teamMessages; + isTryingToPaint = origin.isTryingToPaint; + } + } + + public void copyColors(ExecCommands origin) { + if (origin != null) { + bodyColor = origin.bodyColor; + gunColor = origin.gunColor; + radarColor = origin.radarColor; + bulletColor = origin.bulletColor; + scanColor = origin.scanColor; + } + } + + public int getBodyColor() { + return bodyColor; + } + + public int getRadarColor() { + return radarColor; + } + + public int getGunColor() { + return gunColor; + } + + public int getBulletColor() { + return bulletColor; + } + + public int getScanColor() { + return scanColor; + } + + public void setBodyColor(int color) { + bodyColor = color; + } + + public void setRadarColor(int color) { + radarColor = color; + } + + public void setGunColor(int color) { + gunColor = color; + } + + public void setBulletColor(int color) { + bulletColor = color; + } + + public void setScanColor(int color) { + scanColor = color; + } + + public double getBodyTurnRemaining() { + return bodyTurnRemaining; + } + + public void setBodyTurnRemaining(double bodyTurnRemaining) { + this.bodyTurnRemaining = bodyTurnRemaining; + } + + public double getRadarTurnRemaining() { + return radarTurnRemaining; + } + + public void setRadarTurnRemaining(double radarTurnRemaining) { + this.radarTurnRemaining = radarTurnRemaining; + } + + public double getGunTurnRemaining() { + return gunTurnRemaining; + } + + public void setGunTurnRemaining(double gunTurnRemaining) { + this.gunTurnRemaining = gunTurnRemaining; + } + + public double getDistanceRemaining() { + return distanceRemaining; + } + + public void setDistanceRemaining(double distanceRemaining) { + this.distanceRemaining = distanceRemaining; + } + + public boolean isAdjustGunForBodyTurn() { + return isAdjustGunForBodyTurn; + } + + public void setAdjustGunForBodyTurn(boolean adjustGunForBodyTurn) { + isAdjustGunForBodyTurn = adjustGunForBodyTurn; + } + + public boolean isAdjustRadarForGunTurn() { + return isAdjustRadarForGunTurn; + } + + public void setAdjustRadarForGunTurn(boolean adjustRadarForGunTurn) { + isAdjustRadarForGunTurn = adjustRadarForGunTurn; + } + + public boolean isAdjustRadarForBodyTurn() { + return isAdjustRadarForBodyTurn; + } + + public void setAdjustRadarForBodyTurn(boolean adjustRadarForBodyTurn) { + isAdjustRadarForBodyTurn = adjustRadarForBodyTurn; + } + + public boolean isAdjustRadarForBodyTurnSet() { + return isAdjustRadarForBodyTurnSet; + } + + public void setAdjustRadarForBodyTurnSet(boolean adjustRadarForBodyTurnSet) { + isAdjustRadarForBodyTurnSet = adjustRadarForBodyTurnSet; + } + + public double getMaxTurnRate() { + return maxTurnRate; + } + + public void setMaxTurnRate(double maxTurnRate) { + this.maxTurnRate = Math.min(abs(maxTurnRate), Rules.MAX_TURN_RATE_RADIANS); + } + + public double getMaxVelocity() { + return maxVelocity; + } + + public void setMaxVelocity(double maxVelocity) { + this.maxVelocity = Math.min(abs(maxVelocity), Rules.MAX_VELOCITY); + } + + public boolean isMoved() { + return moved; + } + + public void setMoved(boolean moved) { + this.moved = moved; + } + + public boolean isScan() { + return scan; + } + + public void setScan(boolean scan) { + this.scan = scan; + } + + public List getBullets() { + return bullets; + } + + public Object getGraphicsCalls() { + return graphicsCalls; + } + + public List getDebugProperties() { + return debugProperties; + } + + public void setGraphicsCalls(Object graphicsCalls) { + this.graphicsCalls = graphicsCalls; + } + + public String getOutputText() { + final String out = outputText; + + outputText = ""; + if (out == null) { + return ""; + } + return out; + } + + public void setOutputText(String out) { + outputText = out; + } + + public List getTeamMessages() { + return teamMessages; + } + + public boolean isIORobot() { + return isIORobot; + } + + public void setIORobot() { + isIORobot = true; + } + + public void setDebugProperty(String key, String value) { + debugProperties.add(new DebugProperty(key, value)); + } + + public boolean isTryingToPaint() { + return isTryingToPaint; + } + + public void setTryingToPaint(boolean tryingToPaint) { + isTryingToPaint = tryingToPaint; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + ExecCommands obj = (ExecCommands) object; + int size = RbSerializer.SIZEOF_TYPEINFO + 4 * RbSerializer.SIZEOF_DOUBLE; + + size += 4 * RbSerializer.SIZEOF_BOOL; + size += 5 * RbSerializer.SIZEOF_INT; + size += 2 * RbSerializer.SIZEOF_DOUBLE; + size += 4 * RbSerializer.SIZEOF_BOOL; + size += serializer.sizeOf(obj.outputText); + + size += serializer.sizeOf((byte[]) obj.graphicsCalls); + + // bullets + size += obj.bullets.size() * serializer.sizeOf(RbSerializer.BulletCommand_TYPE, null); + size += 1; + + // messages + for (TeamMessage m : obj.teamMessages) { + size += serializer.sizeOf(RbSerializer.TeamMessage_TYPE, m); + } + size += 1; + + // properties + for (DebugProperty d : obj.debugProperties) { + size += serializer.sizeOf(RbSerializer.DebugProperty_TYPE, d); + } + size += 1; + + return size; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + ExecCommands obj = (ExecCommands) object; + + serializer.serialize(buffer, obj.bodyTurnRemaining); + serializer.serialize(buffer, obj.radarTurnRemaining); + serializer.serialize(buffer, obj.gunTurnRemaining); + serializer.serialize(buffer, obj.distanceRemaining); + + serializer.serialize(buffer, obj.isAdjustGunForBodyTurn); + serializer.serialize(buffer, obj.isAdjustRadarForGunTurn); + serializer.serialize(buffer, obj.isAdjustRadarForBodyTurn); + serializer.serialize(buffer, obj.isAdjustRadarForBodyTurnSet); + + serializer.serialize(buffer, obj.bodyColor); + serializer.serialize(buffer, obj.gunColor); + serializer.serialize(buffer, obj.radarColor); + serializer.serialize(buffer, obj.scanColor); + serializer.serialize(buffer, obj.bulletColor); + + serializer.serialize(buffer, obj.maxTurnRate); + serializer.serialize(buffer, obj.maxVelocity); + + serializer.serialize(buffer, obj.moved); + serializer.serialize(buffer, obj.scan); + serializer.serialize(buffer, obj.isIORobot); + serializer.serialize(buffer, obj.isTryingToPaint); + + serializer.serialize(buffer, obj.outputText); + + serializer.serialize(buffer, (byte[]) obj.graphicsCalls); + + for (BulletCommand bullet : obj.bullets) { + serializer.serialize(buffer, RbSerializer.BulletCommand_TYPE, bullet); + } + buffer.put(RbSerializer.TERMINATOR_TYPE); + for (TeamMessage message : obj.teamMessages) { + serializer.serialize(buffer, RbSerializer.TeamMessage_TYPE, message); + } + buffer.put(RbSerializer.TERMINATOR_TYPE); + for (DebugProperty prop : obj.debugProperties) { + serializer.serialize(buffer, RbSerializer.DebugProperty_TYPE, prop); + } + buffer.put(RbSerializer.TERMINATOR_TYPE); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + ExecCommands res = new ExecCommands(); + + res.bodyTurnRemaining = buffer.getDouble(); + res.radarTurnRemaining = buffer.getDouble(); + res.gunTurnRemaining = buffer.getDouble(); + res.distanceRemaining = buffer.getDouble(); + + res.isAdjustGunForBodyTurn = serializer.deserializeBoolean(buffer); + res.isAdjustRadarForGunTurn = serializer.deserializeBoolean(buffer); + res.isAdjustRadarForBodyTurn = serializer.deserializeBoolean(buffer); + res.isAdjustRadarForBodyTurnSet = serializer.deserializeBoolean(buffer); + + res.bodyColor = buffer.getInt(); + res.gunColor = buffer.getInt(); + res.radarColor = buffer.getInt(); + res.scanColor = buffer.getInt(); + res.bulletColor = buffer.getInt(); + + res.maxTurnRate = buffer.getDouble(); + res.maxVelocity = buffer.getDouble(); + + res.moved = serializer.deserializeBoolean(buffer); + res.scan = serializer.deserializeBoolean(buffer); + res.isIORobot = serializer.deserializeBoolean(buffer); + res.isTryingToPaint = serializer.deserializeBoolean(buffer); + + res.outputText = serializer.deserializeString(buffer); + + res.graphicsCalls = serializer.deserializeBytes(buffer); + + Object item = serializer.deserializeAny(buffer); + + while (item != null) { + if (item instanceof BulletCommand) { + res.bullets.add((BulletCommand) item); + } + item = serializer.deserializeAny(buffer); + } + item = serializer.deserializeAny(buffer); + while (item != null) { + if (item instanceof TeamMessage) { + res.teamMessages.add((TeamMessage) item); + } + item = serializer.deserializeAny(buffer); + } + item = serializer.deserializeAny(buffer); + while (item != null) { + if (item instanceof DebugProperty) { + res.debugProperties.add((DebugProperty) item); + } + item = serializer.deserializeAny(buffer); + } + return res; + } + } +} + diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/ExecResults.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/ExecResults.java new file mode 100644 index 0000000..c24330c --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/ExecResults.java @@ -0,0 +1,177 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.peer; + + +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; +import robocode.Event; +import robocode.RobotStatus; + +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public final class ExecResults implements Serializable { + private static final long serialVersionUID = 1L; + + private ExecCommands commands; + private RobotStatus status; + private List events; + private List teamMessages; + private List bulletUpdates; + private boolean halt; + private boolean shouldWait; + private boolean paintEnabled; + + public ExecResults(ExecCommands commands, RobotStatus status, List events, List teamMessages, List bulletUpdates, boolean halt, boolean shouldWait, boolean paintEnabled) { + this.commands = commands; + this.status = status; + this.events = events; + this.teamMessages = teamMessages; + this.bulletUpdates = bulletUpdates; + this.halt = halt; + this.shouldWait = shouldWait; + this.paintEnabled = paintEnabled; + } + + private ExecResults() {} + + public ExecCommands getCommands() { + return commands; + } + + public RobotStatus getStatus() { + return status; + } + + public List getEvents() { + return events; + } + + public List getTeamMessages() { + return teamMessages; + } + + public List getBulletUpdates() { + return bulletUpdates; + } + + public boolean isHalt() { + return halt; + } + + public boolean isShouldWait() { + return shouldWait; + } + + public boolean isPaintEnabled() { + return paintEnabled; + } + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + ExecResults obj = (ExecResults) object; + int size = RbSerializer.SIZEOF_TYPEINFO + 3 * RbSerializer.SIZEOF_BOOL; + + size += serializer.sizeOf(RbSerializer.ExecCommands_TYPE, obj.commands); + size += serializer.sizeOf(RbSerializer.RobotStatus_TYPE, obj.status); + + // events + for (Event event : obj.events) { + size += serializer.sizeOf(event); + } + size += 1; + + // messages + for (TeamMessage m : obj.teamMessages) { + size += serializer.sizeOf(RbSerializer.TeamMessage_TYPE, m); + } + size += 1; + + // bullets + for (BulletStatus b : obj.bulletUpdates) { + size += serializer.sizeOf(RbSerializer.BulletStatus_TYPE, b); + } + size += 1; + + return size; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + ExecResults obj = (ExecResults) object; + + serializer.serialize(buffer, obj.halt); + serializer.serialize(buffer, obj.shouldWait); + serializer.serialize(buffer, obj.paintEnabled); + + serializer.serialize(buffer, RbSerializer.ExecCommands_TYPE, obj.commands); + serializer.serialize(buffer, RbSerializer.RobotStatus_TYPE, obj.status); + + for (Event event : obj.events) { + serializer.serialize(buffer, event); + } + buffer.put(RbSerializer.TERMINATOR_TYPE); + for (TeamMessage message : obj.teamMessages) { + serializer.serialize(buffer, RbSerializer.TeamMessage_TYPE, message); + } + buffer.put(RbSerializer.TERMINATOR_TYPE); + for (BulletStatus bulletStatus : obj.bulletUpdates) { + serializer.serialize(buffer, RbSerializer.BulletStatus_TYPE, bulletStatus); + } + buffer.put(RbSerializer.TERMINATOR_TYPE); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + ExecResults res = new ExecResults(); + + res.halt = serializer.deserializeBoolean(buffer); + res.shouldWait = serializer.deserializeBoolean(buffer); + res.paintEnabled = serializer.deserializeBoolean(buffer); + + res.commands = (ExecCommands) serializer.deserializeAny(buffer); + res.status = (RobotStatus) serializer.deserializeAny(buffer); + + res.events = new ArrayList(); + res.teamMessages = new ArrayList(); + res.bulletUpdates = new ArrayList(); + Object item = serializer.deserializeAny(buffer); + + while (item != null) { + if (item instanceof Event) { + res.events.add((Event) item); + } + item = serializer.deserializeAny(buffer); + } + item = serializer.deserializeAny(buffer); + while (item != null) { + if (item instanceof TeamMessage) { + res.teamMessages.add((TeamMessage) item); + } + item = serializer.deserializeAny(buffer); + } + item = serializer.deserializeAny(buffer); + while (item != null) { + if (item instanceof BulletStatus) { + res.bulletUpdates.add((BulletStatus) item); + } + item = serializer.deserializeAny(buffer); + } + return res; + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/IRobotPeer.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/IRobotPeer.java new file mode 100644 index 0000000..faf5f63 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/IRobotPeer.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.peer; + + +import java.io.IOException; +import java.nio.ByteBuffer; + + +/** + * @author Pavel Savara (original) + */ +public interface IRobotPeer { + + void drainEnergy(); + + void punishBadBehavior(BadBehavior badBehavior); + + void setRunning(boolean value); + + boolean isRunning(); + + ExecResults waitForBattleEndImpl(ExecCommands newCommands); + + ExecResults executeImpl(ExecCommands newCommands); + + void setupBuffer(ByteBuffer bidirectionalBuffer); // NO_UCD (unused code - used by the .NET plug-in) + + void executeImplSerial() throws IOException; // NO_UCD (unused code - used by the .NET plug-in) + + void waitForBattleEndImplSerial() throws IOException; // NO_UCD (unused code - used by the .NET plug-in) + + void setupThread(); // NO_UCD (unused code - used by the .NET plug-in) +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/TeamMessage.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/TeamMessage.java new file mode 100644 index 0000000..5db0dc1 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/peer/TeamMessage.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.peer; + + +import net.sf.robocode.serialization.ISerializableHelper; +import net.sf.robocode.serialization.RbSerializer; + +import java.io.Serializable; +import java.nio.ByteBuffer; + + +/** + * @author Pavel Savara (original) + */ +public class TeamMessage implements Serializable { + private static final long serialVersionUID = 1L; + + public TeamMessage(String sender, String recipient, byte[] message) { + this.sender = sender; + this.recipient = recipient; + this.message = message; + + } + + public final String sender; + public final String recipient; + public final byte[] message; + + static ISerializableHelper createHiddenSerializer() { + return new SerializableHelper(); + } + + private static class SerializableHelper implements ISerializableHelper { + public int sizeOf(RbSerializer serializer, Object object) { + TeamMessage obj = (TeamMessage) object; + final int s = serializer.sizeOf(obj.sender); + final int r = serializer.sizeOf(obj.recipient); + final int m = serializer.sizeOf(obj.message); + + return RbSerializer.SIZEOF_TYPEINFO + s + r + m; + } + + public void serialize(RbSerializer serializer, ByteBuffer buffer, Object object) { + TeamMessage obj = (TeamMessage) object; + + serializer.serialize(buffer, obj.sender); + serializer.serialize(buffer, obj.recipient); + serializer.serialize(buffer, obj.message); + } + + public Object deserialize(RbSerializer serializer, ByteBuffer buffer) { + String sender = serializer.deserializeString(buffer); + String recipient = serializer.deserializeString(buffer); + byte[] message = serializer.deserializeBytes(buffer); + + return new TeamMessage(sender, recipient, message); + } + } + +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/recording/BattleRecordFormat.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/recording/BattleRecordFormat.java new file mode 100644 index 0000000..c4b825d --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/recording/BattleRecordFormat.java @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.recording; + + +/** + * @author Flemming N. Larsen (original) + */ +public enum BattleRecordFormat { + BINARY, + BINARY_ZIP, + XML, + XML_ZIP +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/recording/IRecordManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/recording/IRecordManager.java new file mode 100644 index 0000000..4a50d66 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/recording/IRecordManager.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.recording; + + +import net.sf.robocode.battle.events.BattleEventDispatcher; +import net.sf.robocode.serialization.SerializableOptions; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (original) + */ +public interface IRecordManager { + + void attachRecorder(BattleEventDispatcher battleEventDispatcher); + void detachRecorder(); + + void saveRecord(String fileName, BattleRecordFormat format, SerializableOptions options); + + void loadRecord(String fileName, BattleRecordFormat format); + + boolean hasRecord(); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/CodeSizeCalculator.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/CodeSizeCalculator.java new file mode 100644 index 0000000..b1bbdb4 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/CodeSizeCalculator.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + + +/** + * Tool used for calculating the code size of a directory or jar file. + * + * @author Flemming N. Larsen (original) + */ +public final class CodeSizeCalculator { + + public static Integer getDirectoryCodeSize(File dir) { + return getCodeSize("processDirectory", dir); + } + + public static Integer getJarFileCodeSize(File jarFile) { + return getCodeSize("processZipFile", jarFile); + } + + private static Integer getCodeSize(String invokeMethod, File jarFile) { + Integer codesize; + try { + // Call the code size utility using reflection + Class classType = Class.forName("codesize.Codesize"); + + Method method = classType.getMethod(invokeMethod, new Class[] { File.class }); + Object item = method.invoke(null/* static method */, jarFile); + + // Calls Codesize.Item.getCodeSize() + method = item.getClass().getMethod("getCodeSize", (Class[]) null); + codesize = (Integer) method.invoke(item, (Object[]) null); + + } catch (IllegalAccessException e) { + codesize = null; + } catch (InvocationTargetException e) { + codesize = null; + } catch (NoSuchMethodException e) { + codesize = null; + } catch (ClassNotFoundException e) { + codesize = null; + } + return codesize; + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRepositoryManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRepositoryManager.java new file mode 100644 index 0000000..fb6bc87 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRepositoryManager.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import robocode.control.RobotSpecification; + +import java.io.File; +import java.io.IOException; +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public interface IRepositoryManager extends IRepositoryManagerBase { + + /** + * Returns the directory containing the robots. + * + * @return a file that is the directory containing the robots. + */ + File getRobotsDirectory(); + + /** + * Returns all development directories that are additional directories to the 'robots' directory. + * + * @return a list of files containing development directories. + */ + List getDevelDirectories(); + + void refresh(String friendlyUrl); + + boolean refresh(boolean force); + void reload(boolean forced); + + List getRepositoryItems(boolean onlyWithSource, boolean onlyWithPackage, + boolean onlyRobots, boolean onlyDevelopment, boolean onlyNotDevelopment, boolean ignoreTeamRobots, boolean onlyInJar); + + RobotSpecification[] loadSelectedRobots(RobotSpecification[] selectedRobots); + + List getSelectedSpecifications(String selectedRobots); + + boolean verifyRobotName(String robotName, String shortClassName); + + int extractJar(IRobotSpecItem item); + + void createTeam(File target, TeamProperties teamProperties) throws IOException; + + String createPackage(File jarFile, List selectedRobots, RobotProperties robotProperties); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRobotItem.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRobotItem.java new file mode 100644 index 0000000..7497808 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRobotItem.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import java.net.URL; + + +/** + * @author Pavel Savara (original) + */ +public interface IRobotItem extends IRobotSpecItem { + String getPlatform(); + + boolean isJuniorRobot(); + boolean isStandardRobot(); + boolean isAdvancedRobot(); + boolean isTeamRobot(); + boolean isDroid(); + boolean isSentryRobot(); + + boolean isInteractiveRobot(); + boolean isPaintRobot(); + + URL getClassPathURL(); + URL[] getSourcePathURLs(); + + String getWritableDirectory(); + String getReadableDirectory(); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRobotSpecItem.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRobotSpecItem.java new file mode 100644 index 0000000..60c77f2 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/IRobotSpecItem.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import robocode.control.RobotSpecification; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.URL; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public interface IRobotSpecItem extends Comparable { + boolean isValid(); + + boolean isTeam(); + + boolean isInJAR(); + + void setValid(boolean value); + + String getVersion(); + + String getDescription(); + + String getAuthorName(); + + URL getWebpage(); + + boolean getIncludeSource(); + + boolean getIncludeData(); + + boolean isSourceIncluded(); + + String getRootPath(); + + URL getItemURL(); + + boolean isDevelopmentVersion(); + + String getRobocodeVersion(); + + String getFullPackage(); + + String getRelativePath(); + + String getRootPackage(); + + String getFullClassNameWithVersion(); + + String getUniqueFullClassName(); + + String getUniqueFullClassNameWithVersion(); + + String getUniqueShortClassNameWithVersion(); + + String getUniqueVeryShortClassNameWithVersion(); + + String getFullClassName(); + + String getShortClassName(); + + RobotSpecification createRobotSpecification(); + + void storeProperties(OutputStream os, RobotProperties robotProperties) throws IOException; +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/RobotProperties.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/RobotProperties.java new file mode 100644 index 0000000..3bd9e0e --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/RobotProperties.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import java.net.URL; + + +/** + * Container for the robot properties used in robot packages. + * + * @author Flemming N. Larsen (original) + */ +public class RobotProperties { + + private boolean includeSource; + private boolean includeData; + private String version; + private String author; + private String description; + private URL webPage; + private Integer codeSize; + + public boolean isIncludeSource() { + return includeSource; + } + + public void setIncludeSource(boolean includeSource) { + this.includeSource = includeSource; + } + + public boolean isIncludeData() { + return includeData; + } + + public void setIncludeData(boolean includeData) { + this.includeData = includeData; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public URL getWebPage() { + return webPage; + } + + public void setWebPage(URL webPage) { + this.webPage = webPage; + } + + public Integer getCodeSize() { + return codeSize; + } + + public void setCodeSize(Integer codeSize) { + this.codeSize = codeSize; + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/RobotType.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/RobotType.java new file mode 100644 index 0000000..ce64a75 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/RobotType.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import java.io.Serializable; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public final class RobotType implements Serializable { + private static final long serialVersionUID = 1L; + + private static final transient int + NONE_FLAG = 0, + JUNIOR_FLAG = 1, + STANDARD_FLAG = 2, + ADVANCED_FLAG = 4, + TEAM_FLAG = 8, + DROID_FLAG = 16, + INTERACTIVE_FLAG = 32, + PAINTING_FLAG = 64, + SENTRY_FLAG = 128; + + public static final transient RobotType INVALID = new RobotType(NONE_FLAG); + + private int typeFlags; + + public RobotType(int typeFlags) { // NO_UCD (use private - used by .NET plug-in) + this.typeFlags = typeFlags; + } + + public RobotType( + boolean isJuniorRobot, + boolean isStandardRobot, + boolean isInteractiveRobot, + boolean isPaintRobot, + boolean isAdvancedRobot, + boolean isTeamRobot, + boolean isDroid, + boolean isSentryRobot) { + + typeFlags = NONE_FLAG; + + if (isJuniorRobot) { + typeFlags |= JUNIOR_FLAG; + } + if (isStandardRobot) { + typeFlags |= STANDARD_FLAG; + } + if (isInteractiveRobot) { + typeFlags |= INTERACTIVE_FLAG; + } + if (isPaintRobot) { + typeFlags |= PAINTING_FLAG; + } + if (isAdvancedRobot) { + typeFlags |= ADVANCED_FLAG; + } + if (isTeamRobot) { + typeFlags |= TEAM_FLAG; + } + if (isDroid) { + typeFlags |= DROID_FLAG; + } + if (isSentryRobot) { + typeFlags |= SENTRY_FLAG; + } + } + + public int getTypeFlags() { + return typeFlags; + } + + public boolean isValid() { + return isJuniorRobot() || isStandardRobot() || isAdvancedRobot(); + } + + public boolean isJuniorRobot() { + return (typeFlags & JUNIOR_FLAG) != 0; + } + + public boolean isStandardRobot() { + return (typeFlags & STANDARD_FLAG) != 0; + } + + public boolean isInteractiveRobot() { + return (typeFlags & INTERACTIVE_FLAG) != 0; + } + + public boolean isPaintRobot() { + return (typeFlags & PAINTING_FLAG) != 0; + } + + public boolean isAdvancedRobot() { + return (typeFlags & ADVANCED_FLAG) != 0; + } + + public boolean isTeamRobot() { + return (typeFlags & TEAM_FLAG) != 0; + } + + public boolean isDroid() { + return (typeFlags & DROID_FLAG) != 0; + } + + public boolean isSentryRobot() { + return (typeFlags & SENTRY_FLAG) != 0; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + typeFlags; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + RobotType other = (RobotType) obj; + return (typeFlags == other.typeFlags); + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/TeamProperties.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/TeamProperties.java new file mode 100644 index 0000000..dcd74f9 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/repository/TeamProperties.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import java.net.URL; + + +/** + * Container for Team properties used in Team packages. + * + * @author Flemming N. Larsen (original) + */ +public class TeamProperties { + + private String members; + private String version; + private String author; + private String description; + private URL webPage; + + public String getMembers() { + return members; + } + + public void setMembers(String members) { + this.members = members; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public URL getWebPage() { + return webPage; + } + + public void setWebPage(URL webPage) { + this.webPage = webPage; + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/robotpaint/Graphics2DSerialized.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/robotpaint/Graphics2DSerialized.java new file mode 100644 index 0000000..8246511 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/robotpaint/Graphics2DSerialized.java @@ -0,0 +1,2340 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.robotpaint; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import net.sf.robocode.serialization.RbSerializer; + +import java.awt.*; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.*; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.text.AttributedCharacterIterator; +import java.text.CharacterIterator; +import java.util.Map; + +import javax.swing.UIManager; + + +/** + * @author Flemming N. Larsen (original) + * @author Pavel Savara (original) + */ +public class Graphics2DSerialized extends Graphics2D implements IGraphicsProxy { + + private static final int INITIAL_BUFFER_SIZE = 2 * 1024; + private static final int MAX_BUFFER_SIZE = 64 * 1024; + + private final Method[] methods = Method.class.getEnumConstants(); + + private enum Method { + TRANSLATE_INT, // translate(int, int) + SET_COLOR, // setColor(Color) + SET_PAINT_MODE, // setPaintMode() + SET_XOR_MODE, // setXORMode(Color) + SET_FONT, // setFont(Font) + CLIP_RECT, // clipRect(int, int, int, int) + SET_CLIP, // setClip(int, int, int, int) + SET_CLIP_SHAPE, // setClip(Shape) + COPY_AREA, // copyArea(int, int, int, int, int, int) + DRAW_LINE, // drawLine(int, int, int, int) + FILL_RECT, // fillRect(int, int, int, int) + DRAW_RECT, // drawRect(int, int, int, int) + CLEAR_RECT, // clearRect(int, int, int, int) + DRAW_ROUND_RECT, // drawRoundRect(int, int, int, int, int, int) + FILL_ROUND_RECT, // fillRoundRect(int, int, int, int, int, int) + DRAW_3D_RECT, // draw3DRect(int, int, int, int, boolean) + FILL_3D_RECT, // draw3DRect(int, int, int, int, boolean) + DRAW_OVAL, // drawOval(int, int, int, int) + FILL_OVAL, // fillOval(int, int, int, int) + DRAW_ARC, // drawArc(int, int, int, int, int, int) + FILL_ARC, // fillArc(int, int, int, int, int, int) + DRAW_POLYLINE, // drawPolyline(int[], int[], int) + DRAW_POLYGON, // drawPolygon(int[], int[], int) + FILL_POLYGON, // fillPolygon(int[], int[], int) + DRAW_STRING_INT, // drawString(String, int, int) + DRAW_STRING_ACI_INT, // drawString(AttributedCharacterIterator, int, int) + DRAW_CHARS, // drawChars(char[], int, int, int, int) + DRAW_BYTES, // drawBytes(byte[], int, int, int, int) + DRAW_IMAGE_1, // drawImage(Image, int, int, ImageObserver) + DRAW_IMAGE_2, // drawImage(Image, int, int, int, int, ImageObserver) + DRAW_IMAGE_3, // drawImage(Image, int, int, Color, ImageObserver) + DRAW_IMAGE_4, // drawImage(Image, int, int, int, int, Color, ImageObserver) + DRAW_IMAGE_5, // drawImage(Image, int, int, int, int, int, int, int, int, ImageObserver) + DRAW_IMAGE_6, // drawImage(Image, int, int, int, int, int, int, int, int, Color, ImageObserver) + DRAW_SHAPE, // draw(Shape) + DRAW_IMAGE_7, // drawImage(Image, AffineTransform, ImageObserver) + DRAW_IMAGE_8, // drawImage(BufferedImage, BufferedImageOp, int, int) + DRAW_RENDERED_IMAGE, // drawRenderedImage(RenderedImage, AffineTransform) + DRAW_RENDERABLE_IMAGE, // drawRenderableImage(RenderableImage, AffineTransform) + DRAW_STRING_FLOAT, // drawString(String, float, float) + DRAW_STRING_ACI_FLOAT, // drawString(AttributedCharacterIterator, float, float) + DRAW_GLYPH_VECTOR, // drawGlyphVector(GlyphVector gv, float x, float y) + FILL_SHAPE, // fill(Shape) + SET_COMPOSITE, // setComposite(Composite) + SET_PAINT, // setPaint(Paint) + SET_STROKE, // setStroke(Stroke) + SET_RENDERING_HINT, // setRenderingHint(Key, Object) + SET_RENDERING_HINTS, // setRenderingHints(Map) + ADD_RENDERING_HINTS, // addRenderingHints(Map) + TRANSLATE_DOUBLE, // translate(double, double) + ROTATE, // rotate(double) + ROTATE_XY, // rotate(double, double, double) + SCALE, // scale(double, double) + SHEAR, // shear(double, double) + TRANSFORM, // transform(AffineTransform) + SET_TRANSFORM, // setTransform(AffineTransform Tx) + SET_BACKGROUND, // setBackground(Color) + CLIP, // clip(Shape) + } + + // Needed for getTransform() + private transient AffineTransform transform = new AffineTransform(); + + // Needed for getComposite() + private transient Composite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER); + + // Needed for getPaint() + private transient Paint paint = Color.BLACK; + + // Needed for getStroke() + private transient Stroke stroke = new BasicStroke(); + + // Needed for getRenderingHint() and getRenderingHints() + private transient RenderingHints renderingHints; + + // Needed for getBackground() + private transient Color background = UIManager.getColor("Button.background"); + + // Needed for getClip() + private transient Shape clip; // is null initially + + // Needed for getColor() + private transient Color color = Color.BLACK; + + // Needed for getFont() + private transient Font font = new Font("Dialog", Font.PLAIN, 11); // used for robot labels + + // Flag indicating if this proxy has been initialized + private transient boolean isInitialized; + + // Flag indicating if painting is enabled + private transient boolean isPaintingEnabled; + + // Byte buffer that works as a stack of method calls to this proxy + private ByteBuffer calls; + + // Serializer for this proxy + private final RbSerializer serializer = new RbSerializer(); + + // FOR-DEBUG private Method lastRead; + // FOR-DEBUG private int lastPos; + + + // The one and only constructor + public Graphics2DSerialized() { + // Create a default RenderingHints object + renderingHints = new RenderingHints(null); + renderingHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT); + renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + renderingHints.put(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_OFF); + renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); + renderingHints.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT); + } + + // -------------------------------------------------------------------------- + // Overriding all methods from the extended Graphics class + // -------------------------------------------------------------------------- + + // Methods that should not be overridden or implemented: + // - finalize() + // - toString() + + @Override + public Graphics create() { + Graphics2DSerialized gfxProxyCopy = new Graphics2DSerialized(); + + gfxProxyCopy.calls = ByteBuffer.allocate(INITIAL_BUFFER_SIZE); + gfxProxyCopy.transform = transform; + gfxProxyCopy.composite = copyOf(composite); + gfxProxyCopy.paint = paint; + gfxProxyCopy.stroke = copyOf(stroke); + gfxProxyCopy.renderingHints = renderingHints; + gfxProxyCopy.background = copyOf(background); + gfxProxyCopy.clip = copyOf(clip); + gfxProxyCopy.color = copyOf(color); + gfxProxyCopy.font = font; + gfxProxyCopy.isInitialized = isInitialized; + + calls.put(calls); + + return gfxProxyCopy; + } + + @Override + public Graphics create(int x, int y, int width, int height) { + Graphics g = create(); + + g.translate(x, y); + g.setClip(0, 0, width, height); + + return g; + } + + @Override + public void translate(int x, int y) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.TRANSLATE_INT); + put(x); + put(y); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + translate(x, y); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getTransform() + this.transform.translate(x, y); + } + + @Override + public Color getColor() { + return color; + } + + @Override + public void setColor(Color c) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_COLOR); + put(c); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setColor(c); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getColor() + this.color = c; + } + + @Override + public void setPaintMode() { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_PAINT_MODE); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setPaintMode(); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void setXORMode(Color c1) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_XOR_MODE); + put(c1); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setXORMode(c1); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public Font getFont() { + return font; + } + + @Override + public void setFont(Font font) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_FONT); + put(font); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setFont(font); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getFont() + this.font = font; + } + + @Override + public FontMetrics getFontMetrics(Font f) { + return new FontMetricsByFont(f, getFontRenderContext()); + } + + @Override + public Rectangle getClipBounds() { + return clip.getBounds(); + } + + @Override + public void clipRect(int x, int y, int width, int height) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.CLIP_RECT); + put(x); + put(y); + put(width); + put(height); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + clipRect(x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getClip() + + Area clipArea = new Area(clip); + Area clipRectArea = new Area(new Rectangle(x, y, width, height)); + + clipArea.intersect(clipRectArea); + + this.clip = clipArea; + } + + @Override + public void setClip(int x, int y, int width, int height) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_CLIP); + put(x); + put(y); + put(width); + put(height); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setClip(x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getClip() + this.clip = new Rectangle(x, y, width, height); + } + + @Override + public Shape getClip() { + return clip; + } + + @Override + public void setClip(Shape clip) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_CLIP_SHAPE); + put(clip); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setClip(clip); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getClip() + this.clip = clip; + } + + @Override + public void copyArea(int x, int y, int width, int height, int dx, int dy) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.COPY_AREA); + put(x); + put(y); + put(width); + put(height); + put(dx); + put(dy); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + copyArea(x, y, width, height, dx, dy); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawLine(int x1, int y1, int x2, int y2) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_LINE); + put(x1); + put(y1); + put(x2); + put(y2); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawLine(x1, y1, x2, y2); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void fillRect(int x, int y, int width, int height) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.FILL_RECT); + put(x); + put(y); + put(width); + put(height); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + fillRect(x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawRect(int x, int y, int width, int height) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_RECT); + put(x); + put(y); + put(width); + put(height); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawRect(x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void clearRect(int x, int y, int width, int height) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.CLEAR_RECT); + put(x); + put(y); + put(width); + put(height); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + clearRect(x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_ROUND_RECT); + put(x); + put(y); + put(width); + put(height); + put(arcWidth); + put(arcHeight); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawRoundRect(x, y, width, height, arcWidth, arcHeight); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.FILL_ROUND_RECT); + put(x); + put(y); + put(width); + put(height); + put(arcWidth); + put(arcHeight); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + fillRoundRect(x, y, width, height, arcWidth, arcHeight); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void draw3DRect(int x, int y, int width, int height, boolean raised) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_3D_RECT); + put(x); + put(y); + put(width); + put(height); + put(raised); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + draw3DRect(x, y, width, height, raised); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void fill3DRect(int x, int y, int width, int height, boolean raised) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.FILL_3D_RECT); + put(x); + put(y); + put(width); + put(height); + put(raised); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + fill3DRect(x, y, width, height, raised); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawOval(int x, int y, int width, int height) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_OVAL); + put(x); + put(y); + put(width); + put(height); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawOval(x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void fillOval(int x, int y, int width, int height) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.FILL_OVAL); + put(x); + put(y); + put(width); + put(height); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + fillOval(x, y, width, height); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_ARC); + put(x); + put(y); + put(width); + put(height); + put(startAngle); + put(arcAngle); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawArc(x, y, width, height, startAngle, arcAngle); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.FILL_ARC); + put(x); + put(y); + put(width); + put(height); + put(startAngle); + put(arcAngle); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + fillArc(x, y, width, height, startAngle, arcAngle); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawPolyline(int[] xPoints, int[] yPoints, int npoints) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_POLYLINE); + put(xPoints); + put(yPoints); + put(npoints); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawPolyline(xPoints, yPoints, npoints); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawPolygon(int[] xPoints, int[] yPoints, int npoints) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_POLYGON); + put(xPoints); + put(yPoints); + put(npoints); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawPolygon(xPoints, yPoints, npoints); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawPolygon(Polygon p) { + if (isPaintingEnabled) { + drawPolygon(p.xpoints, p.ypoints, p.npoints); // Reuse sister method + } + } + + @Override + public void fillPolygon(int[] xPoints, int[] yPoints, int npoints) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.FILL_POLYGON); + put(xPoints); + put(yPoints); + put(npoints); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + fillPolygon(xPoints, yPoints, npoints); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void fillPolygon(Polygon p) { + if (isPaintingEnabled) { + fillPolygon(p.xpoints, p.ypoints, p.npoints); // Reuse sister method + } + } + + @Override + public void drawString(String str, int x, int y) { + if (str == null) { + throw new NullPointerException("str is null"); // According to the specification! + } + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_STRING_INT); + put(str); + put(x); + put(y); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawString(str, x, y); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawString(AttributedCharacterIterator iterator, int x, int y) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_STRING_ACI_INT); + put(iterator); + put(x); + put(y); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawString(iterator, x, y); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawChars(char[] data, int offset, int length, int x, int y) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_CHARS); + put(data); + put(offset); + put(length); + put(x); + put(y); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawChars(data, offset, length, x, y); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawBytes(byte[] data, int offset, int length, int x, int y) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_BYTES); + put(data); + put(offset); + put(length); + put(x); + put(y); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawBytes(data, offset, length, x, y); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public boolean drawImage(Image img, int x, int y, ImageObserver observer) { + if (isPaintingEnabled) { + notSupported(); + } + return false; // as if the image pixels are still changing (as the call is queued) + } + + @Override + public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { + if (isPaintingEnabled) { + notSupported(); + } + return false; // as if the image pixels are still changing (as the call is queued) + } + + @Override + public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) { + if (isPaintingEnabled) { + notSupported(); + } + return false; // as if the image pixels are still changing (as the call is queued) + } + + @Override + public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { + if (isPaintingEnabled) { + notSupported(); + } + return false; // as if the image pixels are still changing (as the call is queued) + } + + @Override + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, + ImageObserver observer) { + + if (isPaintingEnabled) { + notSupported(); + } + return false; // as if the image pixels are still changing (as the call is queued) + } + + @Override + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, + Color bgcolor, ImageObserver observer) { + + if (isPaintingEnabled) { + notSupported(); + } + return false; // as if the image pixels are still changing (as the call is queued) + } + + @Override + public void dispose() {// Ignored here + } + + @Override + @Deprecated + public Rectangle getClipRect() { + return getClipBounds(); // Must use getClipBounds() instead of this deprecated method + } + + @Override + public boolean hitClip(int x, int y, int width, int height) { + return (clip != null) && clip.intersects(x, y, width, height); + } + + @Override + public Rectangle getClipBounds(Rectangle r) { + Rectangle bounds = clip.getBounds(); + + r.setBounds(bounds); + return bounds; + } + + // -------------------------------------------------------------------------- + // Overriding all methods from the extended Graphics2D class + // -------------------------------------------------------------------------- + + @Override + public void draw(Shape s) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_SHAPE); + put(s); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + draw(s); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { + if (isPaintingEnabled) { + notSupported(); + } + return false; // as if the image is still being rendered (as the call is queued) + } + + @Override + public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { + if (isPaintingEnabled) { + notSupported(); + } + } + + @Override + public void drawRenderedImage(RenderedImage img, AffineTransform xform) {} + + @Override + public void drawRenderableImage(RenderableImage img, AffineTransform xform) { + if (isPaintingEnabled) { + notSupported(); + } + } + + @Override + public void drawString(String str, float x, float y) { + if (str == null) { + throw new NullPointerException("str is null"); // According to the specification! + } + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_STRING_FLOAT); + put(str); + put(x); + put(y); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawString(str, x, y); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawString(AttributedCharacterIterator iterator, float x, float y) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.DRAW_STRING_ACI_FLOAT); + put(iterator); + put(x); + put(y); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + drawString(iterator, x, y); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public void drawGlyphVector(GlyphVector gv, float x, float y) { + if (isPaintingEnabled) { + notSupported(); + } + } + + @Override + public void fill(Shape s) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.FILL_SHAPE); + put(s); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + fill(s); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + } + + @Override + public boolean hit(Rectangle rect, Shape s, boolean onStroke) { + if (onStroke && getStroke() != null) { + s = getStroke().createStrokedShape(s); + } + + if (getTransform() != null) { + s = getTransform().createTransformedShape(s); + } + + Area area = new Area(s); + + if (getClip() != null) { + area.intersect(new Area(getClip())); + } + + return area.intersects(rect); + } + + @Override + public GraphicsConfiguration getDeviceConfiguration() { + return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); + } + + @Override + public void setComposite(Composite comp) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_COMPOSITE); + put(comp); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setComposite(comp); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getComposite() + this.composite = comp; + } + + @Override + public void setPaint(Paint paint) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_PAINT); + put(paint); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setPaint(paint); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getPaint() + this.paint = paint; + } + + @Override + public void setStroke(Stroke s) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_STROKE); + put(s); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setStroke(s); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getStroke() + this.stroke = s; + } + + @Override + public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) { + // for getRenderingHint() and getRenderingHints() + this.renderingHints.put(hintKey, hintValue); + + if (isPaintingEnabled) { + notSupportedWarn(); + } + } + + @Override + public Object getRenderingHint(RenderingHints.Key hintKey) { + return renderingHints.get(hintKey); + } + + @Override + public void setRenderingHints(Map hints) { + // for getRenderingHint() and getRenderingHints() + this.renderingHints.clear(); // Needs to clear first + this.renderingHints.putAll(hints); // Only overrides existing keys + + if (isPaintingEnabled) { + notSupportedWarn(); + } + } + + @Override + public void addRenderingHints(Map hints) { + // for getRenderingHint() and getRenderingHints() + this.renderingHints.putAll(hints); + + if (isPaintingEnabled) { + notSupportedWarn(); + } + } + + @Override + public RenderingHints getRenderingHints() { + return renderingHints; + } + + @Override + public void translate(double tx, double ty) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.TRANSLATE_DOUBLE); + put(tx); + put(ty); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + translate(tx, ty); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getTransform() + transform.translate(tx, ty); + } + + @Override + public void rotate(double theta) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.ROTATE); + put(theta); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + rotate(theta); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getTransform() + transform.rotate(theta); + } + + @Override + public void rotate(double theta, double x, double y) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.ROTATE_XY); + put(theta); + put(x); + put(y); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + rotate(theta, x, y); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getTransform() + transform.rotate(theta, x, y); + } + + @Override + public void scale(double sx, double sy) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SCALE); + put(sx); + put(sy); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + scale(sx, sy); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getTransform() + transform.scale(sx, sy); + } + + @Override + public void shear(double shx, double shy) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SHEAR); + put(shx); + put(shy); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + shear(shx, shy); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getTransform() + transform.shear(shx, shy); + } + + @Override + public void transform(AffineTransform Tx) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.TRANSFORM); + put(Tx); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + transform(Tx); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getTransform() + transform.concatenate(Tx); + } + + @Override + public void setTransform(AffineTransform Tx) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_TRANSFORM); + put(Tx); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setTransform(Tx); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getTransform() + this.transform = Tx; + } + + @Override + public AffineTransform getTransform() { + return (AffineTransform) transform.clone(); + } + + @Override + public Paint getPaint() { + return paint; + } + + @Override + public Composite getComposite() { + return composite; + } + + @Override + public void setBackground(Color color) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.SET_BACKGROUND); + put(color); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + setBackground(color); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getBackground() + background = color; + } + + @Override + public Color getBackground() { + return background; + } + + @Override + public Stroke getStroke() { + return stroke; + } + + @Override + public void clip(Shape s) { + if (isPaintingEnabled) { + calls.mark(); // Mark for rollback + try { + put(Method.CLIP); + put(s); + } catch (BufferOverflowException e) { + if (recoverFromBufferOverflow()) { + clip(s); // Retry this method after reallocation + return; // Make sure we leave + } + } + } + + // for getClip() + if (s == null) { + this.clip = null; + } else { + Area shapeArea = new Area(s); + Area clipArea = new Area(clip); + + shapeArea.transform(transform); // transform by the current transform + clipArea.intersect(shapeArea); // intersect current clip by the transformed shape + + this.clip = clipArea; + } + } + + @Override + public FontRenderContext getFontRenderContext() { + RenderingHints hints = getRenderingHints(); + + if (hints == null) { + return new FontRenderContext(null, false, false); + } else { + boolean isAntiAliased = RenderingHints.VALUE_FRACTIONALMETRICS_ON.equals( + hints.get(RenderingHints.KEY_TEXT_ANTIALIASING)); + boolean usesFractionalMetrics = RenderingHints.VALUE_FRACTIONALMETRICS_ON.equals( + hints.get(RenderingHints.KEY_FRACTIONALMETRICS)); + + return new FontRenderContext(null, isAntiAliased, usesFractionalMetrics); + } + } + + // -------------------------------------------------------------------------- + // Processing of queued method calls to a Graphics2D object + // -------------------------------------------------------------------------- + + public void setPaintingEnabled(boolean enabled) { + if (enabled && !isPaintingEnabled) { + calls = ByteBuffer.allocate(INITIAL_BUFFER_SIZE); + calls.put(calls.order() == ByteOrder.BIG_ENDIAN ? (byte) 1 : (byte) 0); + } + isPaintingEnabled = enabled; + } + + public void processTo(Graphics2D g) { + if (!isInitialized) { + calls = ByteBuffer.allocate(INITIAL_BUFFER_SIZE); + + // Make sure the transform is not null + transform = g.getTransform(); + transform = transform == null ? new AffineTransform() : new AffineTransform(transform); + + color = copyOf(g.getColor()); + + font = g.getFont(); + + clip = copyOf(g.getClip()); + + composite = copyOf(g.getComposite()); + + paint = g.getPaint(); + + stroke = copyOf(g.getStroke()); + + renderingHints = (RenderingHints) g.getRenderingHints().clone(); + + background = copyOf(g.getBackground()); + + isInitialized = true; + } + + calls.flip(); + + while (calls.remaining() > 0) { + processQueuedCall(g); + } + } + + public void processTo(Graphics2D g, Object graphicsCalls) { + calls.clear(); + + calls.mark(); // Mark for rollback + try { + calls.put((byte[]) graphicsCalls); + } catch (BufferOverflowException e) { + calls.reset(); // Rollback buffer + if (reallocBuffer()) { + processTo(g, graphicsCalls); + return; // must exit here + } + calls.clear(); + } + + calls.flip(); + calls.order(calls.get() == 1 ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN); + + while (calls.remaining() > 0) { + try { + processQueuedCall(g); + } catch (Exception e) { + e.printStackTrace(); + // FOR-DEBUG } catch (Error e) { + // FOR-DEBUG calls.position(lastPos - 4); + } + } + } + + public byte[] readoutQueuedCalls() { + if (calls == null || calls.position() == 0) { + return null; + } + byte[] res = new byte[calls.position()]; + + calls.flip(); + calls.get(res); + + calls.clear(); + calls.put(calls.order() == ByteOrder.BIG_ENDIAN ? (byte) 1 : (byte) 0); + + return res; + } + + private void processQueuedCall(Graphics2D g) { + Method m = readMethod(); + + switch (m) { + case TRANSLATE_INT: + processTranslate_int(g); + break; + + case SET_COLOR: + processSetColor(g); + break; + + case SET_PAINT_MODE: + processSetPaintMode(g); + break; + + case SET_XOR_MODE: + processSetXORMode(g); + break; + + case SET_FONT: + processSetFont(g); + break; + + case CLIP_RECT: + processClipRect(g); + break; + + case SET_CLIP: + processSetClip(g); + break; + + case SET_CLIP_SHAPE: + processSetClip_Shape(g); + break; + + case COPY_AREA: + processCopyArea(g); + break; + + case DRAW_LINE: + processDrawLine(g); + break; + + case FILL_RECT: + processFillRect(g); + break; + + case DRAW_RECT: + processDrawRect(g); + break; + + case CLEAR_RECT: + processClearRect(g); + break; + + case DRAW_ROUND_RECT: + processDrawRoundRect(g); + break; + + case FILL_ROUND_RECT: + processFillRoundRect(g); + break; + + case DRAW_3D_RECT: + processDraw3DRect(g); + break; + + case FILL_3D_RECT: + processFill3DRect(g); + break; + + case DRAW_OVAL: + processDrawOval(g); + break; + + case FILL_OVAL: + processFillOval(g); + break; + + case DRAW_ARC: + processDrawArc(g); + break; + + case FILL_ARC: + processFillArc(g); + break; + + case DRAW_POLYLINE: + processDrawPolyline(g); + break; + + case DRAW_POLYGON: + processDrawPolygon(g); + break; + + case FILL_POLYGON: + processFillPolygon(g); + break; + + case DRAW_STRING_INT: + processDrawString_int(g); + break; + + case DRAW_STRING_ACI_INT: + processDrawString_ACIterator_int(g); + break; + + case DRAW_CHARS: + processDrawChars(g); + break; + + case DRAW_BYTES: + processDrawBytes(g); + break; + + case DRAW_SHAPE: + processDrawShape(g); + break; + + case DRAW_STRING_FLOAT: + processDrawString_float(g); + break; + + case DRAW_STRING_ACI_FLOAT: + processDrawString_ACIterator_float(g); + break; + + case FILL_SHAPE: + processFillShape(g); + break; + + case SET_COMPOSITE: + processSetComposite(g); + break; + + case SET_PAINT: + processSetPaint(g); + break; + + case SET_STROKE: + processSetStroke(g); + break; + + case TRANSLATE_DOUBLE: + processTranslate_double(g); + break; + + case ROTATE: + processRotate(g); + break; + + case ROTATE_XY: + processRotate_xy(g); + break; + + case SCALE: + processScale(g); + break; + + case SHEAR: + processShear(g); + break; + + case TRANSFORM: + processTransform(g); + break; + + case SET_TRANSFORM: + processSetTransform(g); + break; + + case SET_BACKGROUND: + processSetBackground(g); + break; + + case CLIP: + processClip(g); + break; + + case DRAW_GLYPH_VECTOR: + case DRAW_IMAGE_1: + case DRAW_IMAGE_2: + case DRAW_IMAGE_3: + case DRAW_IMAGE_4: + case DRAW_IMAGE_5: + case DRAW_IMAGE_6: + case DRAW_IMAGE_7: + case DRAW_IMAGE_8: + case DRAW_RENDERED_IMAGE: + case DRAW_RENDERABLE_IMAGE: + case SET_RENDERING_HINT: + case SET_RENDERING_HINTS: + case ADD_RENDERING_HINTS: + default: + notSupported(); + break; + } + } + + private void processTranslate_int(Graphics2D g) { + // translate(int, int) + g.translate(calls.getInt(), calls.getInt()); + } + + private void processSetColor(Graphics2D g) { + // setColor(Color) + g.setColor(readColor()); + } + + private void processSetPaintMode(Graphics2D g) { + // setPaintMode() + g.setPaintMode(); + } + + private void processSetXORMode(Graphics2D g) { + // setXORMode(Color) + g.setXORMode(readColor()); + } + + private void processSetFont(Graphics2D g) { + Font font = calls.get() == 0 + ? null + : new Font(serializer.deserializeString(calls), calls.getInt(), calls.getInt()); + + // setFont(Font) + g.setFont(font); + } + + private void processClipRect(Graphics2D g) { + // clipRect(int, int, int, int) + g.clipRect(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processSetClip(Graphics2D g) { + // setClip(int, int, int, int) + g.setClip(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processSetClip_Shape(Graphics2D g) { + // setClip(Shape) + g.setClip(readShape()); + } + + private void processCopyArea(Graphics2D g) { + // copyArea(int, int, int, int, int, int) + g.copyArea(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processDrawLine(Graphics2D g) { + // drawLine(int, int, int, int) + g.drawLine(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processFillRect(Graphics2D g) { + // fillRect(int, int, int, int) + g.fillRect(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processDrawRect(Graphics2D g) { + // drawRect(int, int, int, int) + g.drawRect(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processClearRect(Graphics2D g) { + // clearRect(int, int, int, int) + g.clearRect(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processDrawRoundRect(Graphics2D g) { + // drawRoundRect(int, int, int, int, int, int) + g.drawRoundRect(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processFillRoundRect(Graphics2D g) { + // fillRoundRect(int, int, int, int, int, int) + g.fillRoundRect(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processDraw3DRect(Graphics2D g) { + // draw3DRect(int, int, int, int, boolean) + g.draw3DRect(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), + serializer.deserializeBoolean(calls)); + } + + private void processFill3DRect(Graphics2D g) { + // fill3DRect(int, int, int, int, boolean) + g.fill3DRect(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), + serializer.deserializeBoolean(calls)); + } + + private void processDrawOval(Graphics2D g) { + // drawOval(int, int, int, int) + g.drawOval(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processFillOval(Graphics2D g) { + // fillOval(int, int, int, int) + g.fillOval(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processDrawArc(Graphics2D g) { + // drawArc(int, int, int, int, int, int) + g.drawArc(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processFillArc(Graphics2D g) { + // fillArc(int, int, int, int, int, int) + g.fillArc(calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processDrawPolyline(Graphics2D g) { + // drawPolyline(int[], int[], int) + g.drawPolyline(serializer.deserializeIntegers(calls), serializer.deserializeIntegers(calls), calls.getInt()); + } + + private void processDrawPolygon(Graphics2D g) { + // drawPolygon(int[], int[], int) + g.drawPolygon(serializer.deserializeIntegers(calls), serializer.deserializeIntegers(calls), calls.getInt()); + } + + private void processFillPolygon(Graphics2D g) { + // fillPolygon(int[], int[], int) + g.fillPolygon(serializer.deserializeIntegers(calls), serializer.deserializeIntegers(calls), calls.getInt()); + } + + private void processDrawString_int(Graphics2D g) { + // drawString(String, int, int) + g.drawString(serializer.deserializeString(calls), calls.getInt(), calls.getInt()); + } + + private void processDrawString_ACIterator_int(Graphics2D g) { + // drawString(String, int, int) + g.drawString(serializer.deserializeString(calls), calls.getInt(), calls.getInt()); + } + + private void processDrawChars(Graphics2D g) { + // drawBytes(char[], int, int, int, int) + g.drawChars(serializer.deserializeChars(calls), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processDrawBytes(Graphics2D g) { + // drawBytes(byte[], int, int, int, int) + g.drawBytes(serializer.deserializeBytes(calls), calls.getInt(), calls.getInt(), calls.getInt(), calls.getInt()); + } + + private void processDrawShape(Graphics2D g) { + // draw(Shape) + g.draw(readShape()); + } + + private void processDrawString_float(Graphics2D g) { + // drawString(String, float, float) + g.drawString(serializer.deserializeString(calls), calls.getFloat(), calls.getFloat()); + } + + private void processDrawString_ACIterator_float(Graphics2D g) { + // drawString(String, float, float) + g.drawString(serializer.deserializeString(calls), calls.getFloat(), calls.getFloat()); + } + + private void processFillShape(Graphics2D g) { + // fill(Shape) + g.fill(readShape()); + } + + private void processSetComposite(Graphics2D g) { + // setComposite(Composite) + g.setComposite(readComposite()); + } + + private void processSetPaint(Graphics2D g) { + // setPaint(Paint) + g.setPaint(readPaint()); + } + + private void processSetStroke(Graphics2D g) { + // setStroke(Stroke) + g.setStroke(readStroke()); + } + + private void processTranslate_double(Graphics2D g) { + // translate(double, double) + g.translate(calls.getDouble(), calls.getDouble()); + } + + private void processRotate(Graphics2D g) { + // rotate(double) + g.rotate(calls.getDouble()); + } + + private void processRotate_xy(Graphics2D g) { + // rotate(double) + g.rotate(calls.getDouble(), calls.getDouble(), calls.getDouble()); + } + + private void processScale(Graphics2D g) { + // scale(double, double) + g.scale(calls.getDouble(), calls.getDouble()); + } + + private void processShear(Graphics2D g) { + // shear(double, double) + g.shear(calls.getDouble(), calls.getDouble()); + } + + private void processTransform(Graphics2D g) { + // transform(AffineTransform) + g.transform(readAffineTransform()); + } + + private void processSetTransform(Graphics2D g) { + // setTransform(AffineTransform) + g.setTransform(readAffineTransform()); + } + + private void processSetBackground(Graphics2D g) { + // setBackground(Color) + g.setBackground(readColor()); + } + + private void processClip(Graphics2D g) { + // clip(Shape) + g.clip(readShape()); + } + + private Shape readShape() { + switch (calls.get()) { + case 0: + return null; + + case 1: + return new Arc2D.Double(calls.getDouble(), // x + calls.getDouble(), // y + calls.getDouble(), // width + calls.getDouble(), // height + calls.getDouble(), // angle start + calls.getDouble(), // angle extended + calls.getInt()); // arc type + + case 2: + return new Line2D.Double(calls.getDouble(), // x1 + calls.getDouble(), // y1 + calls.getDouble(), // x2 + calls.getDouble()); // y2 + + case 3: + return new Rectangle2D.Double(calls.getDouble(), // x + calls.getDouble(), // y + calls.getDouble(), // width + calls.getDouble()); // height + + case 4: + return new Ellipse2D.Double(calls.getDouble(), // x + calls.getDouble(), // y + calls.getDouble(), // width + calls.getDouble()); // height + + case 5: + GeneralPath path = new GeneralPath(); + + path.append(new DeserializePathIterator(), false); + return path; + } + notSupported(); + return null; + } + + /** + * Reallocates the calls buffer by replacing it with a new one with doubled capacity + * and copying the old one. + * + * @return {@code true} if the buffer was reallocated; + * {@code false} if the max. capacity has been reached meaning that the reallocation + * was not performed. + */ + private boolean reallocBuffer() { + int bufferSize; + + if (calls == null) { + // No buffer -> Use initial buffer size + bufferSize = INITIAL_BUFFER_SIZE; + } else { + // Otherwise, double up capacity + bufferSize = 2 * calls.capacity(); + } + + // Check if the max. buffer size has been reached + if (RobocodeProperties.isDebuggingOff() && bufferSize > MAX_BUFFER_SIZE) { + return false; // not reallocated! + } + + // Allocate new buffer + ByteBuffer newBuffer = ByteBuffer.allocate(bufferSize); + + if (calls != null) { + // Copy all bytes contained in the current buffer to the new buffer + + byte[] copiedBytes = new byte[calls.position()]; + + calls.clear(); + calls.get(copiedBytes); + + newBuffer.put(copiedBytes); + } + + // Switch to the new buffer + calls = newBuffer; + + return true; // buffer was reallocated + } + + private int unrecoveredBufferOverflowCount; + + private boolean recoverFromBufferOverflow() { + calls.reset(); // Rollback buffer + + boolean recovered = reallocBuffer(); + + if (!recovered) { + if (unrecoveredBufferOverflowCount++ == 1) { // Prevent spamming + System.out.println( + "SYSTEM: This robot is painting too much between actions.\n" + "SYSTEM: Max. buffer capacity (" + + MAX_BUFFER_SIZE + " bytes per turn) has been reached.\n" + + "SYSTEM: Last painting operations are being dropped.\n"); + } + } + return recovered; + } + + private class DeserializePathIterator implements PathIterator { + final int count; + int pos; + final int windingRule; + int[] type; + double[][] coords; + + public DeserializePathIterator() { + count = calls.getInt(); + pos = 0; + windingRule = calls.getInt(); + if (count > 0) { + type = new int[count]; + coords = new double[count][]; + for (int i = 0; i < count; i++) { + type[i] = calls.getInt(); + coords[i] = serializer.deserializeDoubles(calls); + } + } + } + + public int getWindingRule() { + return windingRule; + } + + public boolean isDone() { + return pos == count; + } + + public void next() { + pos++; + } + + public int currentSegment(float[] coords) { + for (int i = 0; i < coords.length; i++) { + coords[i] = (float) this.coords[pos][i]; + } + return type[pos]; + } + + public int currentSegment(double[] coords) { + System.arraycopy(this.coords[pos], 0, coords, 0, coords.length); + return type[pos]; + } + } + + private void put(Shape shape) { + if (shape == null) { + put((byte) 0); + } else if (shape instanceof Arc2D) { + put((byte) 1); + Arc2D arc = (Arc2D) shape; + + put(arc.getX()); + put(arc.getY()); + put(arc.getWidth()); + put(arc.getHeight()); + put(arc.getAngleStart()); + put(arc.getAngleExtent()); + put(arc.getArcType()); + } else if (shape instanceof Line2D) { + put((byte) 2); + Line2D line = (Line2D) shape; + + put(line.getX1()); + put(line.getY1()); + put(line.getX2()); + put(line.getY2()); + } else if (shape instanceof Rectangle2D) { + put((byte) 3); + Rectangle2D rect = (Rectangle2D) shape; + + put(rect.getX()); + put(rect.getY()); + put(rect.getWidth()); + put(rect.getHeight()); + } else if (shape instanceof Ellipse2D) { + put((byte) 4); + Ellipse2D elipse = (Ellipse2D) shape; + + put(elipse.getX()); + put(elipse.getY()); + put(elipse.getWidth()); + put(elipse.getHeight()); + } else { + put((byte) 5); + + double coords[] = new double[6]; + int count = 0; + + // count them first + PathIterator pi = shape.getPathIterator(null); + + while (!pi.isDone()) { + count++; + pi.next(); + } + put(count); + + // write them + pi = shape.getPathIterator(null); + put(pi.getWindingRule()); + while (!pi.isDone()) { + int type = pi.currentSegment(coords); + + put(type); + put(coords); + pi.next(); + } + } + } + + private Composite readComposite() { + switch (calls.get()) { + case 0: + return null; + + case 1: + return AlphaComposite.getInstance(calls.getInt()); + } + notSupported(); + return null; + } + + private void put(Composite comp) { + if (comp == null) { + put((byte) 0); + } else if (comp instanceof AlphaComposite) { + AlphaComposite composite = (AlphaComposite) comp; + + put((byte) 1); + put(composite.getRule()); + } else { + notSupported(); + } + } + + private Paint readPaint() { + switch (calls.get()) { + case 0: + return null; + + case 1: + return new Color(calls.getInt(), true); + } + notSupported(); + return null; + } + + private void put(Paint paint) { + if (paint == null) { + put((byte) 0); + } else if (paint instanceof Color) { + Color color = (Color) paint; + + put((byte) 1); + put(color.getRGB()); + } else { + notSupported(); + } + } + + private Stroke readStroke() { + switch (calls.get()) { + case 0: + return null; + + case 1: + return new BasicStroke(calls.getFloat(), calls.getInt(), calls.getInt(), calls.getFloat(), + serializer.deserializeFloats(calls), calls.getFloat()); + } + notSupported(); + return null; + } + + private void put(Stroke stroke) { + if (stroke == null) { + put((byte) 0); + } else if (stroke instanceof BasicStroke) { + BasicStroke bs = (BasicStroke) stroke; + + put((byte) 1); + put(bs.getLineWidth()); + put(bs.getEndCap()); + put(bs.getLineJoin()); + put(bs.getMiterLimit()); + put(bs.getDashArray()); + put(bs.getDashPhase()); + } else { + notSupported(); + } + } + + private AffineTransform readAffineTransform() { + switch (calls.get()) { + case 0: + return null; + + case 1: + return new AffineTransform(serializer.deserializeDoubles(calls)); + } + notSupported(); + return null; + } + + private void put(AffineTransform tx) { + if (tx == null) { + put((byte) 0); + } else { + double[] m = new double[6]; + + tx.getMatrix(m); + + put((byte) 1); + put(m); + put(tx.getType()); + } + } + + private Method readMethod() { + // FOR-DEBUG if (calls.getInt() != 0xBADF00D) { + // FOR-DEBUG calls.position(lastPos); + // FOR-DEBUG // throw new Error(); + // FOR-DEBUG } + // FOR-DEBUG lastPos = calls.position(); + Method m = methods[calls.get()]; + + // FOR-DEBUG if (calls.getInt() != 0xBADF00D) { + // FOR-DEBUG throw new Error(); + // FOR-DEBUG } + // FOR-DEBUG lastRead = m; + return m; + } + + private void put(Method m) { + // FOR-DEBUG calls.putInt(0xBADF00D); + calls.put((byte) m.ordinal()); + // FOR-DEBUG calls.putInt(0xBADF00D); + } + + private void put(AttributedCharacterIterator iterator) { + if (iterator == null) { + put((String) null); + } else { + StringBuilder sb = new StringBuilder(); + + for (char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) { + sb.append(c); + } + put(sb.toString()); + } + } + + private void put(String value) { + serializer.serialize(calls, value); + } + + private void put(boolean value) { + serializer.serialize(calls, value); + } + + private void put(byte value) { + calls.put(value); + } + + private void put(int value) { + calls.putInt(value); + } + + private void put(int[] values) { + serializer.serialize(calls, values); + } + + private void put(byte[] values) { + serializer.serialize(calls, values); + } + + private void put(char[] values) { + serializer.serialize(calls, values); + } + + private void put(double[] values) { + serializer.serialize(calls, values); + } + + private void put(float[] values) { + serializer.serialize(calls, values); + } + + private void put(double value) { + calls.putDouble(value); + } + + private void put(float value) { + calls.putFloat(value); + } + + private Color readColor() { + return calls.get() == 0 ? null : new Color(calls.getInt(), true); + } + + private void put(Color value) { + if (value == null) { + calls.put((byte) 0); + } else { + calls.put((byte) 1); + calls.putInt(value.getRGB()); + } + } + + private void put(Font font) { + if (font == null) { + calls.put((byte) 0); + } else { + calls.put((byte) 1); + serializer.serialize(calls, font.getFontName()); + calls.putInt(font.getStyle()); + calls.putInt(font.getSize()); + } + } + + // -------------------------------------------------------------------------- + // Copy + // -------------------------------------------------------------------------- + + private static Color copyOf(Color c) { + return (c != null) ? new Color(c.getRGB(), true) : null; + } + + private Shape copyOf(Shape s) { + return (s != null) ? new GeneralPath(s) : null; + } + + private Stroke copyOf(Stroke s) { + if (s == null) { + return null; + } + if (s instanceof BasicStroke) { + BasicStroke bs = (BasicStroke) s; + + return new BasicStroke(bs.getLineWidth(), bs.getEndCap(), bs.getLineJoin(), bs.getMiterLimit(), + bs.getDashArray(), bs.getDashPhase()); + } + throw new UnsupportedOperationException("The Stroke type '" + s.getClass().getName() + "' is not supported"); + } + + private Composite copyOf(Composite c) { + if (c == null) { + return null; + } + if (c instanceof AlphaComposite) { + AlphaComposite ac = (AlphaComposite) c; + + return AlphaComposite.getInstance(ac.getRule(), ac.getAlpha()); + } + throw new UnsupportedOperationException("The Composite type '" + c.getClass().getName() + "' is not supported"); + } + + private void notSupported() { + throw new UnsupportedOperationException("We are sorry. Operation is not supported in Robocode."); + } + + private void notSupportedWarn() { + Logger.printlnToRobotsConsole("SYSTEM: We are sorry. Operation is not supported in Robocode."); + } + + // -------------------------------------------------------------------------- + // Worker classes + // -------------------------------------------------------------------------- + + + /** + * Extended FontMetrics class which only purpose is to let us access its + * protected contructor taking a Font as input parameter. + * + * @author Flemming N. Larsen + */ + private class FontMetricsByFont extends FontMetrics { + static final long serialVersionUID = 1L; + + final FontRenderContext fontRenderContext; + + FontMetricsByFont(Font font, FontRenderContext frc) { + super(font); + fontRenderContext = frc; + } + + /** + * Bugfix [2791007] - FontMetrics StackOverflowError. + * More info here: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4257064 + */ + @Override + public int charsWidth(char[] data, int off, int len) { + if (font == null) { + return 0; + } + Rectangle2D bounds = font.getStringBounds(data, off, off + len, fontRenderContext); + + return (bounds != null) ? (int) (bounds.getWidth() + 0.5) : 0; + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/robotpaint/IGraphicsProxy.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/robotpaint/IGraphicsProxy.java new file mode 100644 index 0000000..89a1031 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/robotpaint/IGraphicsProxy.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.robotpaint; + + +import java.awt.*; + + +/** + * @author Pavel Savara (original) + */ +public interface IGraphicsProxy { + void setPaintingEnabled(boolean enabled); + void processTo(Graphics2D g, Object graphicsCalls); + + void processTo(Graphics2D g); + + Object readoutQueuedCalls(); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/IXmlSerializable.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/IXmlSerializable.java new file mode 100644 index 0000000..78330dd --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/IXmlSerializable.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.serialization; + + +import java.io.IOException; + + +/** + * @author Pavel Savara (original) + */ +public interface IXmlSerializable { + void writeXml(XmlWriter writer, SerializableOptions options) throws IOException; + + XmlReader.Element readXml(XmlReader reader); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/SerializableOptions.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/SerializableOptions.java new file mode 100644 index 0000000..9e3f9f8 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/SerializableOptions.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.serialization; + + +/** + * @author Pavel Savara (original) + */ +public class SerializableOptions { + public boolean skipExploded; + public boolean skipNames; + public boolean skipVersion; + public boolean skipDebug; + public boolean skipTotal; + public boolean trimPrecision; + public boolean shortAttributes; + + public SerializableOptions(SerializableOptions src) { + skipExploded = src.skipExploded; + skipNames = src.skipNames; + skipVersion = src.skipVersion; + skipDebug = src.skipDebug; + skipTotal = src.skipTotal; + trimPrecision = src.trimPrecision; + shortAttributes = src.shortAttributes; + } + + public SerializableOptions(boolean skipAllDetails) { + if (skipAllDetails) { + skipExploded = true; + skipNames = true; + skipVersion = true; + skipDebug = true; + skipTotal = true; + trimPrecision = true; + shortAttributes = true; + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/XmlReader.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/XmlReader.java new file mode 100644 index 0000000..6d0e453 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/XmlReader.java @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.serialization; + + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Stack; + + +/** + * @author Pavel Savara (original) + */ +public class XmlReader { + + private SAXParser parser; + + private final InputStream input; + private final Stack elements = new Stack(); + private final Stack items = new Stack(); + private final Stack> elementNames = new Stack>(); + private final Stack> attributeNames = new Stack>(); + private IXmlSerializable result; + private Map context = new HashMap(); + + private XmlReader(InputStream input) throws SAXException, ParserConfigurationException { + this.input = input; + SAXParserFactory factory = SAXParserFactory.newInstance(); + + parser = factory.newSAXParser(); + } + + private Object deserialize(IXmlSerializable prototype) throws IOException, SAXException { + elementNames.push(new HashMap()); + attributeNames.push(new HashMap()); + items.push(null); + elements.push(new ListElement() { + public IXmlSerializable read(XmlReader reader) { + return null; + } + + public void add(IXmlSerializable child) { + result = child; + } + + public void close() {} + }); + prototype.readXml(this); + parser.parse(input, new Handler(this)); + items.pop(); + elements.pop(); + elementNames.pop(); + attributeNames.pop(); + + return result; + } + + private class Handler extends DefaultHandler { + final XmlReader parent; + + public Handler(XmlReader parent) { + this.parent = parent; + } + + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + final Map names = XmlReader.this.elementNames.peek(); + final Element element = names == null ? null : names.get(qName); + + if (element != null) { + elements.push(element); + XmlReader.this.elementNames.push(new HashMap()); + attributeNames.push(new HashMap()); + final IXmlSerializable item = element.read(parent); + + item.readXml(parent); + for (int i = 0; i < attributes.getLength(); i++) { + Attribute attribute = attributeNames.peek().get(attributes.getQName(i)); + + if (attribute != null) { + attribute.read(attributes.getValue(i)); + } + } + items.push(item); + } else { + items.push(null); + elements.push(null); + XmlReader.this.elementNames.push(null); + attributeNames.push(null); + } + } + + public void endElement(String uri, String localName, String qName) throws SAXException { + elements.pop(); + final IXmlSerializable item = items.peek(); + final Element parentElement = elements.peek(); + + if (parentElement instanceof ListElement) { + ListElement le = (ListElement) parentElement; + + le.add(item); + } + items.pop(); + elementNames.pop(); + attributeNames.pop(); + final Map names = XmlReader.this.elementNames.peek(); + final Element element = names == null ? null : names.get(qName); + + if (element != null) { + if (element instanceof ElementClose) { + ElementClose ec = (ElementClose) element; + + ec.close(); + } + } + } + + } + + public Map getContext() { + return context; + } + + public Element expect(String name, Element element) { + elementNames.peek().put(name, element); + return element; + } + + public Element expect(String name, String altName, Element element) { + elementNames.peek().put(name, element); + elementNames.peek().put(altName, element); + return element; + } + + public Attribute expect(String name, Attribute attribute) { + attributeNames.peek().put(name, attribute); + return attribute; + } + + public Attribute expect(String name, String altName, Attribute attribute) { + attributeNames.peek().put(name, attribute); + attributeNames.peek().put(altName, attribute); + return attribute; + } + + public interface Element { + IXmlSerializable read(XmlReader reader); + } + + + public interface ElementClose extends Element { + void close(); + } + + + public interface ListElement extends ElementClose { + void add(IXmlSerializable child); + } + + + public interface Attribute { + void read(String value); + } + + public static Object deserialize(InputStream input, IXmlSerializable prototype) throws IOException { + try { + XmlReader xr = new XmlReader(input); + + return xr.deserialize(prototype); + } catch (SAXException e) { + throw new IOException(); + } catch (ParserConfigurationException e) { + throw new IOException(); + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/XmlWriter.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/XmlWriter.java new file mode 100644 index 0000000..bbddec2 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/serialization/XmlWriter.java @@ -0,0 +1,142 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.serialization; + + +import java.io.IOException; +import java.io.Writer; +import java.text.CharacterIterator; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.StringCharacterIterator; +import java.util.Locale; +import java.util.Stack; + + +/** + * @author Pavel Savara (original) + */ +public class XmlWriter { + private static final DecimalFormat decimalFormat = new DecimalFormat("#.####", new DecimalFormatSymbols(Locale.US)); + private final Writer writer; + private final Stack elements = new Stack(); + private boolean headClosed = true; + private boolean innerElement = false; + private boolean indent = true; + + public XmlWriter(Writer writer, boolean indent) { + this.writer = writer; + this.indent = indent; + } + + public void startDocument() throws IOException { + writer.write("\n"); + } + + public void startElement(String name) throws IOException { + closeHead(); + indent(elements.size()); + elements.push(name); + writer.write('<'); + writer.write(encode(name)); + headClosed = false; + innerElement = false; + } + + public void writeAttribute(String name, String value) throws IOException { + if (value != null) { + writer.write(' '); + writer.write(encode(name)); + writer.write("=\""); + writer.write(encode(value)); + writer.write('"'); + } + } + + public void writeAttribute(String name, boolean value) throws IOException { + writeAttribute(name, Boolean.toString(value)); + } + + public void writeAttribute(String name, long value) throws IOException { + writeAttribute(name, Long.toString(value)); + } + + public void writeAttribute(String name, double value, boolean trim) throws IOException { + if (trim) { + writeAttribute(name, decimalFormat.format(value)); + } else { + writeAttribute(name, Double.toString(value)); + } + } + + public void endElement() throws IOException { + String name = elements.pop(); + + if (innerElement || headClosed) { + closeHead(); + indent(elements.size()); + writer.write(""); + } else { + writer.write("/>"); + headClosed = true; + } + newline(); + innerElement = true; + } + + private void newline() throws IOException { + if (indent) { + writer.write("\n"); + } + } + + private void closeHead() throws IOException { + if (!headClosed) { + writer.write('>'); + newline(); + headClosed = true; + } + } + + private void indent(int level) throws IOException { + if (indent) { + for (int i = 0; i < level; i++) { + writer.write("\t"); + } + } + } + + private static String encode(String text) { + final StringBuilder result = new StringBuilder(); + final StringCharacterIterator iterator = new StringCharacterIterator(text); + char character = iterator.current(); + + while (character != CharacterIterator.DONE) { + if (character == '<') { + result.append("<"); + } else if (character == '>') { + result.append(">"); + } else if (character == '&') { + result.append("&"); + } else if (character == '\"') { + result.append("""); + } else if (character == '\n') { + result.append(" "); + } else { + // the char is not a special one + // add it to the result as is + result.append(character); + } + character = iterator.next(); + } + return result.toString(); + } + +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/ISettingsListener.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/ISettingsListener.java new file mode 100644 index 0000000..f779268 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/ISettingsListener.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.settings; + + +/** + * @author Pavel Savara (original) + */ +public interface ISettingsListener { + void settingChanged(String property); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/ISettingsManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/ISettingsManager.java new file mode 100644 index 0000000..db43abb --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/ISettingsManager.java @@ -0,0 +1,317 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.settings; + + +import java.awt.*; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Collection; +import java.util.Date; + + +/** + * @author Pavel Savara (original) + */ +public interface ISettingsManager { + void saveProperties(); + + boolean getOptionsViewRobotNames(); + + void setOptionsViewRobotNames(boolean optionsViewRobotNames); + + boolean getOptionsViewScanArcs(); + + void setOptionsViewScanArcs(boolean optionsViewScanArcs); + + boolean getOptionsViewRobotEnergy(); + + void setOptionsViewRobotEnergy(boolean optionsViewRobotEnergy); + + boolean getOptionsViewGround(); + + void setOptionsViewGround(boolean optionsViewGround); + + boolean getOptionsViewTPS(); + + void setOptionsViewTPS(boolean optionsViewTPS); + + boolean getOptionsViewFPS(); + + void setOptionsViewFPS(boolean optionsViewFPS); + + boolean getOptionsViewExplosions(); + + void setOptionsViewExplosions(boolean optionsViewExplosions); + + boolean getOptionsViewExplosionDebris(); + + void setOptionsViewExplosionDebris(boolean optionsViewExplosionDebris); + + boolean getOptionsViewSentryBorder(); + + void setOptionsViewSentryBorder(boolean optionsViewSentryBorder); + + boolean getOptionsViewPreventSpeedupWhenMinimized(); + + void setOptionsViewPreventSpeedupWhenMinimized(boolean preventSpeedupWhenMinimized); + + int getOptionsRenderingAntialiasing(); + + void setOptionsRenderingAntialiasing(int optionsRenderingAntialiasing); + + int getOptionsRenderingTextAntialiasing(); + + void setOptionsRenderingTextAntialiasing(int optionsRenderingTextAntialiasing); + + int getOptionsRenderingMethod(); + + void setOptionsRenderingMethod(int optionsRenderingMethod); + + RenderingHints getRenderingHints(); + + int getOptionsRenderingNoBuffers(); + + void setOptionsRenderingNoBuffers(int optionsRenderingNoBuffers); + + boolean getOptionsRenderingBufferImages(); + + void setOptionsRenderingBufferImages(boolean optionsRenderingBufferImages); + + boolean getOptionsRenderingForceBulletColor(); + + void setOptionsRenderingForceBulletColor(boolean optionsRenderingForceBulletColor); + + int getOptionsBattleDesiredTPS(); + + void setOptionsBattleDesiredTPS(int optionsBattleDesiredTPS); + + boolean getOptionsSoundEnableSound(); + + void setOptionsSoundEnableSound(boolean optionsSoundEnableSound); + + boolean getOptionsSoundEnableGunshot(); + + void setOptionsSoundEnableGunshot(boolean optionsSoundEnableGunshot); + + boolean getOptionsSoundEnableBulletHit(); + + void setOptionsSoundEnableBulletHit(boolean optionsSoundEnableBulletHit); + + boolean getOptionsSoundEnableRobotDeath(); + + void setOptionsSoundEnableRobotDeath(boolean optionsSoundEnableRobotDeath); + + boolean getOptionsSoundEnableWallCollision(); + + void setOptionsSoundEnableWallCollision(boolean optionsSoundEnableWallCollision); + + boolean getOptionsSoundEnableRobotCollision(); + + void setOptionsSoundEnableRobotCollision(boolean optionsSoundEnableRobotCollision); + + boolean getOptionsSoundEnableMixerVolume(); + + void setOptionsSoundMixer(String optionsSoundMixer); + + String getOptionsSoundMixer(); + + void setOptionsSoundEnableMixerVolume(boolean optionsSoundEnableMixerVolume); + + boolean getOptionsSoundEnableMixerPan(); + + void setOptionsSoundEnableMixerPan(boolean optionsSoundEnableMixerPan); + + boolean getOptionsTeamShowTeamRobots(); + + void setOptionsTeamShowTeamRobots(boolean optionsTeamShowTeamRobots); + + String getFileThemeMusic(); + + String getFileBackgroundMusic(); + + String getFileEndOfBattleMusic(); + + String getFileGunshotSfx(); + + String getBulletHitsRobotSfx(); + + String getBulletHitsBulletSfx(); + + String getRobotDeathSfx(); + + String getRobotCollisionSfx(); + + String getWallCollisionSfx(); + + Date getVersionChecked(); + + void setVersionChecked(Date versionChecked); + + long getRobotFilesystemQuota(); + + void setRobotFilesystemQuota(long robotFilesystemQuota); + + long getConsoleQuota(); + + void setConsoleQuota(long consoleQuota); + + long getCpuConstant(); + + void setCpuConstant(long cpuConstant); + + Collection getOptionsDevelopmentPaths(); + + void setOptionsDevelopmentPaths(Collection paths); + + Collection getOptionsExcludedDevelopmentPaths(); + + void setOptionsExcludedDevelopmentPaths(Collection excludedPaths); + + Collection getOptionsEnabledDevelopmentPaths(); + + boolean getOptionsCommonShowResults(); + + boolean getOptionsCommonDontHideRankings(); + + void setOptionsCommonDontHideRankings(boolean dontHide); + + void setOptionsCommonAppendWhenSavingResults(boolean enable); + + boolean getOptionsCommonAppendWhenSavingResults(); + + void setOptionsCommonShowResults(boolean enable); + + boolean getOptionsCommonEnableReplayRecording(); + + boolean getOptionsCommonEnableAutoRecording(); + + boolean getOptionsCommonAutoRecordingXML(); + + void setOptionsCommonEnableReplayRecording(boolean enable); + + void setOptionsCommonEnableAutoRecording(boolean enable); + + void setOptionsCommonEnableAutoRecordingXML(boolean enable); + + void setOptionsCommonNotifyAboutNewBetaVersions(boolean enable); + + boolean getOptionsCommonNotifyAboutNewBetaVersions(); + + int getBattleDefaultBattlefieldWidth(); + + void setBattleDefaultBattlefieldWidth(int battlefieldWidth); + + int getBattleDefaultBattlefieldHeight(); + + void setBattleDefaultBattlefieldHeight(int battlefieldHeight); + + double getBattleDefaultGunCoolingRate(); + + void setBattleDefaultGunCoolingRate(double gunCoolingRate); + + long getBattleDefaultInactivityTime(); + + void setBattleDefaultInactivityTime(long inactivityTime); + + int getBattleDefaultSentryBorderSize(); + + void setBattleDefaultSentryBorderSize(int sentryBorderSize); + + boolean getBattleDefaultHideEnemyNames(); + + void setBattleDefaultHideEnemyNames(boolean hideEnemyNames); + + int getBattleDefaultNumberOfRounds(); + + void setBattleDefaultNumberOfRounds(int numberOfRounds); + + void store(FileOutputStream out, String desc) throws IOException; + + void load(FileInputStream in) throws IOException; + + String getLastRunVersion(); + + void setLastRunVersion(String lastRunVersion); + + void addPropertyListener(ISettingsListener listener); + + void removePropertyListener(ISettingsListener propertyListener); + + public final static String + OPTIONS_VIEW_ROBOTNAMES = "robocode.options.view.robotNames", + OPTIONS_VIEW_SCANARCS = "robocode.options.view.scanArcs", + OPTIONS_VIEW_ROBOTENERGY = "robocode.options.view.robotEnergy", + OPTIONS_VIEW_GROUND = "robocode.options.view.ground", + OPTIONS_VIEW_TPS = "robocode.options.view.TPS", + OPTIONS_VIEW_FPS = "robocode.options.view.FPS", + OPTIONS_VIEW_EXPLOSIONS = "robocode.options.view.explosions", + OPTIONS_VIEW_EXPLOSION_DEBRIS = "robocode.options.view.explosionDebris", + OPTIONS_VIEW_SENTRY_BORDER = "robocode.options.view.sentryBorder", + + OPTIONS_BATTLE_DESIREDTPS = "robocode.options.battle.desiredTPS", + + OPTIONS_VIEW_PREVENT_SPEEDUP_WHEN_MINIMIZED = "robocode.options.view.preventSpeedupWhenMinimized", + + OPTIONS_RENDERING_ANTIALIASING = "robocode.options.rendering.antialiasing", + OPTIONS_RENDERING_TEXT_ANTIALIASING = "robocode.options.rendering.text.antialiasing", + OPTIONS_RENDERING_METHOD = "robocode.options.rendering.method", + OPTIONS_RENDERING_NO_BUFFERS = "robocode.options.rendering.noBuffers", + OPTIONS_RENDERING_BUFFER_IMAGES = "robocode.options.rendering.bufferImages", + OPTIONS_RENDERING_FORCE_BULLET_COLOR = "robocode.options.rendering.forceBulletColor", + + OPTIONS_SOUND_ENABLESOUND = "robocode.options.sound.enableSound", + OPTIONS_SOUND_ENABLEGUNSHOT = "robocode.options.sound.enableGunshot", + OPTIONS_SOUND_ENABLEBULLETHIT = "robocode.options.sound.enableBulletHit", + OPTIONS_SOUND_ENABLEROBOTDEATH = "robocode.options.sound.enableRobotDeath", + OPTIONS_SOUND_ENABLEWALLCOLLISION = "robocode.options.sound.enableWallCollision", + OPTIONS_SOUND_ENABLEROBOTCOLLISION = "robocode.options.sound.enableRobotCollision", + + OPTIONS_SOUND_MIXER = "robocode.options.sound.mixer", + OPTIONS_SOUND_ENABLEMIXERVOLUME = "robocode.options.sound.enableMixerVolume", + OPTIONS_SOUND_ENABLEMIXERPAN = "robocode.options.sound.enableMixerPan", + + OPTIONS_COMMON_NOTIFY_ABOUT_NEW_BETA_VERSIONS = "robocode.options.common.notifyAboutNewBetaVersions", + OPTIONS_COMMON_SHOW_RESULTS = "robocode.options.common.showResults", + OPTIONS_COMMON_DONT_HIDE_RANKINGS = "robocode.options.common.dontHideRankings", + OPTIONS_COMMON_APPEND_WHEN_SAVING_RESULTS = "robocode.options.common.appendWhenSavingResults", + OPTIONS_COMMON_ENABLE_REPLAY_RECORDING = "robocode.options.common.enableReplayRecording", + OPTIONS_COMMON_ENABLE_AUTO_RECORDING = "robocode.options.common.enableAutoRecording", + OPTIONS_COMMON_AUTO_RECORDING_XML = "robocode.options.common.autoRecordingXML", + + OPTIONS_TEAM_SHOWTEAMROBOTS = "robocode.options.team.showTeamRobots", + + OPTIONS_DEVELOPMENT_PATH = "robocode.options.development.path", + OPTIONS_DEVELOPMENT_PATH_EXCLUDED = "robocode.options.development.path.excluded", + + FILE_THEME_MUSIC = "robocode.file.music.theme", + FILE_BACKGROUND_MUSIC = "robocode.file.music.background", + FILE_END_OF_BATTLE_MUSIC = "robocode.file.music.endOfBattle", + + FILE_GUNSHOT_SFX = "robocode.file.sfx.gunshot", + FILE_ROBOT_COLLISION_SFX = "robocode.file.sfx.robotCollision", + FILE_WALL_COLLISION_SFX = "robocode.file.sfx.wallCollision", + FILE_ROBOT_DEATH_SFX = "robocode.file.sfx.robotDeath", + FILE_BULLET_HITS_ROBOT_SFX = "robocode.file.sfx.bulletHitsRobot", + FILE_BULLET_HITS_BULLET_SFX = "robocode.file.sfx.bulletHitsBullet", + + VERSIONCHECKED = "robocode.versionchecked", + ROBOT_FILESYSTEM_QUOTA = "robocode.robot.filesystem.quota", + CONSOLE_QUOTA = "robocode.console.quota", + CPU_CONSTANT = "robocode.cpu.constant", + LAST_RUN_VERSION = "robocode.version.lastrun", + + BATTLE_DEFAULT_BATTLEFIELD_WIDTH = "robocode.battle.default.battlefieldWidth", + BATTLE_DEFAULT_BATTLEFIELD_HEIGHT = "robocode.battle.default.battlefieldHeight", + BATTLE_DEFAULT_NUMBER_OF_ROUNDS = "robocode.battle.default.numberOfBattles", + BATTLE_DEFAULT_GUN_COOLING_RATE = "robocode.battle.default.gunCoolingRate", + BATTLE_DEFAULT_INACTIVITY_TIME = "robocode.battle.default.inactivityTime", + BATTLE_DEFAULT_SENTRY_BORDER_SIZE = "robocode.battle.default.sentryBorderSize", + BATTLE_DEFAULT_HIDE_ENEMY_NAMES = "robocode.battle.default.hideEnemyNames"; +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/SettingsManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/SettingsManager.java new file mode 100644 index 0000000..39c4a9c --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/settings/SettingsManager.java @@ -0,0 +1,896 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.settings; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import static net.sf.robocode.io.Logger.logError; + +import java.awt.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.List; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Nathaniel Troutman (contributor) + */ +// TODO ZAMO, refactor, split by modules +public class SettingsManager implements ISettingsManager { + // Default SFX files + private final static String + DEFAULT_FILE_GUNSHOT_SFX = "/net/sf/robocode/sound/sounds/zap.wav", + DEFAULT_FILE_ROBOT_COLLISION_SFX = "/net/sf/robocode/sound/sounds/13831_adcbicycle_22.wav", + DEFAULT_FILE_WALL_COLLISION_SFX = DEFAULT_FILE_ROBOT_COLLISION_SFX, + DEFAULT_FILE_ROBOT_DEATH_SFX = "/net/sf/robocode/sound/sounds/explode.wav", + DEFAULT_FILE_BULLET_HITS_ROBOT_SFX = "/net/sf/robocode/sound/sounds/shellhit.wav", + DEFAULT_FILE_BULLET_HITS_BULLET_SFX = DEFAULT_FILE_BULLET_HITS_ROBOT_SFX; + + // View Options (Arena) + private boolean + optionsViewRobotEnergy = true, + optionsViewRobotNames = true, + optionsViewScanArcs = false, + optionsViewExplosions = true, + optionsViewGround = true, + optionsViewExplosionDebris = true, + optionsViewSentryBorder = false; + + // View Options (Turns Per Second) + private boolean + optionsViewTPS = true, + optionsViewFPS = true; + + // Prevent speedup when view is minimized + private boolean + optionsViewPreventSpeedupWhenMinimized = false; + + // Rendering Options + private int + optionsRenderingAntialiasing = 0, // 0 = default, 1 = on, 2 = off + optionsRenderingTextAntialiasing = 0, // 0 = default, 1 = on, 2 = off + optionsRenderingMethod = 0, // 0 = default, 1 = speed, 2 = quality + optionsRenderingNoBuffers = 2, // 1 = single buffering, 2 = double buffering, 3 = triple buffering + optionsBattleDesiredTPS = 30; + + private boolean + optionsRenderingBufferImages = true, + optionsRenderingForceBulletColor = false; + + // Sound Options (Sound Effects) + private boolean + optionsSoundEnableSound = false, + optionsSoundEnableGunshot = true, + optionsSoundEnableBulletHit = true, + optionsSoundEnableRobotDeath = true, + optionsSoundEnableWallCollision = true, + optionsSoundEnableRobotCollision = true; + + // Sound Options (Mixer) + private String optionsSoundMixer = "DirectAudioDevice"; + private boolean + optionsSoundEnableMixerVolume = true, + optionsSoundEnableMixerPan = true; + + // Development Options + private Collection + optionsDevelopmentPaths = new HashSet(), + optionsExcludedDevelopmentPaths = new HashSet(); + + // Common Options + private boolean + optionsCommonNotifyAboutNewBetaVersions = false, + optionsCommonShowResults = true, + optionsCommonAppendWhenSavingResults = true, + optionsCommonDontHideRankings = true, + optionsCommonEnableAutoRecording = false, + optionsCommonAutoRecordingXML = false, + optionsCommonEnableReplayRecording = false; + + // Team Options + private boolean optionsTeamShowTeamRobots = false; + + // Music files + private String + fileThemeMusic = "", + fileBackgroundMusic = "", + fileEndOfBattleMusic = ""; + + // SFX files + private String + fileGunshotSfx = DEFAULT_FILE_GUNSHOT_SFX, + fileRobotCollisionSfx = DEFAULT_FILE_ROBOT_COLLISION_SFX, + fileWallCollisionSfx = DEFAULT_FILE_WALL_COLLISION_SFX, + fileRobotDeathSfx = DEFAULT_FILE_ROBOT_DEATH_SFX, + fileBulletHitsRobotSfx = DEFAULT_FILE_BULLET_HITS_ROBOT_SFX, + fileBulletHitsBulletSfx = DEFAULT_FILE_BULLET_HITS_BULLET_SFX; + + // Robocode internals + private String lastRunVersion = ""; + private Date versionChecked; + private long robotFilesystemQuota = 200000; + private long consoleQuota = 8192; + private long cpuConstant = -1; + + // Battle default settings + private int battleDefaultBattlefieldWidth = 800; + private int battleDefaultBattlefieldHeight = 600; + private double battleDefaultGunCoolingRate = 0.1; + private long battleDefaultInactivityTime = 450; + private int battleDefaultSentryBorderSize = 100; + private boolean battleDefaultHideEnemyNames = false; + private int battleDefaultNumberOfRounds = 10; + + private final Properties props = new SortedProperties(); + + private final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy H:mm:ss"); + + private final RenderingHints renderingHints = new RenderingHints(new HashMap()); + + private final List listeners = new ArrayList(); + + public SettingsManager() { + FileInputStream in = null; + try { + in = new FileInputStream(FileUtil.getRobocodeConfigFile()); + this.load(in); + } catch (FileNotFoundException e) { + logError("No " + FileUtil.getRobocodeConfigFile().getName() + ". Using defaults."); + } catch (IOException e) { + logError("Error while reading " + FileUtil.getRobocodeConfigFile().getName() + ": " + e); + } finally { + if (in != null) { + // noinspection EmptyCatchBlock + try { + in.close(); + } catch (IOException e) {} + } + } + } + + public void saveProperties() { + FileOutputStream out = null; + try { + out = new FileOutputStream(FileUtil.getRobocodeConfigFile()); + this.store(out, "Robocode Properties"); + } catch (IOException e) { + Logger.logError(e); + } finally { + if (out != null) { + // noinspection EmptyCatchBlock + try { + out.close(); + } catch (IOException e) {} + } + } + } + + public boolean getOptionsViewRobotNames() { + return optionsViewRobotNames; + } + + public void setOptionsViewRobotNames(boolean optionsViewRobotNames) { + this.optionsViewRobotNames = optionsViewRobotNames; + props.setProperty(OPTIONS_VIEW_ROBOTNAMES, "" + optionsViewRobotNames); + } + + public boolean getOptionsViewScanArcs() { + return optionsViewScanArcs; + } + + public void setOptionsViewScanArcs(boolean optionsViewScanArcs) { + this.optionsViewScanArcs = optionsViewScanArcs; + props.setProperty(OPTIONS_VIEW_SCANARCS, "" + optionsViewScanArcs); + } + + public boolean getOptionsViewRobotEnergy() { + return optionsViewRobotEnergy; + } + + public void setOptionsViewRobotEnergy(boolean optionsViewRobotEnergy) { + this.optionsViewRobotEnergy = optionsViewRobotEnergy; + props.setProperty(OPTIONS_VIEW_ROBOTENERGY, "" + optionsViewRobotEnergy); + } + + public boolean getOptionsViewGround() { + return optionsViewGround; + } + + public void setOptionsViewGround(boolean optionsViewGround) { + this.optionsViewGround = optionsViewGround; + props.setProperty(OPTIONS_VIEW_GROUND, "" + optionsViewGround); + } + + public boolean getOptionsViewTPS() { + return optionsViewTPS; + } + + public void setOptionsViewTPS(boolean optionsViewTPS) { + this.optionsViewTPS = optionsViewTPS; + props.setProperty(OPTIONS_VIEW_TPS, "" + optionsViewTPS); + } + + public boolean getOptionsViewFPS() { + return optionsViewFPS; + } + + public void setOptionsViewFPS(boolean optionsViewFPS) { + this.optionsViewFPS = optionsViewFPS; + props.setProperty(OPTIONS_VIEW_FPS, "" + optionsViewFPS); + } + + public boolean getOptionsViewExplosions() { + return optionsViewExplosions; + } + + public void setOptionsViewExplosions(boolean optionsViewExplosions) { + this.optionsViewExplosions = optionsViewExplosions; + props.setProperty(OPTIONS_VIEW_EXPLOSIONS, "" + optionsViewExplosions); + } + + public boolean getOptionsViewExplosionDebris() { + return optionsViewExplosionDebris; + } + + public void setOptionsViewExplosionDebris(boolean optionsViewExplosionDebris) { + this.optionsViewExplosionDebris = optionsViewExplosionDebris; + props.setProperty(OPTIONS_VIEW_EXPLOSION_DEBRIS, "" + optionsViewExplosionDebris); + } + + public boolean getOptionsViewPreventSpeedupWhenMinimized() { + return optionsViewPreventSpeedupWhenMinimized; + } + + public void setOptionsViewPreventSpeedupWhenMinimized(boolean preventSpeedupWhenMinimized) { + this.optionsViewPreventSpeedupWhenMinimized = preventSpeedupWhenMinimized; + props.setProperty(OPTIONS_VIEW_PREVENT_SPEEDUP_WHEN_MINIMIZED, "" + preventSpeedupWhenMinimized); + } + + public boolean getOptionsViewSentryBorder() { + return optionsViewSentryBorder; + } + + public void setOptionsViewSentryBorder(boolean optionsViewSentryBorder) { + this.optionsViewSentryBorder = optionsViewSentryBorder; + props.setProperty(OPTIONS_VIEW_SENTRY_BORDER, "" + optionsViewSentryBorder); + } + + public int getOptionsRenderingAntialiasing() { + return optionsRenderingAntialiasing; + } + + public void setOptionsRenderingAntialiasing(int optionsRenderingAntialiasing) { + this.optionsRenderingAntialiasing = optionsRenderingAntialiasing; + props.setProperty(OPTIONS_RENDERING_ANTIALIASING, "" + optionsRenderingAntialiasing); + + Object value; + + switch (optionsRenderingAntialiasing) { + case 1: + value = RenderingHints.VALUE_ANTIALIAS_ON; + break; + + case 2: + value = RenderingHints.VALUE_ANTIALIAS_OFF; + break; + + case 0: + default: + value = RenderingHints.VALUE_ANTIALIAS_DEFAULT; + } + renderingHints.put(RenderingHints.KEY_ANTIALIASING, value); + } + + public int getOptionsRenderingTextAntialiasing() { + return optionsRenderingTextAntialiasing; + } + + public void setOptionsRenderingTextAntialiasing(int optionsRenderingTextAntialiasing) { + this.optionsRenderingTextAntialiasing = optionsRenderingTextAntialiasing; + props.setProperty(OPTIONS_RENDERING_TEXT_ANTIALIASING, "" + optionsRenderingTextAntialiasing); + + Object value; + + switch (optionsRenderingTextAntialiasing) { + case 1: + value = RenderingHints.VALUE_TEXT_ANTIALIAS_ON; + break; + + case 2: + value = RenderingHints.VALUE_TEXT_ANTIALIAS_OFF; + break; + + case 0: + default: + value = RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT; + } + renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, value); + } + + public int getOptionsRenderingMethod() { + return optionsRenderingMethod; + } + + public void setOptionsRenderingMethod(int optionsRenderingMethod) { + this.optionsRenderingMethod = optionsRenderingMethod; + props.setProperty(OPTIONS_RENDERING_METHOD, "" + optionsRenderingMethod); + + Object value; + + switch (optionsRenderingMethod) { + case 1: + value = RenderingHints.VALUE_RENDER_QUALITY; + break; + + case 2: + value = RenderingHints.VALUE_RENDER_SPEED; + break; + + case 0: + default: + value = RenderingHints.VALUE_RENDER_DEFAULT; + } + renderingHints.put(RenderingHints.KEY_RENDERING, value); + } + + public RenderingHints getRenderingHints() { + return renderingHints; + } + + public int getOptionsRenderingNoBuffers() { + return optionsRenderingNoBuffers; + } + + public void setOptionsRenderingNoBuffers(int optionsRenderingNoBuffers) { + this.optionsRenderingNoBuffers = optionsRenderingNoBuffers; + props.setProperty(OPTIONS_RENDERING_NO_BUFFERS, "" + optionsRenderingNoBuffers); + } + + public boolean getOptionsRenderingBufferImages() { + return optionsRenderingBufferImages; + } + + public void setOptionsRenderingBufferImages(boolean optionsRenderingBufferImages) { + this.optionsRenderingBufferImages = optionsRenderingBufferImages; + props.setProperty(OPTIONS_RENDERING_BUFFER_IMAGES, "" + optionsRenderingBufferImages); + } + + public boolean getOptionsRenderingForceBulletColor() { + return optionsRenderingForceBulletColor; + } + + public void setOptionsRenderingForceBulletColor(boolean optionsRenderingForceBulletColor) { + this.optionsRenderingForceBulletColor = optionsRenderingForceBulletColor; + props.setProperty(OPTIONS_RENDERING_FORCE_BULLET_COLOR, "" + optionsRenderingForceBulletColor); + } + + public int getOptionsBattleDesiredTPS() { + return optionsBattleDesiredTPS; + } + + public void setOptionsBattleDesiredTPS(int optionsBattleDesiredTPS) { + this.optionsBattleDesiredTPS = optionsBattleDesiredTPS; + props.setProperty(OPTIONS_BATTLE_DESIREDTPS, "" + optionsBattleDesiredTPS); + } + + public boolean getOptionsSoundEnableSound() { + return optionsSoundEnableSound; + } + + public void setOptionsSoundEnableSound(boolean optionsSoundEnableSound) { + this.optionsSoundEnableSound = optionsSoundEnableSound; + props.setProperty(OPTIONS_SOUND_ENABLESOUND, "" + optionsSoundEnableSound); + } + + public boolean getOptionsSoundEnableGunshot() { + return optionsSoundEnableGunshot; + } + + public void setOptionsSoundEnableGunshot(boolean optionsSoundEnableGunshot) { + this.optionsSoundEnableGunshot = optionsSoundEnableGunshot; + props.setProperty(OPTIONS_SOUND_ENABLEGUNSHOT, "" + optionsSoundEnableGunshot); + } + + public boolean getOptionsSoundEnableBulletHit() { + return optionsSoundEnableBulletHit; + } + + public void setOptionsSoundEnableBulletHit(boolean optionsSoundEnableBulletHit) { + this.optionsSoundEnableBulletHit = optionsSoundEnableBulletHit; + props.setProperty(OPTIONS_SOUND_ENABLEBULLETHIT, "" + optionsSoundEnableBulletHit); + } + + public boolean getOptionsSoundEnableRobotDeath() { + return optionsSoundEnableRobotDeath; + } + + public void setOptionsSoundEnableRobotDeath(boolean optionsSoundEnableRobotDeath) { + this.optionsSoundEnableRobotDeath = optionsSoundEnableRobotDeath; + props.setProperty(OPTIONS_SOUND_ENABLEROBOTDEATH, "" + optionsSoundEnableRobotDeath); + } + + public boolean getOptionsSoundEnableWallCollision() { + return optionsSoundEnableWallCollision; + } + + public void setOptionsSoundEnableWallCollision(boolean optionsSoundEnableWallCollision) { + this.optionsSoundEnableWallCollision = optionsSoundEnableWallCollision; + props.setProperty(OPTIONS_SOUND_ENABLEWALLCOLLISION, "" + optionsSoundEnableWallCollision); + } + + public boolean getOptionsSoundEnableRobotCollision() { + return optionsSoundEnableRobotCollision; + } + + public void setOptionsSoundEnableRobotCollision(boolean optionsSoundEnableRobotCollision) { + this.optionsSoundEnableRobotCollision = optionsSoundEnableRobotCollision; + props.setProperty(OPTIONS_SOUND_ENABLEROBOTCOLLISION, "" + optionsSoundEnableRobotCollision); + } + + public boolean getOptionsSoundEnableMixerVolume() { + return optionsSoundEnableMixerVolume; + } + + public void setOptionsSoundMixer(String optionsSoundMixer) { + this.optionsSoundMixer = optionsSoundMixer; + props.setProperty(OPTIONS_SOUND_MIXER, optionsSoundMixer); + } + + public String getOptionsSoundMixer() { + return optionsSoundMixer; + } + + public void setOptionsSoundEnableMixerVolume(boolean optionsSoundEnableMixerVolume) { + this.optionsSoundEnableMixerVolume = optionsSoundEnableMixerVolume; + props.setProperty(OPTIONS_SOUND_ENABLEMIXERVOLUME, "" + optionsSoundEnableMixerVolume); + } + + public boolean getOptionsSoundEnableMixerPan() { + return optionsSoundEnableMixerPan; + } + + public void setOptionsSoundEnableMixerPan(boolean optionsSoundEnableMixerPan) { + this.optionsSoundEnableMixerPan = optionsSoundEnableMixerPan; + props.setProperty(OPTIONS_SOUND_ENABLEMIXERPAN, "" + optionsSoundEnableMixerPan); + } + + public boolean getOptionsTeamShowTeamRobots() { + return optionsTeamShowTeamRobots; + } + + public void setOptionsTeamShowTeamRobots(boolean optionsTeamShowTeamRobots) { + this.optionsTeamShowTeamRobots = optionsTeamShowTeamRobots; + props.setProperty(OPTIONS_TEAM_SHOWTEAMROBOTS, "" + optionsTeamShowTeamRobots); + } + + public String getFileThemeMusic() { + return fileThemeMusic; + } + + public String getFileBackgroundMusic() { + return fileBackgroundMusic; + } + + public String getFileEndOfBattleMusic() { + return fileEndOfBattleMusic; + } + + public String getFileGunshotSfx() { + return fileGunshotSfx; + } + + public String getBulletHitsRobotSfx() { + return fileBulletHitsRobotSfx; + } + + public String getBulletHitsBulletSfx() { + return fileBulletHitsBulletSfx; + } + + public String getRobotDeathSfx() { + return fileRobotDeathSfx; + } + + public String getRobotCollisionSfx() { + return fileRobotCollisionSfx; + } + + public String getWallCollisionSfx() { + return fileWallCollisionSfx; + } + + public Date getVersionChecked() { + return (versionChecked != null) ? (Date) versionChecked.clone() : null; + } + + public void setVersionChecked(Date versionChecked) { + this.versionChecked = (versionChecked != null) ? (Date) versionChecked.clone() : null; + props.setProperty(VERSIONCHECKED, dateFormat.format(new Date())); + } + + public long getRobotFilesystemQuota() { + return robotFilesystemQuota; + } + + public void setRobotFilesystemQuota(long robotFilesystemQuota) { + this.robotFilesystemQuota = robotFilesystemQuota; + props.setProperty(ROBOT_FILESYSTEM_QUOTA, "" + robotFilesystemQuota); + } + + public long getConsoleQuota() { + return consoleQuota; + } + + public void setConsoleQuota(long consoleQuota) { + this.consoleQuota = consoleQuota; + props.setProperty(CONSOLE_QUOTA, "" + consoleQuota); + } + + public long getCpuConstant() { + return cpuConstant; + } + + public void setCpuConstant(long cpuConstant) { + this.cpuConstant = cpuConstant; + props.setProperty(CPU_CONSTANT, "" + cpuConstant); + } + + public Collection getOptionsDevelopmentPaths() { + return new HashSet(optionsDevelopmentPaths); + } + + public void setOptionsDevelopmentPaths(Collection paths) { + this.optionsDevelopmentPaths = new HashSet(paths); + + props.setProperty(OPTIONS_DEVELOPMENT_PATH, toCommaSeparatedString(paths)); + } + + public Collection getOptionsExcludedDevelopmentPaths() { + return new HashSet(optionsExcludedDevelopmentPaths); + } + + public void setOptionsExcludedDevelopmentPaths(Collection paths) { + this.optionsExcludedDevelopmentPaths = new HashSet(paths); + + props.setProperty(OPTIONS_DEVELOPMENT_PATH_EXCLUDED, toCommaSeparatedString(paths)); + } + + public Collection getOptionsEnabledDevelopmentPaths() { + Collection paths = getOptionsDevelopmentPaths(); + + paths.removeAll(getOptionsExcludedDevelopmentPaths()); + return paths; + } + + public boolean getOptionsCommonShowResults() { + return optionsCommonShowResults; + } + + public void setOptionsCommonAppendWhenSavingResults(boolean enable) { + this.optionsCommonAppendWhenSavingResults = enable; + props.setProperty(OPTIONS_COMMON_APPEND_WHEN_SAVING_RESULTS, "" + enable); + } + + public boolean getOptionsCommonAppendWhenSavingResults() { + return optionsCommonAppendWhenSavingResults; + } + + public void setOptionsCommonShowResults(boolean enable) { + this.optionsCommonShowResults = enable; + props.setProperty(OPTIONS_COMMON_SHOW_RESULTS, "" + enable); + } + + public boolean getOptionsCommonDontHideRankings() { + return optionsCommonDontHideRankings; + } + + public void setOptionsCommonDontHideRankings(boolean enable) { + this.optionsCommonDontHideRankings = enable; + props.setProperty(OPTIONS_COMMON_DONT_HIDE_RANKINGS, "" + enable); + } + + public boolean getOptionsCommonEnableReplayRecording() { + return optionsCommonEnableReplayRecording; + } + + public void setOptionsCommonEnableReplayRecording(boolean enable) { + this.optionsCommonEnableReplayRecording = enable; + props.setProperty(OPTIONS_COMMON_ENABLE_REPLAY_RECORDING, "" + enable); + } + + public boolean getOptionsCommonEnableAutoRecording() { + return optionsCommonEnableAutoRecording; + } + + public boolean getOptionsCommonAutoRecordingXML() { + return optionsCommonAutoRecordingXML; + } + + public void setOptionsCommonEnableAutoRecording(boolean enable) { + this.optionsCommonEnableAutoRecording = enable; + props.setProperty(OPTIONS_COMMON_ENABLE_AUTO_RECORDING, "" + enable); + } + + public void setOptionsCommonEnableAutoRecordingXML(boolean enable) { + this.optionsCommonAutoRecordingXML = enable; + props.setProperty(OPTIONS_COMMON_AUTO_RECORDING_XML, "" + enable); + } + + public void setOptionsCommonNotifyAboutNewBetaVersions(boolean enable) { + this.optionsCommonNotifyAboutNewBetaVersions = enable; + props.setProperty(OPTIONS_COMMON_NOTIFY_ABOUT_NEW_BETA_VERSIONS, "" + enable); + } + + public boolean getOptionsCommonNotifyAboutNewBetaVersions() { + return optionsCommonNotifyAboutNewBetaVersions; + } + + public int getBattleDefaultBattlefieldWidth() { + return battleDefaultBattlefieldWidth; + } + + public void setBattleDefaultBattlefieldWidth(int battlefieldWidth) { + this.battleDefaultBattlefieldWidth = Math.max(400, battlefieldWidth); + props.setProperty(BATTLE_DEFAULT_BATTLEFIELD_WIDTH, "" + this.battleDefaultBattlefieldWidth); + } + + public int getBattleDefaultBattlefieldHeight() { + return battleDefaultBattlefieldHeight; + } + + public void setBattleDefaultBattlefieldHeight(int battlefieldHeight) { + this.battleDefaultBattlefieldHeight = Math.max(400, battlefieldHeight); + props.setProperty(BATTLE_DEFAULT_BATTLEFIELD_HEIGHT, "" + this.battleDefaultBattlefieldHeight); + } + + public double getBattleDefaultGunCoolingRate() { + return battleDefaultGunCoolingRate; + } + + public void setBattleDefaultGunCoolingRate(double gunCoolingRate) { + this.battleDefaultGunCoolingRate = Math.max(0.1, gunCoolingRate); + props.setProperty(BATTLE_DEFAULT_GUN_COOLING_RATE, "" + this.battleDefaultGunCoolingRate); + } + + public long getBattleDefaultInactivityTime() { + return battleDefaultInactivityTime; + } + + public void setBattleDefaultInactivityTime(long inactivityTime) { + this.battleDefaultInactivityTime = Math.max(0, inactivityTime); + props.setProperty(BATTLE_DEFAULT_INACTIVITY_TIME, "" + this.battleDefaultInactivityTime); + } + + public int getBattleDefaultSentryBorderSize() { + return battleDefaultSentryBorderSize; + } + + public void setBattleDefaultSentryBorderSize(int sentryBorderSize) { + this.battleDefaultSentryBorderSize = sentryBorderSize; + props.setProperty(BATTLE_DEFAULT_SENTRY_BORDER_SIZE, "" + this.battleDefaultSentryBorderSize); + } + + public boolean getBattleDefaultHideEnemyNames() { + return battleDefaultHideEnemyNames; + } + + public void setBattleDefaultHideEnemyNames(boolean hideEnemyNames) { + this.battleDefaultHideEnemyNames = hideEnemyNames; + props.setProperty(BATTLE_DEFAULT_HIDE_ENEMY_NAMES, "" + this.battleDefaultHideEnemyNames); + } + + public int getBattleDefaultNumberOfRounds() { + return battleDefaultNumberOfRounds; + } + + public void setBattleDefaultNumberOfRounds(int numberOfRounds) { + this.battleDefaultNumberOfRounds = Math.max(1, numberOfRounds); + props.setProperty(BATTLE_DEFAULT_NUMBER_OF_ROUNDS, "" + this.battleDefaultNumberOfRounds); + } + + public void store(FileOutputStream out, String desc) throws IOException { + props.store(out, desc); + } + + public void load(FileInputStream in) throws IOException { + props.load(in); + + optionsViewRobotNames = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_ROBOTNAMES, "true")); + optionsViewScanArcs = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_SCANARCS, "false")); + optionsViewRobotEnergy = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_ROBOTENERGY, "true")); + optionsViewGround = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_GROUND, "true")); + optionsViewTPS = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_TPS, "true")); + optionsViewFPS = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_FPS, "true")); + optionsViewExplosions = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_EXPLOSIONS, "true")); + optionsViewExplosionDebris = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_EXPLOSION_DEBRIS, "true")); + optionsViewSentryBorder = Boolean.valueOf(props.getProperty(OPTIONS_VIEW_SENTRY_BORDER, "false")); + optionsViewPreventSpeedupWhenMinimized = Boolean.valueOf( + props.getProperty(OPTIONS_VIEW_PREVENT_SPEEDUP_WHEN_MINIMIZED, "false")); + + optionsBattleDesiredTPS = Integer.parseInt(props.getProperty(OPTIONS_BATTLE_DESIREDTPS, "30")); + + // set methods are used here in order to set the rendering hints, which must be rebuild + setOptionsRenderingAntialiasing(Integer.parseInt(props.getProperty(OPTIONS_RENDERING_ANTIALIASING, "0"))); + setOptionsRenderingTextAntialiasing( + Integer.parseInt(props.getProperty(OPTIONS_RENDERING_TEXT_ANTIALIASING, "0"))); + setOptionsRenderingMethod(Integer.parseInt(props.getProperty(OPTIONS_RENDERING_METHOD, "0"))); + optionsRenderingNoBuffers = Integer.parseInt(props.getProperty(OPTIONS_RENDERING_NO_BUFFERS, "2")); + optionsRenderingBufferImages = Boolean.valueOf(props.getProperty(OPTIONS_RENDERING_BUFFER_IMAGES, "true")); + optionsRenderingForceBulletColor = Boolean.valueOf( + props.getProperty(OPTIONS_RENDERING_FORCE_BULLET_COLOR, "false")); + + optionsSoundEnableSound = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLESOUND, "false")); + optionsSoundEnableGunshot = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEGUNSHOT, "true")); + optionsSoundEnableBulletHit = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEBULLETHIT, "true")); + optionsSoundEnableRobotDeath = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEROBOTDEATH, "true")); + optionsSoundEnableRobotCollision = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEROBOTCOLLISION, "true")); + optionsSoundEnableWallCollision = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEWALLCOLLISION, "true")); + + optionsSoundMixer = props.getProperty(OPTIONS_SOUND_MIXER, "DirectAudioDevice"); + optionsSoundEnableMixerVolume = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEMIXERVOLUME, "true")); + optionsSoundEnableMixerPan = Boolean.valueOf(props.getProperty(OPTIONS_SOUND_ENABLEMIXERPAN, "true")); + + optionsDevelopmentPaths = fromCommaSeparatedString(props.getProperty(OPTIONS_DEVELOPMENT_PATH, "")); + optionsExcludedDevelopmentPaths = fromCommaSeparatedString( + props.getProperty(OPTIONS_DEVELOPMENT_PATH_EXCLUDED, "")); + + optionsCommonNotifyAboutNewBetaVersions = Boolean.valueOf( + props.getProperty(OPTIONS_COMMON_NOTIFY_ABOUT_NEW_BETA_VERSIONS, "false")); + optionsCommonShowResults = Boolean.valueOf(props.getProperty(OPTIONS_COMMON_SHOW_RESULTS, "true")); + optionsCommonAppendWhenSavingResults = Boolean.valueOf( + props.getProperty(OPTIONS_COMMON_APPEND_WHEN_SAVING_RESULTS, "true")); + optionsCommonDontHideRankings = Boolean.valueOf(props.getProperty(OPTIONS_COMMON_DONT_HIDE_RANKINGS, "true")); + optionsCommonEnableReplayRecording = Boolean.valueOf( + props.getProperty(OPTIONS_COMMON_ENABLE_REPLAY_RECORDING, "false")); + optionsCommonEnableAutoRecording = Boolean.valueOf( + props.getProperty(OPTIONS_COMMON_ENABLE_AUTO_RECORDING, "false")); + optionsCommonAutoRecordingXML = Boolean.valueOf(props.getProperty(OPTIONS_COMMON_AUTO_RECORDING_XML, "false")); + + optionsTeamShowTeamRobots = Boolean.valueOf(props.getProperty(OPTIONS_TEAM_SHOWTEAMROBOTS, "false")); + + fileThemeMusic = props.getProperty(FILE_THEME_MUSIC); + fileBackgroundMusic = props.getProperty(FILE_BACKGROUND_MUSIC); + fileEndOfBattleMusic = props.getProperty(FILE_END_OF_BATTLE_MUSIC); + + fileGunshotSfx = props.getProperty(FILE_GUNSHOT_SFX, DEFAULT_FILE_GUNSHOT_SFX); + fileRobotCollisionSfx = props.getProperty(FILE_ROBOT_COLLISION_SFX, DEFAULT_FILE_ROBOT_COLLISION_SFX); + fileWallCollisionSfx = props.getProperty(FILE_WALL_COLLISION_SFX, DEFAULT_FILE_WALL_COLLISION_SFX); + fileRobotDeathSfx = props.getProperty(FILE_ROBOT_DEATH_SFX, DEFAULT_FILE_ROBOT_DEATH_SFX); + fileBulletHitsRobotSfx = props.getProperty(FILE_BULLET_HITS_ROBOT_SFX, DEFAULT_FILE_BULLET_HITS_ROBOT_SFX); + fileBulletHitsBulletSfx = props.getProperty(FILE_BULLET_HITS_BULLET_SFX, DEFAULT_FILE_BULLET_HITS_BULLET_SFX); + + lastRunVersion = props.getProperty(LAST_RUN_VERSION, ""); + + props.remove("robocode.cpu.constant.1000"); + + try { + versionChecked = dateFormat.parse(props.getProperty(VERSIONCHECKED)); + } catch (Exception e) { + Logger.logMessage("Initializing version check date."); + setVersionChecked(new Date()); + } + + battleDefaultBattlefieldWidth = Integer.parseInt(props.getProperty(BATTLE_DEFAULT_BATTLEFIELD_WIDTH, "800")); + battleDefaultBattlefieldHeight = Integer.parseInt(props.getProperty(BATTLE_DEFAULT_BATTLEFIELD_HEIGHT, "600")); + battleDefaultGunCoolingRate = Double.parseDouble(props.getProperty(BATTLE_DEFAULT_GUN_COOLING_RATE, "0.1")); + battleDefaultInactivityTime = Long.parseLong(props.getProperty(BATTLE_DEFAULT_INACTIVITY_TIME, "450")); + battleDefaultHideEnemyNames = Boolean.parseBoolean(props.getProperty(BATTLE_DEFAULT_HIDE_ENEMY_NAMES, "false")); + battleDefaultNumberOfRounds = Integer.parseInt(props.getProperty(BATTLE_DEFAULT_NUMBER_OF_ROUNDS, "10")); + + robotFilesystemQuota = Long.parseLong(props.getProperty(ROBOT_FILESYSTEM_QUOTA, "" + 200000)); + consoleQuota = Long.parseLong(props.getProperty(CONSOLE_QUOTA, "8192")); + cpuConstant = Long.parseLong(props.getProperty(CPU_CONSTANT, "-1")); + } + + public String getLastRunVersion() { + return lastRunVersion; + } + + public void setLastRunVersion(String lastRunVersion) { + this.lastRunVersion = lastRunVersion; + props.setProperty(LAST_RUN_VERSION, "" + lastRunVersion); + } + + public void addPropertyListener(ISettingsListener listener) { + listeners.add(listener); + } + + public void removePropertyListener(ISettingsListener propertyListener) { + listeners.remove(propertyListener); + } + + private void notifyPropertyChanged(String name) { + for (ISettingsListener listener : listeners) { + try { + listener.settingChanged(name); + } catch (Exception e) { + Logger.logError(e); + } + } + } + + /** + * Returns a comma-separated string from a collection of strings. + */ + private static String toCommaSeparatedString(Collection strings) { + if (strings == null || strings.size() == 0) { + return ""; + } + StringBuilder sb = new StringBuilder(); + + for (String s : strings) { + sb.append(s).append(','); + } + String line = sb.toString(); + + return line.substring(0, line.length() - 1); + } + + /** + * Returns a collection of strings from a comma-separated string. + */ + private static Collection fromCommaSeparatedString(String line) { + if (line == null || line.trim().length() == 0) { + return new HashSet(); + } + Set set = new HashSet(); + String splitExpr = File.pathSeparatorChar == ':' ? "[,:]+" : "[,;]+"; + String[] strings = line.split(splitExpr); + + for (String s : strings) { + set.add(s); + } + return set; + } + + /** + * Sorted properties used for sorting the keys for the properties file. + * + * @author Flemming N. Larsen + */ + private class SortedProperties extends Properties { + private static final long serialVersionUID = 1L; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public Enumeration keys() { + Enumeration keysEnum = super.keys(); + + Vector keyList = new Vector(); + + while (keysEnum.hasMoreElements()) { + keyList.add((String) keysEnum.nextElement()); + } + + Collections.sort(keyList); + + // noinspection RedundantCast + return (Enumeration) keyList.elements(); + } + + @Override + public synchronized Object setProperty(String key, String value) { + final String old = super.getProperty(key, null); + boolean notify = (old == null && value != null) || (old != null && !old.equals(value)); + final Object res = super.setProperty(key, value); + + if (notify) { + notifyPropertyChanged(key); + } + return res; + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/sound/ISoundManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/sound/ISoundManager.java new file mode 100644 index 0000000..691a57f --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/sound/ISoundManager.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.sound; + + +/** + * @author Pavel Savara (original) + */ +public interface ISoundManager { + void setEnableSound(boolean enable); + + void playThemeMusic(); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/ui/IWindowManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/ui/IWindowManager.java new file mode 100644 index 0000000..80be36a --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/ui/IWindowManager.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import net.sf.robocode.gui.IWindowManagerBase; +import robocode.control.events.IBattleListener; +import robocode.control.snapshot.ITurnSnapshot; + +import javax.swing.*; + + +/** + * @author Pavel Savara (original) + */ +public interface IWindowManager extends IWindowManagerBase { + void init(); + + void setEnableGUI(boolean enable); + + boolean isGUIEnabled(); + + boolean isSlave(); + + boolean isShowResultsEnabled(); + + boolean isIconified(); + + void setSlave(boolean slave); + + void showRobocodeFrame(boolean visible, boolean iconified); + + void showSplashScreen(); + + void cleanup(); + + JFrame getRobocodeFrame(); + + void setBusyPointer(boolean enabled); + + void setStatus(String s); + + ITurnSnapshot getLastSnapshot(); + + void addBattleListener(IBattleListener listener); + + void removeBattleListener(IBattleListener listener); + + void runIntroBattle(); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/util/AlphanumericComparator.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/util/AlphanumericComparator.java new file mode 100644 index 0000000..0bace67 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/util/AlphanumericComparator.java @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.util; + + +import java.util.Comparator; + +import static java.lang.Character.isDigit; + + +/** + * This is a comparator used for comparing two alphanumeric strings. + * Normally strings are sorted one character at a time, meaning that e.g. "1.22" comes before "1.3". + * However, with alphanumeric sorting, "1.3" comes before "1.22", as 3 is lesser than 22. + * This comparator also others letter in this order "A", "a", "B", "b" instead of the normal character + * order "A", "B", "a", "b". + * + * Example of usage: + *
+ *    String[] strings = new String[] { "1.22", "1.3", "A", "B", "a", "b" };
+ *
+ *    Arrays.sort(strings, new AlphanumericComparator());
+ *	
+ *    for (String s : strings) {
+ *        System.out.println(s);
+ *    }
+ * 
+ * + * @author Flemming N. Larsen + */ +public class AlphanumericComparator implements Comparator, java.io.Serializable { + + private static final long serialVersionUID = 1L; + + /** + * Compares two alphanumeric strings. + * + * @param str1 the first string to be compared. + * @param str2 the second string to be compared. + * @return a negative integer, zero, or a positive integer as the first string is less than, equal to, or greater + * than the second. + */ + public int compare(final String str1, final String str2) { + + // Checks against null strings + if (str1 == null) { + return (str2 == null) ? 0 : 1; + } + if (str2 == null) { + return -1; + } + if (str1.equals(str2)) { + return 0; + } + + // Main loop where we keep read tokens from both input strings until the tokens differ + + String tok1; + int result = 0; + + for (int index = 0;; index += tok1.length()) { + tok1 = readToken(str1, index); + + result = compareTokens(tok1, readToken(str2, index)); + if (result != 0) { + return result; + } + } + } + + /** + * Reads a token from the specified input string from a start index. + * + * @param input the input string. + * @param startIndex the start index of the token to read. + * @return the read token or null if there is no token could be read. + */ + private static String readToken(final String input, final int startIndex) { + + // Return null if the input string is null or the startIndex is out of bounds + if (input == null || startIndex >= input.length()) { + return null; + } + + int index = startIndex + 1; + + // Check if the next token is numeric or not + if (isDigit(input.charAt(startIndex))) { + // Handle numeric token, which contains only digits in one continuous sequence + for (; index < input.length() && isDigit(input.charAt(index)); index++) { + ; + } + } else { + // Handle all other tokens that does not contain any digits + for (; index < input.length() && !isDigit(input.charAt(index)); index++) { + ; + } + } + + // Return our token + return input.substring(startIndex, index); + } + + /** + * Compares two tokens. + * + * @param tok1 the first token to be compared. + * @param tok2 the second token to be compared. + * @return a negative integer, zero, or a positive integer as the first token is less than, equal to, or greater + * than the second. + */ + private static int compareTokens(final String tok1, final String tok2) { + + // Checks against null strings + if (tok1 == null) { + return (tok2 == null) ? 0 : 1; + } + if (tok2 == null) { + return -1; + } + + // A numeric token has precedence over other tokens + + if (isDigit(tok1.charAt(0))) { + if (isDigit(tok2.charAt(0))) { + // Two numeric tokens are compared as two long values + return (int) (Long.parseLong(tok1) - Long.parseLong(tok2)); + } + return -1; + } else if (isDigit(tok2.charAt(0))) { + return 1; + } + + // Compare two non-numeric tokens in alphabetic order. + // That is, we want "A", "a", "B", "b" instead of "A", "B", "a", "b" + + int result = tok1.toUpperCase().compareTo(tok2.toUpperCase()); + + if (result != 0) { + return result; + } + return tok1.compareTo(tok2); + } + + /* Example application where output must be: + "1.2" + "1.3" + "1.22A" + "1.22" + "1c" + "1h" + "1p" + "2.1.1" + "2.1a" + "2.10.2" + "2.10a.1" + "2.10" + " " + "ALPHA" + "ALpha" + "Alpha1" + "Alpha2" + "Alpha" + "alPHA" + "alpha1" + "alpha2" + "alpha" + "alpha" + "BETA" + "BEta" + "BeTa" + "bEtA" + "beTA" + "beta" + "" + + */ + public static void main(String... args) { + // Our unsorted strings that must be sorted + final String[] strings = { + null, "", " ", "alpha2", "alpha1", "bEtA", "BeTa", "alpha", "Alpha2", "Alpha1", "Alpha", "1.2", "1.22", + "1.22A", "1.3", "2.10a.1", "2.1.1", "2.10", "2.1a", "2.10.2", "1c", "1h", "1p", "alpha", "beta", "alPHA", + "beTA", "ALpha", "BEta", "ALPHA", "BETA" + }; + + java.util.Arrays.sort(strings, new AlphanumericComparator()); + + for (String s : strings) { + System.out.println(s == null ? "" : '"' + s + '"'); + } + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/IVersionManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/IVersionManager.java new file mode 100644 index 0000000..3c9dd32 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/IVersionManager.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.version; + + +import net.sf.robocode.manager.IVersionManagerBase; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public interface IVersionManager extends IVersionManagerBase { + String checkForNewVersion(); +} diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/Version.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/Version.java new file mode 100644 index 0000000..88ac8a5 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/Version.java @@ -0,0 +1,178 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.version; + + +/** + * @author Flemming N. Larsen (original) + */ +public class Version implements Comparable { + + private final String version; + + // The allowed format is ... where all of these are ints + private final int major; + private final int minor; + private final int revision; + private final int build; + + // , e.g. in "Beta 3" the maturity is 2, and maturity version is 3 + private final int maturity; // Alpha is 1, Beta is 2, Final is 3 + private final int maturity_version; // The number following e.g. "Alpha" or "Beta" + + public Version(String version) { + + // Validate version format + if (!version.matches("\\s*[0-9]+\\.[0-9]+(\\.[0-9]+)?(\\.[0-9]+)?(\\s?(([aA]lpha)|([bB]eta))(\\s?[0-9]+)?)?\\s*")) { + throw new IllegalArgumentException("The format of the version string is not a valid"); + } + version = version.trim(); + this.version = version; + + // Split the version number into its integer numbers + final String[] numbers = version.split("\\."); + + // Parse the major version + int major = 0; + + if (numbers.length >= 1) { + try { + major = Integer.parseInt(numbers[0]); + } catch (NumberFormatException ignore) {} + } + this.major = major; + + // Parse the minor version + int minor = 0; + + if (numbers.length >= 2) { + try { + String[] split = numbers[1].split("\\s++|([aA]lpha)|([bB]eta)"); + + minor = Integer.parseInt(split[0]); + } catch (NumberFormatException ignore) {} + } + this.minor = minor; + + // Parse the revision + int revision = 0; + + if (numbers.length >= 3) { + try { + String[] split = numbers[2].split("\\s++|([aA]lpha)|([bB]eta)"); + + revision = Integer.parseInt(split[0]); + } catch (NumberFormatException ignore) {} + } + this.revision = revision; + + // Parse the build number + int build = 0; + + if (numbers.length >= 4) { + try { + String[] split = numbers[3].split("\\s++|([aA]lpha)|([bB]eta)"); + + build = Integer.parseInt(split[0]); + } catch (NumberFormatException ignore) {} + } + this.build = build; + + // Parse the maturity version, e.g. "Beta 1" + int maturity; + int maturity_version = 1; + + if (isAlpha()) { + maturity = 1; + final String[] split = version.split("[aA]lpha"); + + if (split.length >= 2) { + maturity_version = Integer.parseInt(split[1].trim()); + } + } else if (isBeta()) { + maturity = 2; + final String[] split = version.split("[bB]eta"); + + if (split.length >= 2) { + maturity_version = Integer.parseInt(split[1].trim()); + } + } else { + maturity = 3; + } + this.maturity = maturity; + this.maturity_version = maturity_version; + } + + public boolean isAlpha() { + return (version.matches(".*[aA]lpha.*")); + } + + public boolean isBeta() { + return (version.matches(".*[bB]eta.*")); + } + + public boolean isFinal() { + return !(isAlpha() || isBeta()); + } + + public int getMajor() { + return major; + } + + public int getMinor() { + return minor; + } + + public int getRevision() { + return revision; + } + + public int getBuild() { + return build; + } + + @Override + public String toString() { + return version; + } + + public int compareTo(Object o) { + if (o == null) { + throw new IllegalArgumentException("The input object cannot be null"); + } + if (o instanceof String) { + return compareTo(new Version((String) o)); + } + if (o instanceof Version) { + Version v = (Version) o; + + long delta = getVersionLong() - v.getVersionLong(); + + return (delta == 0) ? 0 : (delta < 0) ? -1 : 1; + } + throw new IllegalArgumentException("The input object must be a String or Version object"); + } + + private long getVersionLong() { + return ((long) major << 40) + ((long) minor << 32) + (revision << 24) + (build << 16) + (maturity << 8) + + maturity_version; + } + + public static int compare(String oneVersion, String anotherVersion) { + return new Version(oneVersion).compareTo(new Version(anotherVersion)); + } + + public static boolean isBeta(String version) { + return new Version(version).isBeta(); + } + + public static boolean isFinal(String version) { + return new Version(version).isFinal(); + } +} + diff --git a/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/VersionManager.java b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/VersionManager.java new file mode 100644 index 0000000..774b557 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/java/net/sf/robocode/version/VersionManager.java @@ -0,0 +1,224 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.version; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.RobocodeProperties; +import static net.sf.robocode.io.Logger.logError; +import static net.sf.robocode.io.Logger.logMessage; +import static net.sf.robocode.io.Logger.logWarning; +import net.sf.robocode.settings.ISettingsManager; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; + + +/** + * @author Mathew A. Nelson (original) + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public final class VersionManager implements IVersionManager { + + private static final String VERSIONS_TXT = "versions.md"; + private static final String UNKNOWN_VERSION = "unknown"; + + private static Version version; + + private final boolean versionChanged; + + public VersionManager(ISettingsManager settingsManager) { // NO_UCD (unused code) + if (settingsManager != null) { + versionChanged = !settingsManager.getLastRunVersion().equals(getVersion()); + if (versionChanged) { + settingsManager.setLastRunVersion(getVersion()); + } + } else { + versionChanged = false; + } + } + + public String checkForNewVersion() { + String newVersLine = null; + InputStream inputStream = null; + InputStreamReader inputStreamReader = null; + BufferedReader reader = null; + + try { + URL url = new URL("http://robocode.sourceforge.net/version/version.html"); + + URLConnection urlConnection = url.openConnection(); + + urlConnection.setConnectTimeout(5000); + + if (urlConnection instanceof HttpURLConnection) { + logMessage("Update checking with http."); + HttpURLConnection h = (HttpURLConnection) urlConnection; + + if (h.usingProxy()) { + logMessage("http using proxy."); + } + } + inputStream = urlConnection.getInputStream(); + inputStreamReader = new InputStreamReader(inputStream); + reader = new BufferedReader(inputStreamReader); + + newVersLine = reader.readLine(); + + } catch (MalformedURLException e) { + logError("Unable to check for new version", e); + newVersLine = null; + } catch (IOException e) { + logError("Unable to check for new version", e); + newVersLine = null; + } finally { + FileUtil.cleanupStream(inputStream); + FileUtil.cleanupStream(inputStreamReader); + FileUtil.cleanupStream(reader); + } + return newVersLine; + } + + public String getVersion() { + return getVersionInstance().toString(); + } + + private static Version getVersionInstance() { + if (version == null) { + version = new Version(getVersionFromJar()); + } + return version; + } + + public boolean isLastRunVersionChanged() { + return versionChanged; + } + + public String getVersionN() { + Version v = getVersionInstance(); + + return v.getMajor() + "." + v.getMinor() + "." + v.getRevision() + "." + v.getBuild(); + } + + public int getVersionAsInt() { + Version v = getVersionInstance(); + + return (v.getMajor() << 24) + (v.getMinor() << 16) + (v.getRevision() << 8) + v.getBuild(); + } + + private static String getVersionFromJar() { + String versionString = null; + + BufferedReader in = null; + + try { + URL versionsUrl = VersionManager.class.getResource("/" + VERSIONS_TXT); + + if (versionsUrl == null) { + logError("The URL for the " + VERSIONS_TXT + " was not found"); + versionString = UNKNOWN_VERSION; + } else { + final URLConnection connection = versionsUrl.openConnection(); + + connection.setUseCaches(false); + final InputStream is = connection.getInputStream(); + + in = new BufferedReader(new InputStreamReader(is)); + + versionString = in.readLine(); + while (versionString != null && !versionString.startsWith("## Version ")) { + versionString = in.readLine(); + } + } + } catch (FileNotFoundException e) { + logError("No " + VERSIONS_TXT + " file in robocode.jar"); + versionString = UNKNOWN_VERSION; + } catch (IOException e) { + logError("Error while reading " + VERSIONS_TXT + " from robocode.jar: " + e); + versionString = UNKNOWN_VERSION; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) {} + } + } + + String version = UNKNOWN_VERSION; + + if (versionString != null && !versionString.equals(UNKNOWN_VERSION)) { + try { + version = versionFileLineToVersion(versionString); + } catch (Exception ignore) {} + } + if (version.equals(UNKNOWN_VERSION)) { + logWarning("Getting version from file"); + return getVersionFromFile(); + } + return version; + } + + private static String getVersionFromFile() { + String versionString = null; + + FileReader fileReader = null; + BufferedReader in = null; + + try { + File dir = FileUtil.getCwd(); + + if (RobocodeProperties.isTestingOn()) { + dir = dir.getParentFile().getParentFile().getParentFile(); + } + fileReader = new FileReader(new File(dir, VERSIONS_TXT)); + in = new BufferedReader(fileReader); + + versionString = in.readLine(); + } catch (FileNotFoundException e) { + logError("No " + VERSIONS_TXT + " file."); + versionString = UNKNOWN_VERSION; + } catch (IOException e) { + logError("IO Exception reading " + VERSIONS_TXT, e); + versionString = UNKNOWN_VERSION; + } finally { + if (fileReader != null) { + try { + fileReader.close(); + } catch (IOException ignored) {} + } + if (in != null) { + try { + in.close(); + } catch (IOException ignored) {} + } + } + + String version = UNKNOWN_VERSION; + + if (versionString != null && !versionString.equals(UNKNOWN_VERSION)) { + try { + version = versionFileLineToVersion(versionString); + } catch (Exception ignore) {} + } + return version; + } + + private static String versionFileLineToVersion(String versionFileLine) { + String version = versionFileLine.substring("## Version ".length()); + + int index = version.indexOf('('); + if (index >= 0) { + version = version.substring(0, index); + } + return version.trim(); + } +} diff --git a/代码/workspace_robo4/robocode.core/src/main/resources/battleRecord.xsd b/代码/workspace_robo4/robocode.core/src/main/resources/battleRecord.xsd new file mode 100644 index 0000000..b29815e --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/resources/battleRecord.xsd @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.core/src/main/resources/battleRecordS.xsd b/代码/workspace_robo4/robocode.core/src/main/resources/battleRecordS.xsd new file mode 100644 index 0000000..abd5f78 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/main/resources/battleRecordS.xsd @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/serialization/ObjectCloner.java b/代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/serialization/ObjectCloner.java new file mode 100644 index 0000000..1f4207a --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/serialization/ObjectCloner.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.serialization; + + +import java.awt.*; +import java.io.*; + + +/** + * This utility class is used for cloning objects. + * + * @author Flemming N. Larsen (original) + */ +public class ObjectCloner { + + /** + * Returns a deep copy of the specified object, or {@code null} if the + * object cannot be serialized. + * + * @param orig the object to deep copy. + * @return a new object that is a deep copy of the specified input object; or + * {@code null} if the object was not copied for some reason. + */ + public static Object deepCopy(Object orig) { + if (!(orig instanceof Serializable)) { + return null; + } + + // Write the object out to a byte array + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream out = null; + + try { + out = new ObjectOutputStream(baos); + out.writeObject(orig); + out.flush(); + } catch (IOException e) { + return null; + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException ignored) {} + } + } + + // Now, create a new object by reading it in from the byte array where the + // original object was written to. + + Object obj = null; + ObjectInputStream in = null; + + try { + in = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); + + obj = in.readObject(); + } catch (IOException e) { + return null; + } catch (ClassNotFoundException e) { + return null; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) {} + } + } + + return obj; + } + + /** + * Returns a deep copy of the specified {@code Color}, or {@code null} if + * the reference to the {@code Color} is {@code null}. + * + * @param c the {@code Color} to deep copy. + * @return a new {@code Color} that is a deep copy if the specified input + * {@code Color}; or {@code null} if the reference to the + * {@code Color} is {@code null}. + */ + public static Color deepCopy(Color c) { + return (c != null) ? new Color(c.getRGB(), true) : null; + } +} diff --git a/代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/serialization/RbSerializerTest.java b/代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/serialization/RbSerializerTest.java new file mode 100644 index 0000000..af1b629 --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/serialization/RbSerializerTest.java @@ -0,0 +1,261 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.serialization; + + +import net.sf.robocode.peer.BulletCommand; +import net.sf.robocode.peer.DebugProperty; +import net.sf.robocode.peer.ExecCommands; +import net.sf.robocode.peer.TeamMessage; +import net.sf.robocode.robotpaint.Graphics2DSerialized; +import net.sf.robocode.security.HiddenAccess; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import robocode.util.Utils; + +import javax.swing.*; + +import java.awt.*; +import java.awt.geom.*; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + + +/** + * @author Pavel Savara (original) + */ +public class RbSerializerTest { + + Exception exception = null; + + @BeforeClass + public static void init() { + // we need to switch off engine classloader for this test + System.setProperty("NOSECURITY", "true"); + System.setProperty("WORKINGDIRECTORY", "target//test-classes"); + System.setProperty("TESTING", "true"); + HiddenAccess.initContainer(); + } + + @AfterClass + public static void cleanup() { + System.setProperty("NOSECURITY", "false"); + } + + @Test + public void empty() throws IOException { + HiddenAccess.initContainer(); + ExecCommands ec = new ExecCommands(); + + ec.setBodyTurnRemaining(150.123); + ec.setTryingToPaint(true); + + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + RbSerializer rbs = new RbSerializer(); + + rbs.serialize(out, RbSerializer.ExecCommands_TYPE, ec); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ExecCommands ec2 = (ExecCommands) rbs.deserialize(in); + + assertNear(ec2.getBodyTurnRemaining(), ec.getBodyTurnRemaining()); + Assert.assertEquals(ec2.isTryingToPaint(), true); + } + + @Test + public void withBullets() throws IOException { + ExecCommands ec = new ExecCommands(); + + ec.setBodyTurnRemaining(150.123); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9354, 11)); + ec.getBullets().add(new BulletCommand(1.0, false, 0.9454, 12)); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9554, -128)); + + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + RbSerializer rbs = new RbSerializer(); + + rbs.serialize(out, RbSerializer.ExecCommands_TYPE, ec); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ExecCommands ec2 = (ExecCommands) rbs.deserialize(in); + + assertNear(ec2.getBodyTurnRemaining(), ec.getBodyTurnRemaining()); + assertNear(ec2.getBullets().get(0).getPower(), 1.0); + Assert.assertEquals(ec2.getBullets().get(1).isFireAssistValid(), false); + Assert.assertEquals(ec2.getBullets().get(2).isFireAssistValid(), true); + Assert.assertEquals(ec2.getBullets().get(2).getBulletId(), -128); + } + + @Test + public void withMessages() throws IOException { + ExecCommands ec = new ExecCommands(); + + ec.setBodyTurnRemaining(150.123); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9354, 11)); + final byte[] data = new byte[20]; + + data[10] = 10; + ec.getTeamMessages().add(new TeamMessage("Foo", "Bar", data)); + ec.getTeamMessages().add(new TeamMessage("Foo", "Bar", null)); + + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + RbSerializer rbs = new RbSerializer(); + + rbs.serialize(out, RbSerializer.ExecCommands_TYPE, ec); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ExecCommands ec2 = (ExecCommands) rbs.deserialize(in); + + Assert.assertEquals(ec2.getTeamMessages().get(0).message[0], 0); + Assert.assertEquals(ec2.getTeamMessages().get(0).message[10], 10); + Assert.assertEquals(ec2.getTeamMessages().get(0).sender, "Foo"); + Assert.assertEquals(ec2.getTeamMessages().get(0).recipient, "Bar"); + Assert.assertEquals(ec2.getTeamMessages().get(1).message, null); + } + + @Test + public void withProperties() throws IOException { + ExecCommands ec = new ExecCommands(); + + ec.setBodyTurnRemaining(150.123); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9354, 11)); + ec.getTeamMessages().add(new TeamMessage("Foo", "Bar", null)); + ec.getDebugProperties().add( + new DebugProperty("UTF8 Native characters", "Pli lu?ouk k pl belsk dy")); + + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + RbSerializer rbs = new RbSerializer(); + + rbs.serialize(out, RbSerializer.ExecCommands_TYPE, ec); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ExecCommands ec2 = (ExecCommands) rbs.deserialize(in); + + Assert.assertEquals(ec2.getDebugProperties().get(0).getKey(), "UTF8 Native characters"); + Assert.assertEquals(ec2.getDebugProperties().get(0).getValue(), "Pli lu?ouk k pl belsk dy"); + } + + // @Test + // 14 seconds for 1000 000, + // 15x faster + public void speed() throws IOException { + ExecCommands ec = new ExecCommands(); + + ec.setBodyTurnRemaining(150.123); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9354, 11)); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9354, 11)); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9354, 11)); + ec.getTeamMessages().add(new TeamMessage("Foo", "Bar", null)); + ec.getDebugProperties().add(new DebugProperty("ooooh", "aaaah")); + + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + + for (int i = 0; i < 1000000; i++) { + out.reset(); + ec.setGunColor(i); + RbSerializer rbs = new RbSerializer(); + + rbs.serialize(out, RbSerializer.ExecCommands_TYPE, ec); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ExecCommands ec2 = (ExecCommands) rbs.deserialize(in); + + Assert.assertEquals(ec2.getGunColor(), i); + } + } + + // @Test + // 21 seconds for 100 000 + public void speed2() { + ExecCommands ec = new ExecCommands(); + + ec.setBodyTurnRemaining(150.123); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9354, 11)); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9354, 11)); + ec.getBullets().add(new BulletCommand(1.0, true, 0.9354, 11)); + ec.getTeamMessages().add(new TeamMessage("Foo", "Bar", null)); + ec.getDebugProperties().add(new DebugProperty("ooooh", "aaaah")); + + ByteArrayOutputStream out = new ByteArrayOutputStream(1024); + + for (int i = 0; i < 100000; i++) { + out.reset(); + ec.setGunColor(i); + ExecCommands ec2 = (ExecCommands) ObjectCloner.deepCopy(ec); + + Assert.assertEquals(ec2.getGunColor(), i); + } + } + + @SuppressWarnings("serial") + @Test + public void graphics() throws InterruptedException { + final Graphics2DSerialized sg = new Graphics2DSerialized(); + + sg.setPaintingEnabled(true); + sg.setBackground(Color.GREEN); + sg.setColor(Color.RED); + Arc2D a = new Arc2D.Double(Arc2D.PIE); + + a.setAngleExtent(10); + a.setAngleStart(-30); + a.setFrame(0, 0, 80, 80); + sg.draw(a); + + sg.setColor(Color.BLUE); + sg.draw(new Line2D.Double(99, 98, 78, 3)); + + sg.setColor(Color.YELLOW); + sg.draw(new Rectangle2D.Double(20, 20, 30, 50)); + + sg.setColor(Color.BLACK); + sg.drawLine(99, 3, 78, 3); + sg.drawRect(90, 20, 30, 50); + + sg.setColor(Color.CYAN); + + sg.setStroke(new BasicStroke(1, 2, BasicStroke.JOIN_ROUND, 4, null, 0)); + sg.fill(new Rectangle2D.Double(20, 70, 30, 50)); + sg.fill(new Ellipse2D.Double(70, 70, 30, 50)); + + sg.setColor(Color.MAGENTA); + sg.fill(new RoundRectangle2D.Double(110, 70, 30, 50, 13.5, 16.1)); + + exception = null; + + Canvas d = new Canvas() { + @Override + public void paint(Graphics g) { + synchronized (this) { + try { + sg.processTo((Graphics2D) g); + } catch (Exception e) { + exception = e; + } + } + } + }; + + d.setSize(200, 200); + + JFrame f = new JFrame() {}; + + f.add(d); + f.pack(); + f.setVisible(true); + f.setFocusable(true); + Thread.sleep(100); + f.setVisible(false); + + Assert.assertNull("Exception occured: " + exception, exception); + } + + public static void assertNear(double v1, double v2) { + org.junit.Assert.assertEquals(v1, v2, Utils.NEAR_DELTA); + } +} diff --git a/代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/version/VersionTest.java b/代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/version/VersionTest.java new file mode 100644 index 0000000..2feb52c --- /dev/null +++ b/代码/workspace_robo4/robocode.core/src/test/java/net/sf/robocode/version/VersionTest.java @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.version; + + +import org.junit.Assert; +import org.junit.Test; + + +/** + * @author Pavel Savara (original) + */ +public class VersionTest { + + @Test + public void same() { + Assert.assertTrue(Version.compare("1.1.3", "1.1.3") == 0); + } + + @Test + public void equalVersion() { + Assert.assertTrue(Version.compare("1.1", "1.1.0.0") == 0); + } + + @Test + public void equalAlphas() { + Assert.assertTrue(Version.compare(" 1.2 Alpha", "1.2.0.0alpha1 ") == 0); + } + + @Test + public void equalBetas() { + Assert.assertTrue(Version.compare("4.2.1Beta2 ", " 4.2.1.0 beta 2") == 0); + } + + @Test + public void greater() { + Assert.assertTrue(Version.compare("1.1.4", "1.1.3") > 0); + } + + @Test + public void greaterShort() { + Assert.assertTrue(Version.compare("1.4", "1.1.3") > 0); + } + + @Test + public void greaterShort2() { + Assert.assertTrue(Version.compare("1.4", "1.1") > 0); + } + + @Test + public void greaterShortBeta() { + Assert.assertTrue(Version.compare("1.4 Beta", "1.1.3") > 0); + } + + @Test + public void greaterShortBeta3() { + Assert.assertTrue(Version.compare("1.4 Beta", "1.1") > 0); + } + + @Test + public void greaterShortBeta2() { + Assert.assertTrue(Version.compare("1.4", "1.1.3") > 0); + } + + @Test + public void greaterLong() { + Assert.assertTrue(Version.compare("1.4.1", "1.1") > 0); + } + + @Test + public void smaller() { + Assert.assertTrue(Version.compare("1.1.2", "1.1.3") < 0); + } + + @Test + public void greaterToo() { + Assert.assertTrue(Version.compare("4.1.2", "1.1.3") > 0); + } + + @Test + public void greaterThanBeta() { + Assert.assertTrue(Version.compare("1.1.3", "1.1.3 Beta") > 0); + } + + @Test + public void smallerThanBeta() { + Assert.assertTrue(Version.compare("1.1.2", "1.1.3 Beta") < 0); + } + + @Test + public void smallerThanAlpha() { + Assert.assertTrue(Version.compare("1.1.3 Alpha", "1.1.3 Beta") < 0); + } + + @Test + public void compareBetas() { + // we can't name versions Beta 2 + Assert.assertTrue(Version.compare("1.1.3 Beta", "1.1.3 Beta 2") < 0); + } + + @Test + public void compareBetas2() { + // we can't name versions Beta 2 + Assert.assertTrue(Version.compare("1.1.3 Beta 2 ", "1.1.3 Beta 3") < 0); + } + + @Test + public void compareBetas3() { + // we can't name versions Beta 2 + Assert.assertTrue(Version.compare("1.1.3 Beta2 ", "1.1.3 Beta 3") < 0); + } + + @Test + public void compareBetas4() { + // we can't name versions Beta 2 + Assert.assertTrue(Version.compare("1.1.3Beta2", "1.1.3 Beta 3") < 0); + } + + @Test + public void compareBetasShort() { + // we can't name versions Beta 2 + Assert.assertTrue(Version.compare("1.7 Beta", "1.1") > 0); + } + + @Test + public void compareBetasShort2() { + // we can't name versions Beta 2 + Assert.assertTrue(Version.compare("1.7 Beta", "1.8") < 0); + } +} diff --git a/代码/workspace_robo4/robocode.distribution/.classpath b/代码/workspace_robo4/robocode.distribution/.classpath new file mode 100644 index 0000000..adc405e --- /dev/null +++ b/代码/workspace_robo4/robocode.distribution/.classpath @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.distribution/.project b/代码/workspace_robo4/robocode.distribution/.project new file mode 100644 index 0000000..602d015 --- /dev/null +++ b/代码/workspace_robo4/robocode.distribution/.project @@ -0,0 +1,27 @@ + + + robocode.distribution + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + robocode.roborumble + robocode.battle + robocode.core + robocode.host + robocode.repository + robocode.ui.editor + robocode.ui + robocode.sound + robocode.installer + robocode.content + robocode.samples + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.distribution/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.distribution/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..66e68a8 --- /dev/null +++ b/代码/workspace_robo4/robocode.distribution/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:10 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.distribution/pom.xml b/代码/workspace_robo4/robocode.distribution/pom.xml new file mode 100644 index 0000000..d13ecae --- /dev/null +++ b/代码/workspace_robo4/robocode.distribution/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + robocode.distribution + Robocode Distribution + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + jar + + + net.sf.robocode + robocode.roborumble + ${project.version} + jar + + + net.sf.robocode + robocode.ui.editor + ${project.version} + jar + + + net.sf.robocode + robocode.installer + ${project.version} + jar + + + net.sf.robocode + robocode.content + ${project.version} + jar + + + + + + maven-assembly-plugin + + ${project.parent.artifactId}-${project.version} + true + + setup.asm.xml + src.asm.xml + + + + net.sf.robocode.installer.AutoExtract + + + + + + make-assembly + package + + single + + + + + + + diff --git a/代码/workspace_robo4/robocode.distribution/robocode.distribution.iml b/代码/workspace_robo4/robocode.distribution/robocode.distribution.iml new file mode 100644 index 0000000..daa00fa --- /dev/null +++ b/代码/workspace_robo4/robocode.distribution/robocode.distribution.iml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.distribution/setup.asm.xml b/代码/workspace_robo4/robocode.distribution/setup.asm.xml new file mode 100644 index 0000000..c8a5b52 --- /dev/null +++ b/代码/workspace_robo4/robocode.distribution/setup.asm.xml @@ -0,0 +1,96 @@ + + + setup + + dir + jar + + false + + + + + net.sf.robocode:robocode.api + + libs + false + robocode.${artifact.extension} + + + + + net.sf.robocode:robocode.roborumble + + libs + false + roborumble.${artifact.extension} + + + + + + net.sf.robocode:robocode.distribution + + net.sf.robocode:robocode.installer + net.sf.robocode:robocode.content + net.sf.robocode:robocode.samples + + net.sf.robocode:robocode.api + + net.sf.robocode:robocode.roborumble + + libs + false + + + + + net.sf.robocode:robocode.content + net.sf.robocode:robocode.installer + + true + + + **/META-INF/** + + + + + + + + net.sf.robocode:robocode.samples + + true + + robots + + + + + ../robocode.api/target/site/apidocs + javadoc + lf + + + + + ../versions.md + lf + + + diff --git a/代码/workspace_robo4/robocode.distribution/src.asm.xml b/代码/workspace_robo4/robocode.distribution/src.asm.xml new file mode 100644 index 0000000..86b0cec --- /dev/null +++ b/代码/workspace_robo4/robocode.distribution/src.asm.xml @@ -0,0 +1,53 @@ + + + src + + dir + zip + + + + .. + lf + + plugins/battleview3d/** + plugins/js/** + plugins/scala/** + **/_ReSharper*/** + **/_ReSharper.*/** + **/Debug/** + **/Release/** + **/obj/** + **/target/** + **/lib/** + **/*.suo + **/*.user + **/*.log + **/*.iws + **/*.iml + **/*.ipr + **/*.jar + **/*.dll + **/*.exe + **/*.bak + **/Thumbs.db + **/~* + **/.* + **/.* + **/_svn/** + **/.svn/** + **/.metadata/** + **/*.jkey + **/*.snk + + + + diff --git a/代码/workspace_robo4/robocode.dummy.zip b/代码/workspace_robo4/robocode.dummy.zip new file mode 100644 index 0000000000000000000000000000000000000000..354edba3f544c7e9d884cb9f2d9322c549239bfd GIT binary patch literal 3658 zcmWIWW@Zs#U|`^2ILv8mHB01sturG7gCGk7gBVb>C_gDbIX@*;FQqg$w^F|#KUc3J zH)rc)UvFkZfwuR5MZG`lIvHl`adMfsV2jvM{XNHWZn@3kpS0z+(!cWLZ^3sKx!#Gs zSE=^-T#A@~dC}aQouy8zWqK0Xgx1Z_Yl(XH;NwHBy$r!dhmO4pKUX7^@w8~er+YpE zlS)pDE@|5&+I~y#;@h(_a}U4yJk7(e%x_Ccf2g0PwUu0 zjm&)$ED8;+F8BO;@$UGllZr{tyS#jq*$+!jh~SaV+WBe8+MbnPlN@L6*Xy{dZ*`_A z`HHZ0QRdfUEUtz8cbUpcgkM~!I`rhp+Jy=n^_$? z6_CH-hR4qT_Z}Kf6P-He&ef2j$XJP^T5$!3Lj}Ki6hL`pP#G$&l8%jq7(bIc`|ZP81(zIw#8t04M(PCLl51&MAX-Pl1;8ch4)!hjzLQ-sIH=eoda&f)QA<^7; z2VQo@xd%?F?7CHUY4*A{t^W6+_hXAL-=80nxawcJQ2m?job!*W>|ubpn}MN$L)!}I zR5%a@ve1%CaZ$29ZVeLHHRL8{=HbyLi$_;hVp$>{t%`)S=B1Y4(XK*__Tn@=Cg>7r z0xTHu7^Q^AsG`*3{L-T2)M7mP)riuMKR`5zHUn>{7?ENO5kZ3^U6rI3^HWN5QuRPqt_?byciVu+?s&uf#^Xyoo~A5cxO>eD zJ=SXrZ+v6wITCS5<>G=A@q-)6=PzM-*%s%`+2%UoKL65(&uSOHf50YJVbv*}+qU)I zf%dz3``6y@|Il*t689bLA8vMqEIn-dJ~x_5Go3Z;wmvgc)pSnv`-Klx1iVzZC0Xs) zdK+-|H!b`s?%}Z3(nrEyuTQ{Wvc;El0THd4O#R$e{p|h*?#`Efc_n%rI9^uqK%i^c z^PdmqwypOI_F*|4_g3mccj>LTnKDZ+g)EVner}cQ@m%4MN$X=~L~lM@xl5XDXGLgd z`o)qINl({P&Gwslt3GW%UAH`kZ=YG*v!7Noc28URv4^|zN8k#U^(Uh%di2CUKREP6 zGvG|b)T>S3dl$Y}yRyGPMT0HGYSn5>MUPykUt081RGtp;Q>uvK~> zoe(q1foTWL3`7-(Fa~=a1Tuz!K>&#Lfe9SV7)Xr-^9!Z{pt1u3Kn5gWHvn2g;WhY&OHZ z22K2+6bBAagd3qnC_b-)>O=?t8Jj_hu`v7b1}$nj-+|qHaQ%VLm8j|b9UfCiOy`=c zSi=#uLc`}W6B1U8YGceXV7ZKTCu^Ww%Dd9%LYG8=l man->P3lxBq8ynWZC1e3ojU3?33N(X(K^O@6fGjl*5Dx$e+ZEgZ literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.host/.classpath b/代码/workspace_robo4/robocode.host/.classpath new file mode 100644 index 0000000..a1d093f --- /dev/null +++ b/代码/workspace_robo4/robocode.host/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.host/.project b/代码/workspace_robo4/robocode.host/.project new file mode 100644 index 0000000..e6a7e2e --- /dev/null +++ b/代码/workspace_robo4/robocode.host/.project @@ -0,0 +1,17 @@ + + + robocode.host + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + robocode.core + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.host/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.host/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..65f3846 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:08 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.host/pom.xml b/代码/workspace_robo4/robocode.host/pom.xml new file mode 100644 index 0000000..f0e6ed6 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + robocode.host + Robocode Host + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + net.sf.robocode + robocode.core + ${project.version} + + + + junit + junit + 4.11 + test + + + diff --git a/代码/workspace_robo4/robocode.host/robocode.host.iml b/代码/workspace_robo4/robocode.host/robocode.host.iml new file mode 100644 index 0000000..ddbee93 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/robocode.host.iml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/CpuManager.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/CpuManager.java new file mode 100644 index 0000000..93a9a28 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/CpuManager.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.io.Logger; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.IWindowManager; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert Maupin (contributor) + * @author Pavel Savara (contributor) + */ +public class CpuManager implements ICpuManager { // NO_UCD (use default) + private final static int APPROXIMATE_CYCLES_ALLOWED = 6250; + private final static int TEST_PERIOD_MILLIS = 5000; + + private long cpuConstant = -1; + private final ISettingsManager properties; + + public CpuManager(ISettingsManager properties) { // NO_UCD (unused code) + this.properties = properties; + } + + public long getCpuConstant() { + if (cpuConstant == -1) { + cpuConstant = properties.getCpuConstant(); + if (cpuConstant == -1) { + calculateCpuConstant(); + } + } + return cpuConstant; + } + + public void calculateCpuConstant() { + setStatus("Estimating CPU speed, please wait..."); + + setCpuConstant(); + Logger.logMessage( + "Each robot will be allowed a maximum of " + cpuConstant + " nanoseconds per turn on this system."); + + properties.setCpuConstant(cpuConstant); + properties.saveProperties(); + + setStatus(""); + } + + private void setCpuConstant() { + long count = 0; + double d = 0; + + long start = System.currentTimeMillis(); + + while (System.currentTimeMillis() - start < TEST_PERIOD_MILLIS) { + d += Math.hypot(Math.sqrt(Math.abs(Math.log(Math.atan(Math.random())))), + Math.cbrt(Math.abs(Math.random() * 10))) + / Math.exp(Math.random()); + count++; + } + + // to cheat optimizer, almost never happen + if (d == 0.0) { + Logger.logMessage("bingo!"); + } + + cpuConstant = Math.max(1, (long) (1000000.0 * APPROXIMATE_CYCLES_ALLOWED * TEST_PERIOD_MILLIS / count)); + } + + private void setStatus(String message) { + IWindowManager windowManager = Container.getComponent(IWindowManager.class); + + if (windowManager != null) { + windowManager.setStatus(message); + } + } + +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/HostManager.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/HostManager.java new file mode 100644 index 0000000..8dd1320 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/HostManager.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import net.sf.robocode.host.proxies.*; +import net.sf.robocode.host.security.*; +import net.sf.robocode.host.jarjar.JarJarURLConnection; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import net.sf.robocode.peer.IRobotPeer; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.repository.RobotType; +import net.sf.robocode.security.HiddenAccess; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.core.Container; +import robocode.control.RobotSpecification; + +import java.io.InputStream; +import java.io.PrintStream; + + +/** + * @author Pavel Savara (original) + */ +public class HostManager implements IHostManager { + private final ISettingsManager properties; + private IThreadManager threadManager; + + public HostManager(ISettingsManager properties, IThreadManager threadManager) { // NO_UCD (unused code) + this.properties = properties; + this.threadManager = threadManager; + } + + static { + initStreams(); + } + + private static void initStreams() { + PrintStream sysout = new SecurePrintStream(Logger.realOut, true); + PrintStream syserr = new SecurePrintStream(Logger.realErr, true); + InputStream sysin = new SecureInputStream(System.in); + + System.setOut(sysout); + if (RobocodeProperties.isDebuggingOff()) { + System.setErr(syserr); + } + System.setIn(sysin); + } + + public long getRobotFilesystemQuota() { + return properties.getRobotFilesystemQuota(); + } + + public IThreadManager getThreadManager() { + return threadManager; + } + + public void resetThreadManager() { + threadManager.reset(); + } + + public void addSafeThread(Thread safeThread) { + threadManager.addSafeThread(safeThread); + } + + public void removeSafeThread(Thread safeThread) { + threadManager.removeSafeThread(safeThread); + } + + public PrintStream getRobotOutputStream() { + return threadManager.getRobotOutputStream(); + } + + public void cleanup() {// TODO + } + + public String[] getReferencedClasses(IRobotItem robotItem) { + return getHost(robotItem).getReferencedClasses(robotItem); + } + + public RobotType getRobotType(IRobotItem robotItem, boolean resolve, boolean message) { + return getHost(robotItem).getRobotType(robotItem, resolve, message); + } + + public IHostingRobotProxy createRobotProxy(RobotSpecification robotSpecification, RobotStatics statics, IRobotPeer peer) { + IRobotItem specification = (IRobotItem) HiddenAccess.getFileSpecification(robotSpecification); + return getHost(specification).createRobotProxy(this, robotSpecification, statics, peer); + } + + private IHost getHost(IRobotItem robotItem) { + return (IHost) Container.cache.getComponent("robocode.host." + robotItem.getPlatform().toLowerCase()); + } + + public void initSecurity() { + JarJarURLConnection.register(); + new RobocodeSecurityPolicy(threadManager); + new RobocodeSecurityManager(threadManager); + } + +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IHost.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IHost.java new file mode 100644 index 0000000..f5d6a33 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IHost.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import net.sf.robocode.peer.IRobotStatics; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.repository.RobotType; +import net.sf.robocode.host.proxies.IHostingRobotProxy; +import net.sf.robocode.peer.IRobotPeer; +import robocode.control.RobotSpecification; + + +/** + * @author Pavel Savara (original) + */ +public interface IHost { // NO_UCD (use default) + IHostingRobotProxy createRobotProxy(IHostManager hostManager, RobotSpecification robotSpecification, IRobotStatics statics, IRobotPeer peer); + String[] getReferencedClasses(IRobotItem robotItem); + RobotType getRobotType(IRobotItem robotItem, boolean resolve, boolean message); +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IHostedThread.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IHostedThread.java new file mode 100644 index 0000000..98addcc --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IHostedThread.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import net.sf.robocode.host.io.RobotFileSystemManager; +import net.sf.robocode.host.io.RobotOutputStream; + + +/** + * @author Pavel Savara (original) + */ +public interface IHostedThread extends Runnable { + void println(String s); + + void drainEnergy(); + + void punishSecurityViolation(String message); + + RobotStatics getStatics(); + + RobotFileSystemManager getRobotFileSystemManager(); + + RobotOutputStream getOut(); + + ClassLoader getRobotClassloader(); +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IThreadManager.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IThreadManager.java new file mode 100644 index 0000000..e0e3aac --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/IThreadManager.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import net.sf.robocode.security.IThreadManagerBase; + +import java.io.PrintStream; + + +/** + * @author Pavel Savara (original) + */ +public interface IThreadManager extends IThreadManagerBase { + void addThreadGroup(ThreadGroup g, IHostedThread robotProxy); + + IHostedThread getLoadingRobotProxy(Thread t); + + IHostedThread getLoadedOrLoadingRobotProxy(Thread t); + + IHostedThread getRobotProxy(Thread t); + + void reset(); + + void setLoadingRobot(IHostedThread newLoadingRobotProxy); + + void addSafeThread(Thread safeThread); + + void addSafeThreadGroup(ThreadGroup safeThreadGroup); + + void removeSafeThread(Thread safeThread); + + boolean isSafeThread(Thread c); + + PrintStream getRobotOutputStream(); + + boolean checkRobotFileStream(); +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/Module.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/Module.java new file mode 100644 index 0000000..d551df1 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/Module.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host; + + +import net.sf.robocode.core.BaseModule; +import net.sf.robocode.core.Container; +import net.sf.robocode.host.security.ThreadManager; + + +/** + * @author Pavel Savara (original) + */ +public class Module extends BaseModule { + static { + Container.cache.addComponent(IHostManager.class, HostManager.class); + Container.cache.addComponent(ICpuManager.class, CpuManager.class); + Container.cache.addComponent(IThreadManager.class, ThreadManager.class); + Container.cache.addComponent("robocode.host.java", JavaHost.class); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventQueue.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventQueue.java new file mode 100644 index 0000000..62779b5 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/EventQueue.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.events; + + +import net.sf.robocode.security.HiddenAccess; +import robocode.Event; + +import java.util.ArrayList; +import java.util.Collections; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class EventQueue extends ArrayList { + + public void clear(boolean includingSystemEvents) { + if (includingSystemEvents) { + super.clear(); + return; + } + + for (int i = 0; i < size(); i++) { + Event e = get(i); + + if (!HiddenAccess.isCriticalEvent(e)) { + remove(i--); + } + } + } + + public void clear(long clearTime) { + for (int i = 0; i < size(); i++) { + Event e = get(i); + + if ((e.getTime() <= clearTime) && !HiddenAccess.isCriticalEvent(e)) { + remove(i--); + } + } + } + + void sort() { + Collections.sort(this); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/IEventManager.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/IEventManager.java new file mode 100644 index 0000000..0d8a85e --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/events/IEventManager.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.events; + + +import robocode.*; + +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public interface IEventManager { + void addCustomEvent(Condition condition); + + void removeCustomEvent(Condition condition); + + void clearAllEvents(boolean includingSystemEvents); + + void setEventPriority(String eventClass, int priority); + + int getEventPriority(String eventClass); + + java.util.List getAllEvents(); + + List getBulletMissedEvents(); + + List getBulletHitBulletEvents(); + + List getBulletHitEvents(); + + List getHitByBulletEvents(); + + List getHitRobotEvents(); + + List getHitWallEvents(); + + List getRobotDeathEvents(); + + List getScannedRobotEvents(); + + // team + List getMessageEvents(); +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/BufferedPipedInputStream.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/BufferedPipedInputStream.java new file mode 100644 index 0000000..9e7c191 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/BufferedPipedInputStream.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.io; + + +import java.io.IOException; +import java.io.InputStream; + + +/** + * @author Mathew A. Nelson (original) + */ +class BufferedPipedInputStream extends InputStream { + + private final BufferedPipedOutputStream out; + + protected BufferedPipedInputStream(BufferedPipedOutputStream out) { + this.out = out; + } + + @Override + public int read() throws IOException { + return out.read(); + } + + @Override + public int read(byte b[], int off, int len) throws IOException { + return out.read(b, off, len); + } + + @Override + public int available() { + return out.available(); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/BufferedPipedOutputStream.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/BufferedPipedOutputStream.java new file mode 100644 index 0000000..448e50c --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/BufferedPipedOutputStream.java @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.io; + + +import java.io.IOException; +import java.io.OutputStream; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +class BufferedPipedOutputStream extends OutputStream { + + private final Object monitor = new Object(); + private final byte[] buf; + private volatile int readIndex; + private volatile int writeIndex; + private volatile boolean waiting; + private volatile boolean closed; + private BufferedPipedInputStream in; + private final boolean skipLines; + + BufferedPipedOutputStream(int bufferSize, boolean skipLines) { + this.buf = new byte[bufferSize]; + this.skipLines = skipLines; + } + + /* + * @see OutputStream#write(int) + */ + @Override + public void write(int b) throws IOException { + synchronized (monitor) { + if (closed) { + throw new IOException("Stream is closed."); + } + + buf[writeIndex++] = (byte) (b & 0xff); + if (writeIndex == buf.length) { + writeIndex = 0; + } + if (writeIndex == readIndex) { + // skipping a line! + if (skipLines) { + boolean writeIndexReached = false; + + while (buf[readIndex] != '\n') { + readIndex++; + if (readIndex == buf.length) { + readIndex = 0; + } + if (readIndex == writeIndex) { + writeIndexReached = true; + } + } + if (!writeIndexReached) { + readIndex++; + if (readIndex == buf.length) { + readIndex = 0; + } + } + } else { + throw new IOException("Buffer is full."); + } + } + if (waiting) { + monitor.notifyAll(); + } + } + } + + protected int read() throws IOException { + synchronized (monitor) { + while (readIndex == writeIndex) { + waiting = true; + try { + if (!closed) { + monitor.wait(10000); + } + if (closed) { + return -1; + } + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + + IOException ioException = new IOException("read interrupted"); + + ioException.initCause(e); + throw ioException; + } + } + int result = buf[readIndex++]; + + if (readIndex == buf.length) { + readIndex = 0; + } + + return result; + } + } + + int read(byte b[], int off, int len) throws IOException { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || off >= b.length || (off + len) > b.length) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + int first = read(); + + if (first == -1) { + return -1; + } + + b[off] = (byte) (first & 0xff); + int count = 1; + + synchronized (monitor) { + for (int i = 1; readIndex != writeIndex && i < len; i++) { + b[off + i] = buf[readIndex++]; + count++; + if (readIndex == buf.length) { + readIndex = 0; + } + } + } + return count; + } + + protected int available() { + synchronized (monitor) { + if (writeIndex == readIndex) { + return 0; + } else if (writeIndex > readIndex) { + return writeIndex - readIndex; + } else { + return buf.length - readIndex + writeIndex; + } + } + } + + public BufferedPipedInputStream getInputStream() { + synchronized (monitor) { + if (in == null) { + in = new BufferedPipedInputStream(this); + } + return in; + } + } + + @Override + public void close() { + synchronized (monitor) { + closed = true; + if (waiting) { + monitor.notifyAll(); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotFileOutputStream.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotFileOutputStream.java new file mode 100644 index 0000000..3895021 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotFileOutputStream.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.io; + + +import java.io.FileOutputStream; +import java.io.IOException; + + +/** + * @author Pavel Savara (original) + */ +public class RobotFileOutputStream extends FileOutputStream { + + private RobotFileSystemManager fileSystemManager; + + public RobotFileOutputStream(String filename, boolean append, RobotFileSystemManager fileSystemManager) throws IOException { + super(filename, append); + this.fileSystemManager = fileSystemManager; + fileSystemManager.addStream(this); + } + + @Override + public final void close() throws IOException { + fileSystemManager.removeStream(this); + super.close(); + } + + @Override + public final void write(byte[] b) throws IOException { + try { + fileSystemManager.checkQuota(b.length); + super.write(b); + } catch (IOException e) { + try { + close(); + } catch (IOException ignored) {} + throw e; + } + } + + @Override + public final void write(byte[] b, int off, int len) throws IOException { + if (len < 0) { + throw new IndexOutOfBoundsException(); + } + try { + fileSystemManager.checkQuota(len); + super.write(b, off, len); + } catch (IOException e) { + try { + close(); + } catch (IOException ignored) {} + throw e; + } + } + + @Override + public final void write(int b) throws IOException { + try { + fileSystemManager.checkQuota(1); + super.write(b); + } catch (IOException e) { + try { + close(); + } catch (IOException ignored) {} + throw e; + } + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotFileSystemManager.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotFileSystemManager.java new file mode 100644 index 0000000..7ffb8d4 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotFileSystemManager.java @@ -0,0 +1,336 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.io; + + +import net.sf.robocode.host.IHostedThread; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.version.Version; + +import java.io.*; +import java.net.JarURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +public class RobotFileSystemManager { + private final IHostedThread robotProxy; + private long quotaUsed; + private boolean quotaMessagePrinted; + private final List streams = new ArrayList(); + private final long maxQuota; + private final String writableRootDirectory; + private final String readableRootDirectory; + private final String rootPath; + private final String dataDir; + + public RobotFileSystemManager(IHostedThread robotProxy, long maxQuota, String writableRootDirectory, String readableRootDirectory, String rootPath) { + this.robotProxy = robotProxy; + this.maxQuota = maxQuota; + this.writableRootDirectory = writableRootDirectory; + this.readableRootDirectory = readableRootDirectory; + this.rootPath = rootPath; + + this.dataDir = robotProxy.getStatics().getFullClassName().replace('.', '/') + ".data/"; + } + + public void initialize() { + initializeQuota(); + updateDataFiles(); + } + + void addStream(RobotFileOutputStream s) throws IOException { + if (s == null) { + throw new SecurityException("You may not add a null stream."); + } + if (!streams.contains(s)) { + if (streams.size() < 5) { + streams.add(s); + } else { + throw new SecurityException( + "You may only have 5 streams open at a time.\n Make sure you call close() on your streams when you are finished with them."); + } + } + } + + public synchronized void adjustQuota(long len) { + quotaUsed += len; + } + + public void checkQuota() throws IOException { + checkQuota(0); + } + + void checkQuota(long numBytes) throws IOException { + if (numBytes < 0) { + throw new IllegalArgumentException("checkQuota on negative numBytes!"); + } + if (quotaUsed + numBytes <= maxQuota) { + adjustQuota(numBytes); + } else { + final String msg = "You have reached your filesystem quota of: " + maxQuota + " bytes."; + + if (!quotaMessagePrinted) { + robotProxy.println("SYSTEM: " + msg); + quotaMessagePrinted = true; + } + throw new IOException(msg); // Must be IOException due to bug fix [2960894] + } + } + + public long getMaxQuota() { + return maxQuota; + } + + public long getQuotaUsed() { + return quotaUsed; + } + + public File getReadableDirectory() { + try { + return (readableRootDirectory == null) ? null : new File(readableRootDirectory).getCanonicalFile(); + } catch (IOException e) { + Logger.logError(e); + return null; + } + } + + public File getWritableDirectory() { + try { + return (writableRootDirectory == null) + ? null + : new File(writableRootDirectory, robotProxy.getStatics().getShortClassName() + ".data").getCanonicalFile(); + } catch (IOException e) { + Logger.logError(e); + return null; + } + } + + public File getDataFile(String filename) { + filename = filename.replaceAll("\\*", ""); + + final File parent = getWritableDirectory(); + File file = new File(parent, filename); + + // TODO the file is never replaced from jar or directory after it was created + // TODO it would be good to replace it when it have bigger last modified date + if (!file.exists()) { + if (parent != null && !parent.exists() && !parent.mkdirs()) { + return file; + } + InputStream is = null; + OutputStream os = null; + + try { + URL url = new URL(rootPath + dataDir + filename); + + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + try { + is = connection.getInputStream(); + } catch (FileNotFoundException ex) { // Expected as no file might exists with the specified input 'filename' + // #380 yet another historical bot related bug + Version robocodeVersion = toVersion(robotProxy.getStatics().getRobocodeVersion()); + if (robocodeVersion != null && robocodeVersion.compareTo("1.8.2.0") < 0) { + throw ex; + } + } + os = new FileOutputStream(file); + if (is != null) { + copyStream(is, os); + } + } catch (IOException e) { + // #380 yet another historical bot related bug + boolean legacyRobot = false; + if (e instanceof FileNotFoundException) { + Version robocodeVersion = toVersion(robotProxy.getStatics().getRobocodeVersion()); + if (robocodeVersion != null && robocodeVersion.compareTo("1.8.2.0") < 0) { + legacyRobot = true; + } + } + if (!legacyRobot) { + // Always log error, unless an legacy robot got a FileNotFoundException + Logger.logError(e); + } + } finally { + FileUtil.cleanupStream(is); + FileUtil.cleanupStream(os); + } + } + return file; + } + + private void initializeQuota() { + quotaUsed = 0; + quotaMessagePrinted = false; + + File dataDirectory = getWritableDirectory(); + + if (dataDirectory != null && dataDirectory.exists()) { + File[] dataFiles = dataDirectory.listFiles(); + + for (File file : dataFiles) { + quotaUsed += file.length(); + } + } + } + + public boolean isReadable(String fileName) { + File allowedDirectory = getReadableDirectory(); + if (allowedDirectory == null) { + return false; + } + + File attemptedFile; + try { + attemptedFile = new File(fileName).getCanonicalFile(); + } catch (IOException e) { + return false; + } + + if (attemptedFile.equals(allowedDirectory)) { + return true; // recursive check + } + + if (attemptedFile.getParent().indexOf(allowedDirectory.toString()) == 0) { + String fs = attemptedFile.toString(); + int dataIndex = fs.indexOf(".data", allowedDirectory.toString().length()); + + if (dataIndex >= 0) { + if (isWritable(fileName) || attemptedFile.equals(getWritableDirectory())) { + return true; + } + throw new java.security.AccessControlException( + "Preventing " + Thread.currentThread().getName() + " from access to: " + fileName + + ": You may not read another robot's data directory."); + } + return true; + } + + return false; + } + + public boolean isWritable(String fileName) { + File allowedDirectory = getWritableDirectory(); + + if (allowedDirectory == null) { + return false; + } + + File attemptedFile; + + try { + attemptedFile = new File(fileName).getCanonicalFile(); + } catch (IOException e) { + return false; + } + + return attemptedFile.equals(allowedDirectory) || attemptedFile.getParentFile().equals(allowedDirectory); + } + + void removeStream(RobotFileOutputStream s) { + if (s == null) { + throw new SecurityException("You may not remove a null stream."); + } + if (streams.contains(s)) { + streams.remove(s); + } + } + + private void updateDataFiles() { + try { + if (rootPath.startsWith("jar:")) { + updateDataFilesFromJar(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + private void updateDataFilesFromJar() throws IOException { + URL url = new URL(rootPath); + JarURLConnection jarConnection = (JarURLConnection) url.openConnection(); + + jarConnection.setUseCaches(false); + + JarFile jarFile = jarConnection.getJarFile(); + + Enumeration entries = jarFile.entries(); + + final File parent = getWritableDirectory(); + + if (!parent.exists() && !parent.mkdirs()) { + throw new IOException("Could not create writeable directory for " + robotProxy.getStatics().getName()); + } + + InputStream is = null; + OutputStream os = null; + + while (entries.hasMoreElements()) { + JarEntry jarEntry = (JarEntry) entries.nextElement(); + + String filename = jarEntry.getName(); + + if (filename.startsWith(dataDir)) { + filename = filename.substring(dataDir.length()); + if (filename.length() == 0) { // Bugfix [2845608] - FileNotFoundException + continue; + } + + is = null; + os = null; + try { + is = jarFile.getInputStream(jarEntry); + os = new FileOutputStream(new File(parent, filename)); + copyStream(is, os); + } finally { + FileUtil.cleanupStream(is); + FileUtil.cleanupStream(os); + } + } + } + } + + private void copyStream(InputStream is, OutputStream os) throws IOException { + BufferedInputStream bis = new BufferedInputStream(is); + BufferedOutputStream bos = new BufferedOutputStream(os); + + byte[] buf = new byte[8192]; + int len; + + while ((len = bis.read(buf)) > 0) { + bos.write(buf, 0, len); + } + bos.flush(); + } + + private static Version toVersion(String vers) { + if (vers != null) { + vers = vers.trim(); + if (vers.length() > 0) { + try { + return new Version(vers); + } catch (IllegalArgumentException ex) { + return null; + } + } + } + return null; + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotOutputStream.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotOutputStream.java new file mode 100644 index 0000000..74cd65f --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/io/RobotOutputStream.java @@ -0,0 +1,294 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.io; + + +import java.io.PrintWriter; +import java.io.StringWriter; + +import net.sf.robocode.io.RobocodeProperties; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobotOutputStream extends java.io.PrintStream { + + private static final int MAX_CHARS = 50000; + + private int count = 0; + private boolean messaged = false; + private final StringBuilder text; + private final Object syncRoot = new Object(); + + public RobotOutputStream() { + super(new BufferedPipedOutputStream(128, true)); + this.text = new StringBuilder(8192); + } + + public String readAndReset() { + synchronized (syncRoot) { + + // Out's counter must be reset before processing event. + // Otherwise, it will not be reset when printing in the onScannedEvent() + // before a scan() call, which will potentially cause a new onScannedEvent() + // and therefore not be able to reset the counter. + count = 0; + + if (text.length() > 0) { + final String result = text.toString(); + + text.setLength(0); + return result; + } + return ""; + } + } + + private boolean isOkToPrint() { + synchronized (syncRoot) { + if (RobocodeProperties.isDebuggingOn()) { // It is always allowed to print when debugging is enabled. + return true; + } + if (count > MAX_CHARS) { + if (!messaged) { + text.append( + "\nSYSTEM: This robot is printing too much between actions. Output stopped until next action.\n"); + messaged = true; + } + return false; + } + messaged = false; + return true; + } + } + + @Override + public void print(char[] s) { + synchronized (syncRoot) { + if (isOkToPrint()) { + int origLen = text.length(); + + text.append(s); + count += text.length() - origLen; + } + } + } + + @Override + public void print(char c) { + synchronized (syncRoot) { + if (isOkToPrint()) { + text.append(c); + count++; + } + } + } + + @Override + public void print(double d) { + synchronized (syncRoot) { + if (isOkToPrint()) { + int origLen = text.length(); + + text.append(d); + count += text.length() - origLen; + } + } + } + + @Override + public void print(float f) { + synchronized (syncRoot) { + if (isOkToPrint()) { + int origLen = text.length(); + + text.append(f); + count += text.length() - origLen; + } + } + } + + @Override + public void print(int i) { + synchronized (syncRoot) { + if (isOkToPrint()) { + int origLen = text.length(); + + text.append(i); + count += text.length() - origLen; + } + } + } + + @Override + public void print(long l) { + synchronized (syncRoot) { + if (isOkToPrint()) { + int origLen = text.length(); + + text.append(l); + count += text.length() - origLen; + } + } + } + + @Override + public void print(Object obj) { + synchronized (syncRoot) { + if (isOkToPrint()) { + int origLen = text.length(); + + if (obj != null) { + String s = obj.toString(); + + text.append(s); + } else { + text.append((Object) null); + } + count += text.length() - origLen; + } + } + } + + @Override + public void print(String s) { + synchronized (syncRoot) { + if (isOkToPrint()) { + int origLen = text.length(); + + text.append(s); + count += text.length() - origLen; + } + } + } + + @Override + public void print(boolean b) { + synchronized (syncRoot) { + if (isOkToPrint()) { + int origLen = text.length(); + + text.append(b); + count += text.length() - origLen; + } + } + } + + @Override + public void println() { + print('\n'); + } + + @Override + public void println(char[] x) { + print(x); + print('\n'); + } + + @Override + public void println(char x) { + print(x); + print('\n'); + } + + @Override + public void println(double x) { + print(x); + print('\n'); + } + + @Override + public void println(float x) { + print(x); + print('\n'); + } + + @Override + public void println(int x) { + print(x); + print('\n'); + } + + @Override + public void println(long x) { + print(x); + print('\n'); + } + + @Override + public void println(Object x) { + print(x); + print('\n'); + } + + @Override + public void println(String x) { + print(x); + print('\n'); + } + + @Override + public void println(boolean x) { + print(x); + print('\n'); + } + + @Override + public void write(byte[] buf) { + write(buf, 0, buf.length); + } + + @Override + public void write(byte[] buf, int off, int len) { + synchronized (syncRoot) { + if (isOkToPrint()) { + if (buf != null) { + int origLen = text.length(); + + for (int i = 0; i < len; i++) { + text.append((char) buf[off + i]); + } + count += text.length() - origLen; + } + } + } + } + + @Override + public void write(int b) { + synchronized (syncRoot) { + if (isOkToPrint()) { + int origLen = text.length(); + + text.append((char) b); + count += text.length() - origLen; + } + } + } + + public void printStackTrace(Throwable t) { + if (t != null) { + synchronized (syncRoot) { + if (isOkToPrint()) { + StringWriter sw = new StringWriter(); + final PrintWriter writer = new PrintWriter(sw); + + t.printStackTrace(writer); + writer.flush(); + + int origLen = text.length(); + + text.append(sw.toString()); + count += text.length() - origLen; + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/jarjar/JarJarURLConnection.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/jarjar/JarJarURLConnection.java new file mode 100644 index 0000000..bce050c --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/jarjar/JarJarURLConnection.java @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +// NOTE: JarJarURLStreamHandler is just tweaked version of jar handler from OpenJDK. + +package net.sf.robocode.host.jarjar; + + +import net.sf.robocode.io.URLJarCollector; +import net.sf.robocode.io.JarJar; + +import java.io.InputStream; +import java.io.IOException; +import java.net.*; + + +// TODO: Update to new version from OpenJDK + +/** + * @author Sun Microsystems, Inc (original) + * @author Pavel Savara (contributor) + */ +public class JarJarURLConnection extends URLConnection { + + private final static char SEPARATOR_CHAR = JarJar.SEPARATOR_CHAR; // this is '^' now + private final static String SEPARATOR = SEPARATOR_CHAR + "/"; + + private URLConnection connection; + private static boolean registered; + + private JarJarURLConnection(URL url) + throws IOException { + super(url); + final String file = url.getFile(); + URL inner = new URL(file); + + // this is same as + // connection = inner.openConnection() + // we just cache the connection in URLJarCollector + // because we need to be able to close it to release jar files + connection = URLJarCollector.openConnection(inner); + } + + public void connect() throws IOException { + if (!connected) { + connection.connect(); + connected = true; + } + } + + public InputStream getInputStream() throws IOException { + connect(); + return connection.getInputStream(); + } + + public static void register() { + if (!registered) { + URL.setURLStreamHandlerFactory(new JarJarURLStreamHandlerFactory()); + registered = true; + } + } + + private static class JarJarURLStreamHandlerFactory implements URLStreamHandlerFactory { + public URLStreamHandler createURLStreamHandler(String protocol) { + if (protocol.equals("jarjar")) { + return new JarJarURLStreamHandler(); + } + return null; + } + } + + + private static class JarJarURLStreamHandler extends URLStreamHandler { + + protected URLConnection openConnection(URL u) throws IOException { + return new JarJarURLConnection(u); + } + + private int indexOfBangSlash(String spec) { + int indexOfBang = spec.length(); + + while ((indexOfBang = spec.lastIndexOf(SEPARATOR_CHAR, indexOfBang)) != -1) { + if ((indexOfBang != (spec.length() - 1)) && (spec.charAt(indexOfBang + 1) == '/')) { + return indexOfBang + 1; + } else { + indexOfBang--; + } + } + return -1; + } + + @SuppressWarnings({ "deprecation"}) + protected void parseURL(URL url, String spec, + int start, int limit) { + String file = null; + String ref = null; + // first figure out if there is an anchor + int refPos = spec.indexOf('#', limit); + boolean refOnly = refPos == start; + + if (refPos > -1) { + ref = spec.substring(refPos + 1, spec.length()); + if (refOnly) { + file = url.getFile(); + } + } + // then figure out if the spec is + // 1. absolute (jarjar:) + // 2. relative (i.e. url + foo/bar/baz.ext) + // 3. anchor-only (i.e. url + #foo), which we already did (refOnly) + boolean absoluteSpec = false; + + if (spec.length() >= 7) { + absoluteSpec = spec.substring(0, 7).equalsIgnoreCase("jarjar:"); + } + spec = spec.substring(start, limit); + + if (absoluteSpec) { + file = parseAbsoluteSpec(spec); + } else if (!refOnly) { + file = parseContextSpec(url, spec); + + // Canonize the result after the bangslash + int bangSlash = indexOfBangSlash(file); + String toBangSlash = file.substring(0, bangSlash); + String afterBangSlash = file.substring(bangSlash); + + file = toBangSlash + afterBangSlash; + } + file = file != null ? "jar:" + file.replaceFirst("\\" + SEPARATOR, "!/") : null; + setURL(url, "jarjar", "", -1, file, ref); + } + + private String parseAbsoluteSpec(String spec) { + @SuppressWarnings("unused") + URL url = null; + int index = -1; + + // check for !/ + if ((index = indexOfBangSlash(spec)) == -1) { + throw new NullPointerException("no " + SEPARATOR + " in spec"); + } + // test the inner URL + try { + String innerSpec = spec.substring(0, index - 1); + + url = new URL(innerSpec); + } catch (MalformedURLException e) { + throw new NullPointerException("invalid url: " + spec + " (" + e + ")"); + } + return spec; + } + + private String parseContextSpec(URL url, String spec) { + String ctxFile = url.getFile(); + + // if the spec begins with /, chop up the jar back !/ + if (spec.startsWith("/")) { + int bangSlash = indexOfBangSlash(ctxFile); + + if (bangSlash == -1) { + throw new NullPointerException("malformed " + "context url:" + url + ": no " + SEPARATOR); + } + ctxFile = ctxFile.substring(0, bangSlash); + } + if (!ctxFile.endsWith("/") && (!spec.startsWith("/"))) { + // chop up the last component + int lastSlash = ctxFile.lastIndexOf('/'); + + if (lastSlash == -1) { + throw new NullPointerException("malformed " + "context url:" + url); + } + ctxFile = ctxFile.substring(0, lastSlash + 1); + } + return (ctxFile + spec); + } + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/AdvancedRobotProxy.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/AdvancedRobotProxy.java new file mode 100644 index 0000000..da868da --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/AdvancedRobotProxy.java @@ -0,0 +1,216 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.proxies; + + +import net.sf.robocode.host.RobotStatics; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.peer.IRobotPeer; +import net.sf.robocode.repository.IRobotItem; +import robocode.*; +import robocode.robotinterfaces.peer.IAdvancedRobotPeer; + +import java.io.File; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class AdvancedRobotProxy extends StandardRobotProxy implements IAdvancedRobotPeer { + + public AdvancedRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { + super(specification, hostManager, peer, statics); + } + + public boolean isAdjustGunForBodyTurn() { + getCall(); + return commands.isAdjustGunForBodyTurn(); + } + + public boolean isAdjustRadarForGunTurn() { + getCall(); + return commands.isAdjustRadarForGunTurn(); + } + + public boolean isAdjustRadarForBodyTurn() { + getCall(); + return commands.isAdjustRadarForBodyTurn(); + } + + // asynchronous actions + public void setResume() { + setCall(); + setResumeImpl(); + } + + public void setStop(boolean overwrite) { + setCall(); + setStopImpl(overwrite); + } + + public void setMove(double distance) { + setCall(); + setMoveImpl(distance); + } + + public void setTurnBody(double radians) { + setCall(); + setTurnBodyImpl(radians); + } + + public void setTurnGun(double radians) { + setCall(); + setTurnGunImpl(radians); + } + + public void setTurnRadar(double radians) { + setCall(); + setTurnRadarImpl(radians); + } + + // blocking actions + public void waitFor(Condition condition) { + waitCondition = condition; + do { + execute(); // Always tick at least once + } while (!condition.test()); + + waitCondition = null; + } + + // fast setters + public void setMaxTurnRate(double newTurnRate) { + setCall(); + if (Double.isNaN(newTurnRate)) { + println("You cannot setMaxTurnRate to: " + newTurnRate); + return; + } + commands.setMaxTurnRate(newTurnRate); + } + + public void setMaxVelocity(double newVelocity) { + setCall(); + if (Double.isNaN(newVelocity)) { + println("You cannot setMaxVelocity to: " + newVelocity); + return; + } + commands.setMaxVelocity(newVelocity); + } + + // events manipulation + public void setInterruptible(boolean interruptable) { + setCall(); + eventManager.setInterruptible(eventManager.getCurrentTopEventPriority(), interruptable); + } + + public void setEventPriority(String eventClass, int priority) { + setCall(); + eventManager.setEventPriority(eventClass, priority); + } + + public int getEventPriority(String eventClass) { + getCall(); + return eventManager.getEventPriority(eventClass); + } + + public void removeCustomEvent(Condition condition) { + setCall(); + eventManager.removeCustomEvent(condition); + } + + public void addCustomEvent(Condition condition) { + setCall(); + eventManager.addCustomEvent(condition); + } + + public void clearAllEvents() { + setCall(); + eventManager.clearAllEvents(false); + } + + public List getAllEvents() { + getCall(); + return eventManager.getAllEvents(); + } + + public List getStatusEvents() { + getCall(); + return eventManager.getStatusEvents(); + } + + public List getBulletMissedEvents() { + getCall(); + return eventManager.getBulletMissedEvents(); + } + + public List getBulletHitBulletEvents() { + getCall(); + return eventManager.getBulletHitBulletEvents(); + } + + public List getBulletHitEvents() { + getCall(); + return eventManager.getBulletHitEvents(); + } + + public List getHitByBulletEvents() { + getCall(); + return eventManager.getHitByBulletEvents(); + } + + public List getHitRobotEvents() { + getCall(); + return eventManager.getHitRobotEvents(); + } + + public List getHitWallEvents() { + getCall(); + return eventManager.getHitWallEvents(); + } + + public List getRobotDeathEvents() { + getCall(); + return eventManager.getRobotDeathEvents(); + } + + public List getScannedRobotEvents() { + getCall(); + return eventManager.getScannedRobotEvents(); + } + + // data + public File getDataDirectory() { + getCall(); + commands.setIORobot(); + return robotFileSystemManager.getWritableDirectory(); + } + + public File getDataFile(final String filename) { + getCall(); + commands.setIORobot(); + if (filename.contains("..")) { + throw new AccessControlException("no relative path allowed"); + } + + return AccessController.doPrivileged(new PrivilegedAction() { + public File run() { + return robotFileSystemManager.getDataFile(filename); + } + }); + } + + public long getDataQuotaAvailable() { + getCall(); + return robotFileSystemManager.getMaxQuota() - robotFileSystemManager.getQuotaUsed(); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/BasicRobotProxy.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/BasicRobotProxy.java new file mode 100644 index 0000000..8f0fea8 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/BasicRobotProxy.java @@ -0,0 +1,567 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.proxies; + + +import net.sf.robocode.host.RobotStatics; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.host.events.EventManager; +import net.sf.robocode.peer.*; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.robotpaint.Graphics2DSerialized; +import net.sf.robocode.robotpaint.IGraphicsProxy; +import net.sf.robocode.security.HiddenAccess; +import robocode.*; +import robocode.Event; +import robocode.exception.AbortedException; +import robocode.exception.DeathException; +import robocode.exception.DisabledException; +import robocode.exception.RobotException; +import robocode.exception.WinException; +import robocode.robotinterfaces.peer.IBasicRobotPeer; +import robocode.util.Utils; + +import java.awt.*; +import static java.lang.Math.max; +import static java.lang.Math.min; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + + +// XXX Remember to update the .NET version whenever a change is made to this class! + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class BasicRobotProxy extends HostingRobotProxy implements IBasicRobotPeer { + private static final long + MAX_SET_CALL_COUNT = 10000, + MAX_GET_CALL_COUNT = 10000; + + private IGraphicsProxy graphicsProxy; + + private RobotStatus status; + private boolean isDisabled; + protected ExecCommands commands; + private ExecResults execResults; + + private final Map bullets = new ConcurrentHashMap(); + private int nextBulletId = 1; // 0 is used for bullet explosions + + private final AtomicInteger setCallCount = new AtomicInteger(0); + private final AtomicInteger getCallCount = new AtomicInteger(0); + + protected Condition waitCondition; + private boolean testingCondition; + private double firedEnergy; + private double firedHeat; + + BasicRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { + super(specification, hostManager, peer, statics); + + eventManager = new EventManager(this); + + graphicsProxy = new Graphics2DSerialized(); + + // dummy + execResults = new ExecResults(null, null, null, null, null, false, false, false); + + setSetCallCount(0); + setGetCallCount(0); + } + + protected void initializeRound(ExecCommands commands, RobotStatus status) { + updateStatus(commands, status); + + eventManager.reset(); + eventManager.add(new StatusEvent(status)); // Start event + + setSetCallCount(0); + setGetCallCount(0); + } + + @Override + public void cleanup() { + super.cleanup(); + + // Cleanup and remove current wait condition + if (waitCondition != null) { + waitCondition.cleanup(); + waitCondition = null; + } + + // Cleanup and remove the event manager + if (eventManager != null) { + eventManager.cleanup(); + eventManager = null; + } + + // Cleanup graphics proxy + graphicsProxy = null; + execResults = null; + status = null; + commands = null; + } + + // asynchronous actions + public Bullet setFire(double power) { + setCall(); + return setFireImpl(power); + } + + // blocking actions + public void execute() { + executeImpl(); + } + + public void move(double distance) { + setMoveImpl(distance); + do { + execute(); // Always tick at least once + } while (getDistanceRemaining() != 0); + } + + public void turnBody(double radians) { + setTurnBodyImpl(radians); + do { + execute(); // Always tick at least once + } while (getBodyTurnRemaining() != 0); + } + + public void turnGun(double radians) { + setTurnGunImpl(radians); + do { + execute(); // Always tick at least once + } while (getGunTurnRemaining() != 0); + } + + public Bullet fire(double power) { + Bullet bullet = setFire(power); + + execute(); + return bullet; + } + + // fast setters + public void setBodyColor(Color color) { + setCall(); + commands.setBodyColor(color != null ? color.getRGB() : ExecCommands.defaultBodyColor); + } + + public void setGunColor(Color color) { + setCall(); + commands.setGunColor(color != null ? color.getRGB() : ExecCommands.defaultGunColor); + } + + public void setRadarColor(Color color) { + setCall(); + commands.setRadarColor(color != null ? color.getRGB() : ExecCommands.defaultRadarColor); + } + + public void setBulletColor(Color color) { + setCall(); + commands.setBulletColor(color != null ? color.getRGB() : ExecCommands.defaultBulletColor); + } + + public void setScanColor(Color color) { + setCall(); + commands.setScanColor(color != null ? color.getRGB() : ExecCommands.defaultScanColor); + } + + // counters + public void setCall() { + if (!isDisabled) { + final int res = setCallCount.incrementAndGet(); + + if (res >= MAX_SET_CALL_COUNT) { + isDisabled = true; + println("SYSTEM: You have made " + res + " calls to setXX methods without calling execute()"); + throw new DisabledException("Too many calls to setXX methods"); + } + } + } + + public void getCall() { + if (!isDisabled) { + final int res = getCallCount.incrementAndGet(); + + if (res >= MAX_GET_CALL_COUNT) { + isDisabled = true; + println("SYSTEM: You have made " + res + " calls to getXX methods without calling execute()"); + throw new DisabledException("Too many calls to getXX methods"); + } + } + } + + public double getDistanceRemaining() { + getCall(); + return commands.getDistanceRemaining(); + } + + public double getRadarTurnRemaining() { + getCall(); + return commands.getRadarTurnRemaining(); + } + + public double getBodyTurnRemaining() { + getCall(); + return commands.getBodyTurnRemaining(); + } + + public double getGunTurnRemaining() { + getCall(); + return commands.getGunTurnRemaining(); + } + + public double getVelocity() { + getCall(); + return status.getVelocity(); + } + + public double getGunCoolingRate() { + getCall(); + return statics.getBattleRules().getGunCoolingRate(); + } + + public String getName() { + getCall(); + return statics.getName(); + } + + public long getTime() { + getCall(); + return getTimeImpl(); + } + + public double getBodyHeading() { + getCall(); + return status.getHeadingRadians(); + } + + public double getGunHeading() { + getCall(); + return status.getGunHeadingRadians(); + } + + public double getRadarHeading() { + getCall(); + return status.getRadarHeadingRadians(); + } + + public double getEnergy() { + getCall(); + return getEnergyImpl(); + } + + public double getGunHeat() { + getCall(); + return getGunHeatImpl(); + } + + public double getX() { + getCall(); + return status.getX(); + } + + public double getY() { + getCall(); + return status.getY(); + } + + public int getOthers() { + getCall(); + return status.getOthers(); + } + + public int getNumSentries() { + getCall(); + return status.getNumSentries(); + } + + public double getBattleFieldHeight() { + getCall(); + return statics.getBattleRules().getBattlefieldHeight(); + } + + public double getBattleFieldWidth() { + getCall(); + return statics.getBattleRules().getBattlefieldWidth(); + } + + public int getNumRounds() { + getCall(); + return statics.getBattleRules().getNumRounds(); + } + + public int getRoundNum() { + getCall(); + return status.getRoundNum(); + } + + public int getSentryBorderSize() { + getCall(); + return statics.getBattleRules().getSentryBorderSize(); + } + + public Graphics2D getGraphics() { + getCall(); + commands.setTryingToPaint(true); + return getGraphicsImpl(); + } + + public void setDebugProperty(String key, String value) { + setCall(); + commands.setDebugProperty(key, value); + } + + public void rescan() { + boolean reset = false; + boolean origInterruptableValue = false; + + if (eventManager.getCurrentTopEventPriority() == eventManager.getScannedRobotEventPriority()) { + reset = true; + origInterruptableValue = eventManager.isInterruptible(eventManager.getScannedRobotEventPriority()); + eventManager.setInterruptible(eventManager.getScannedRobotEventPriority(), true); + } + + commands.setScan(true); + executeImpl(); + + if (reset) { + eventManager.setInterruptible(eventManager.getScannedRobotEventPriority(), origInterruptableValue); + } + } + + // ----------- + // implementations + // ----------- + + public long getTimeImpl() { + return status.getTime(); + } + + public Graphics2D getGraphicsImpl() { + return (Graphics2D) graphicsProxy; + } + + @Override + protected final void executeImpl() { + if (execResults == null) { + // this is to slow down undead robot after cleanup, from fast exception-loop + try { + Thread.sleep(1000); + } catch (InterruptedException ignore) {} + } + + // Entering tick + robotThreadManager.checkRunThread(); + if (testingCondition) { + throw new RobotException( + "You cannot take action inside Condition.test(). You should handle onCustomEvent instead."); + } + + setSetCallCount(0); + setGetCallCount(0); + + // This stops autoscan from scanning... + if (waitCondition != null && waitCondition.test()) { + waitCondition = null; + commands.setScan(true); + } + + commands.setOutputText(out.readAndReset()); + commands.setGraphicsCalls(graphicsProxy.readoutQueuedCalls()); + + // Call server + execResults = peer.executeImpl(commands); + + updateStatus(execResults.getCommands(), execResults.getStatus()); + + graphicsProxy.setPaintingEnabled(execResults.isPaintEnabled()); + firedEnergy = 0; + firedHeat = 0; + + // add new events + eventManager.add(new StatusEvent(execResults.getStatus())); + if (statics.isPaintRobot() && execResults.isPaintEnabled()) { + // Add paint event, if robot is a paint robot and its painting is enabled + eventManager.add(new PaintEvent()); + } + + // add other events + if (execResults.getEvents() != null) { + for (Event event : execResults.getEvents()) { + eventManager.add(event); + } + } + + if (execResults.getBulletUpdates() != null) { + for (BulletStatus bulletStatus : execResults.getBulletUpdates()) { + final Bullet bullet = bullets.get(bulletStatus.bulletId); + + if (bullet != null) { + HiddenAccess.update(bullet, bulletStatus.x, bulletStatus.y, bulletStatus.victimName, + bulletStatus.isActive); + if (!bulletStatus.isActive) { + bullets.remove(bulletStatus.bulletId); + } + } + } + } + + // add new team messages + loadTeamMessages(execResults.getTeamMessages()); + + eventManager.processEvents(); + } + + @Override + protected final void waitForBattleEndImpl() { + eventManager.clearAllEvents(false); + graphicsProxy.setPaintingEnabled(false); + do { + // Make sure remaining system events like e.g. are processed this round + try { + eventManager.processEvents(); + + // The exceptions below are expected to occur, and has already been logged in the robot console, + // but still exists in the robot's event queue. Hence we just ignore these! + // Look in the HostingRobotProxy.run() to see which robot errors that are already handled. + } catch (DeathException ignore) {} catch (WinException ignore) {// Bug fix [2952549] + } catch (AbortedException ignore) {} catch (DisabledException ignore) {// Bug fix [2976258] + } + + commands.setOutputText(out.readAndReset()); + commands.setGraphicsCalls(graphicsProxy.readoutQueuedCalls()); + + // Call server + execResults = peer.waitForBattleEndImpl(commands); + + updateStatus(execResults.getCommands(), execResults.getStatus()); + + // Add remaining events like BattleEndedEvent Otherwise, the robot might never receive those events + if (execResults.getEvents() != null) { + for (Event event : execResults.getEvents()) { + if (event instanceof BattleEndedEvent) { + eventManager.add(event); + } + } + } + eventManager.resetCustomEvents(); + } while (!execResults.isHalt() && execResults.isShouldWait()); + } + + private void updateStatus(ExecCommands commands, RobotStatus status) { + this.status = status; + this.commands = commands; + } + + protected void loadTeamMessages(java.util.List teamMessages) {} + + private final double getEnergyImpl() { + return status.getEnergy() - firedEnergy; + } + + private final double getGunHeatImpl() { + return status.getGunHeat() + firedHeat; + } + + protected final void setMoveImpl(double distance) { + if (getEnergyImpl() == 0) { + return; + } + commands.setDistanceRemaining(distance); + commands.setMoved(true); + } + + private final Bullet setFireImpl(double power) { + if (Double.isNaN(power)) { + println("SYSTEM: You cannot call fire(NaN)"); + return null; + } + if (getGunHeatImpl() > 0 || getEnergyImpl() == 0) { + return null; + } + + power = min(getEnergyImpl(), min(max(power, Rules.MIN_BULLET_POWER), Rules.MAX_BULLET_POWER)); + + Bullet bullet; + BulletCommand wrapper; + Event currentTopEvent = eventManager.getCurrentTopEvent(); + + nextBulletId++; + + if (currentTopEvent != null && currentTopEvent.getTime() == status.getTime() && !statics.isAdvancedRobot() + && status.getGunHeadingRadians() == status.getRadarHeadingRadians() + && ScannedRobotEvent.class.isAssignableFrom(currentTopEvent.getClass())) { + // this is angle assisted bullet + ScannedRobotEvent e = (ScannedRobotEvent) currentTopEvent; + double fireAssistAngle = Utils.normalAbsoluteAngle(status.getHeadingRadians() + e.getBearingRadians()); + + bullet = new Bullet(fireAssistAngle, getX(), getY(), power, statics.getName(), null, true, nextBulletId); + wrapper = new BulletCommand(power, true, fireAssistAngle, nextBulletId); + } else { + // this is normal bullet + bullet = new Bullet(status.getGunHeadingRadians(), getX(), getY(), power, statics.getName(), null, true, + nextBulletId); + wrapper = new BulletCommand(power, false, 0, nextBulletId); + } + + firedEnergy += power; + firedHeat += Rules.getGunHeat(power); + + commands.getBullets().add(wrapper); + + bullets.put(nextBulletId, bullet); + + return bullet; + } + + protected final void setTurnGunImpl(double radians) { + commands.setGunTurnRemaining(radians); + } + + protected final void setTurnBodyImpl(double radians) { + if (getEnergyImpl() > 0) { + commands.setBodyTurnRemaining(radians); + } + } + + protected final void setTurnRadarImpl(double radians) { + commands.setRadarTurnRemaining(radians); + } + + // ----------- + // battle driven methods + // ----------- + + private void setSetCallCount(int setCallCount) { + this.setCallCount.set(setCallCount); + } + + private void setGetCallCount(int getCallCount) { + this.getCallCount.set(getCallCount); + } + + // ----------- + // for robot thread + // ----------- + + public void setTestingCondition(boolean testingCondition) { + this.testingCondition = testingCondition; + } + + @Override + public String toString() { + return statics.getShortName() + "(" + (int) status.getEnergy() + ") X" + (int) status.getX() + " Y" + + (int) status.getY(); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/IHostingRobotProxy.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/IHostingRobotProxy.java new file mode 100644 index 0000000..13be4eb --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/IHostingRobotProxy.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.proxies; + + +import net.sf.robocode.peer.ExecCommands; +import robocode.RobotStatus; + + +/** + * @author Pavel Savara (original) + */ +public interface IHostingRobotProxy { + + void startRound(ExecCommands commands, RobotStatus status); + + void forceStopThread(); + + void waitForStopThread(); + + void cleanup(); + +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/JuniorRobotProxy.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/JuniorRobotProxy.java new file mode 100644 index 0000000..65fa414 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/JuniorRobotProxy.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.proxies; + + +import net.sf.robocode.host.RobotStatics; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.peer.IRobotPeer; +import net.sf.robocode.repository.IRobotItem; +import robocode.Rules; +import robocode.robotinterfaces.peer.IJuniorRobotPeer; + + +/** + * NOTE: This is temporary implementation of the interface. You should not build any external component on top of it. + * + * @author Flemming N. Larsen (original) + * @author Pavel Savara (contributor) + */ +public class JuniorRobotProxy extends BasicRobotProxy implements IJuniorRobotPeer { + + public JuniorRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { + super(specification, hostManager, peer, statics); + } + + public void turnAndMove(double distance, double radians) { + if (distance == 0) { + turnBody(radians); + return; + } + + // Save current max. velocity and max. turn rate so they can be restored + final double savedMaxVelocity = commands.getMaxVelocity(); + final double savedMaxTurnRate = commands.getMaxTurnRate(); + + final double absDegrees = Math.abs(Math.toDegrees(radians)); + final double absDistance = Math.abs(distance); + + // -- Calculate max. velocity for moving perfect in a circle -- + + // maxTurnRate = 10 * 0.75 * abs(velocity) (Robocode rule), and + // maxTurnRate = velocity * degrees / distance (curve turn rate) + // + // Hence, max. velocity = 10 / (degrees / distance + 0.75) + + final double maxVelocity = Math.min(Rules.MAX_VELOCITY, 10 / (absDegrees / absDistance + 0.75)); + + // -- Calculate number of turns for acceleration + deceleration -- + + double accDist = 0; // accumulated distance during acceleration + double decDist = 0; // accumulated distance during deceleration + + int turns = 0; // number of turns to it will take to move the distance + + // Calculate the amount of turn it will take to accelerate + decelerate + // up to the max. velocity, but stop if the distance for used for + // acceleration + deceleration gets bigger than the total distance to move + for (int t = 1; t < maxVelocity; t++) { + + // Add the current velocity to the acceleration distance + accDist += t; + + // Every 2nd time we add the deceleration distance needed to + // get to a velocity of 0 + if (t > 2 && (t % 2) > 0) { + decDist += t - 2; + } + + // Stop if the acceleration + deceleration > total distance to move + if ((accDist + decDist) >= absDistance) { + break; + } + + // Increment turn for acceleration + turns++; + + // Every 2nd time we increment time for deceleration + if (t > 2 && (t % 2) > 0) { + turns++; + } + } + + // Add number of turns for the remaining distance at max velocity + if ((accDist + decDist) < absDistance) { + turns += (int) ((absDistance - accDist - decDist) / maxVelocity + 1); + } + + // -- Move and turn in a curve -- + + // Set the calculated max. velocity + commands.setMaxVelocity(maxVelocity); + + // Set the robot to move the specified distance + setMoveImpl(distance); + // Set the robot to turn its body to the specified amount of radians + setTurnBodyImpl(radians); + + // Loop thru the number of turns it will take to move the distance and adjust + // the max. turn rate so it fit the current velocity of the robot + for (int t = turns; t >= 0; t--) { + commands.setMaxTurnRate(getVelocity() * radians / absDistance); + execute(); // Perform next turn + } + + // Restore the saved max. velocity and max. turn rate + commands.setMaxVelocity(savedMaxVelocity); + commands.setMaxTurnRate(savedMaxTurnRate); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/StandardRobotProxy.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/StandardRobotProxy.java new file mode 100644 index 0000000..804c379 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/StandardRobotProxy.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.proxies; + + +import net.sf.robocode.host.RobotStatics; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.peer.ExecCommands; +import net.sf.robocode.peer.IRobotPeer; +import net.sf.robocode.repository.IRobotItem; +import robocode.RobotStatus; +import robocode.robotinterfaces.peer.IStandardRobotPeer; + + +/** + * @author Pavel Savara (original) + */ +public class StandardRobotProxy extends BasicRobotProxy implements IStandardRobotPeer { + + private boolean isStopped; + private double saveAngleToTurn; + private double saveDistanceToGo; + private double saveGunAngleToTurn; + private double saveRadarAngleToTurn; + + public StandardRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { + super(specification, hostManager, peer, statics); + } + + @Override + protected void initializeRound(ExecCommands commands, RobotStatus status) { + super.initializeRound(commands, status); + isStopped = true; + } + + // blocking actions + public void stop(boolean overwrite) { + setStopImpl(overwrite); + execute(); + } + + public void resume() { + setResumeImpl(); + execute(); + } + + public void turnRadar(double radians) { + setTurnRadarImpl(radians); + do { + execute(); // Always tick at least once + } while (getRadarTurnRemaining() != 0); + } + + // fast setters + public void setAdjustGunForBodyTurn(boolean newAdjustGunForBodyTurn) { + setCall(); + commands.setAdjustGunForBodyTurn(newAdjustGunForBodyTurn); + } + + public void setAdjustRadarForGunTurn(boolean newAdjustRadarForGunTurn) { + setCall(); + commands.setAdjustRadarForGunTurn(newAdjustRadarForGunTurn); + if (!commands.isAdjustRadarForBodyTurnSet()) { + commands.setAdjustRadarForBodyTurn(newAdjustRadarForGunTurn); + } + } + + public void setAdjustRadarForBodyTurn(boolean newAdjustRadarForBodyTurn) { + setCall(); + commands.setAdjustRadarForBodyTurn(newAdjustRadarForBodyTurn); + commands.setAdjustRadarForBodyTurnSet(true); + } + + protected final void setResumeImpl() { + if (isStopped) { + isStopped = false; + commands.setDistanceRemaining(saveDistanceToGo); + commands.setBodyTurnRemaining(saveAngleToTurn); + commands.setGunTurnRemaining(saveGunAngleToTurn); + commands.setRadarTurnRemaining(saveRadarAngleToTurn); + } + } + + protected final void setStopImpl(boolean overwrite) { + if (!isStopped || overwrite) { + this.saveDistanceToGo = getDistanceRemaining(); + this.saveAngleToTurn = getBodyTurnRemaining(); + this.saveGunAngleToTurn = getGunTurnRemaining(); + this.saveRadarAngleToTurn = getRadarTurnRemaining(); + } + isStopped = true; + + commands.setDistanceRemaining(0); + commands.setBodyTurnRemaining(0); + commands.setGunTurnRemaining(0); + commands.setRadarTurnRemaining(0); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/TeamRobotProxy.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/TeamRobotProxy.java new file mode 100644 index 0000000..22b8ca0 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/proxies/TeamRobotProxy.java @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.proxies; + + +import net.sf.robocode.host.RobotStatics; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.host.serialization.RobocodeObjectInputStream; +import net.sf.robocode.peer.IRobotPeer; +import net.sf.robocode.peer.TeamMessage; +import net.sf.robocode.repository.IRobotItem; +import robocode.MessageEvent; +import robocode.robotinterfaces.peer.ITeamRobotPeer; + +import java.io.*; +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public class TeamRobotProxy extends AdvancedRobotProxy implements ITeamRobotPeer { + private static final int MAX_MESSAGE_SIZE = 32768; + private final ByteArrayOutputStream byteStreamWriter; + + public TeamRobotProxy(IRobotItem specification, IHostManager hostManager, IRobotPeer peer, RobotStatics statics) { + super(specification, hostManager, peer, statics); + byteStreamWriter = new ByteArrayOutputStream(MAX_MESSAGE_SIZE); + } + + // team + public String[] getTeammates() { + getCall(); + return statics.getTeammates(); + } + + public boolean isTeammate(String name) { + getCall(); + if (name != null) { // Bugfix [2960870] + if (name.equals(statics.getName())) { + return true; + } + final String[] teammates = statics.getTeammates(); + + if (teammates != null) { + for (String mate : teammates) { + if (mate.equals(name)) { + return true; + } + } + } + } + return false; + } + + public void broadcastMessage(Serializable message) throws IOException { + sendMessage(null, message); + } + + public void sendMessage(String name, Serializable message) throws IOException { + setCall(); + + try { + if (!statics.isTeamRobot()) { + throw new IOException("You are not on a team."); + } + byteStreamWriter.reset(); + ObjectOutputStream objectStreamWriter = new ObjectOutputStream(byteStreamWriter); + + objectStreamWriter.writeObject(message); + objectStreamWriter.flush(); + byteStreamWriter.flush(); + final byte[] bytes = byteStreamWriter.toByteArray(); + + objectStreamWriter.reset(); + if (bytes.length > MAX_MESSAGE_SIZE) { + throw new IOException("Message too big. " + bytes.length + ">" + MAX_MESSAGE_SIZE); + } + commands.getTeamMessages().add(new TeamMessage(getName(), name, bytes)); + } catch (IOException e) { + out.printStackTrace(e); + throw e; + } + + } + + @Override + protected final void loadTeamMessages(List teamMessages) { + if (teamMessages == null) { + return; + } + for (TeamMessage teamMessage : teamMessages) { + try { + ByteArrayInputStream byteStreamReader = new ByteArrayInputStream(teamMessage.message); + byteStreamReader.reset(); + + RobocodeObjectInputStream objectStreamReader = null; + try { + objectStreamReader = new RobocodeObjectInputStream(byteStreamReader, (ClassLoader) robotClassLoader); + Serializable message = (Serializable) objectStreamReader.readObject(); + MessageEvent event = new MessageEvent(teamMessage.sender, message); + eventManager.add(event); + } finally { + if (objectStreamReader != null) { + objectStreamReader.close(); + } + } + } catch (IOException e) { + out.printStackTrace(e); + } catch (ClassNotFoundException e) { + out.printStackTrace(e); + } + } + } + + // events + public List getMessageEvents() { + getCall(); + return eventManager.getMessageEvents(); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/ClassAnalyzer.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/ClassAnalyzer.java new file mode 100644 index 0000000..36208f3 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/ClassAnalyzer.java @@ -0,0 +1,248 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.security; + + +import net.sf.robocode.io.Logger; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +class ClassAnalyzer { + private final static byte CONSTANT_Class = 7; + private final static byte CONSTANT_Fieldref = 9; + private final static byte CONSTANT_Methodref = 10; + private final static byte CONSTANT_InterfaceMethodref = 11; + private final static byte CONSTANT_String = 8; + private final static byte CONSTANT_Integer = 3; + private final static byte CONSTANT_Float = 4; + private final static byte CONSTANT_Long = 5; + private final static byte CONSTANT_Double = 6; + private final static byte CONSTANT_NameAndType = 12; + private final static byte CONSTANT_Utf8 = 1; + + /** + * ClassAnalyzer constructor comment. + */ + public ClassAnalyzer() { + super(); + } + + static void getReferencedClasses(ByteBuffer classFile, Set collection) { + + /* + http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html + + 4.1 The ClassFile Structure + A class file consists of a single ClassFile structure: + + ClassFile { + u4 magic; + u2 minor_version; + u2 major_version; + u2 constant_pool_count; + cp_info constant_pool[constant_pool_count-1]; + u2 access_flags; + u2 this_class; + u2 super_class; + u2 interfaces_count; + u2 interfaces[interfaces_count]; + u2 fields_count; + field_info fields[fields_count]; + u2 methods_count; + method_info methods[methods_count]; + u2 attributes_count; + attribute_info attributes[attributes_count]; + } + */ + String strings[]; + List classNameIndexes = new ArrayList(); + + try { + DataInputStream in = new DataInputStream(new ByteArrayInputStream(classFile.array(), 0, classFile.limit())); + long magic = in.readInt(); + + if (magic != 0xCAFEBABE) { + Logger.logError("Not a class file!"); + return; + } + in.readUnsignedShort(); // minor version + in.readUnsignedShort(); // major version + int constant_pool_count = in.readUnsignedShort(); + + strings = new String[constant_pool_count]; + + /* + + All constant_pool table entries have the following general format: + + + cp_info { + u1 tag; + u1 info[]; + } + + Constant Type Value + CONSTANT_Class 7 + CONSTANT_Fieldref 9 + CONSTANT_Methodref 10 + CONSTANT_InterfaceMethodref 11 + CONSTANT_String 8 + CONSTANT_Integer 3 + CONSTANT_Float 4 + CONSTANT_Long 5 + CONSTANT_Double 6 + CONSTANT_NameAndType 12 + CONSTANT_Utf8 1 + */ + + + for (int i = 1; i < constant_pool_count; i++) { + byte tag = in.readByte(); + + switch (tag) { + + /* + CONSTANT_Class_info { + u1 tag; + u2 name_index; + } + */ + case CONSTANT_Class: { + int name_index = in.readUnsignedShort(); + + classNameIndexes.add(name_index); + } + break; + + /* + CONSTANT_Fieldref_info { + u1 tag; + u2 class_index; + u2 name_and_type_index; + } + CONSTANT_Methodref_info { + u1 tag; + u2 class_index; + u2 name_and_type_index; + } + CONSTANT_InterfaceMethodref_info { + u1 tag; + u2 class_index; + u2 name_and_type_index; + } + */ + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: { + in.readUnsignedShort(); // class index + in.readUnsignedShort(); // name and type index + } + break; + + /* + CONSTANT_String_info { + u1 tag; + u2 string_index; + } + */ + case CONSTANT_String: { + in.readUnsignedShort(); // string index + } + break; + + /* + CONSTANT_Integer_info { + u1 tag; + u4 bytes; + } + CONSTANT_Float_info { + u1 tag; + u4 bytes; + } + */ + case CONSTANT_Integer: + case CONSTANT_Float: { + in.readInt(); // bytes + } + break; + + /* + CONSTANT_Long_info { + u1 tag; + u4 high_bytes; + u4 low_bytes; + } + CONSTANT_Double_info { + u1 tag; + u4 high_bytes; + u4 low_bytes; + } + All 8-byte constants take up two entries in the constant_pool table of the class file. If a CONSTANT_Long_info or CONSTANT_Double_info structure is the item in the constant_pool table at index n, then the next usable item in the pool is located at index n+2. The constant_pool index n+1 must be valid but is considered unusable.2 + */ + + case CONSTANT_Long: + case CONSTANT_Double: { + in.readInt(); // high bytes + in.readInt(); // low bytes + i++; // see "all 8-byte..." comment above. + } + break; + + /* + CONSTANT_NameAndType_info { + u1 tag; + u2 name_index; + u2 descriptor_index; + } + */ + case CONSTANT_NameAndType: { + in.readUnsignedShort(); // name index + in.readUnsignedShort(); // descriptor index + } + break; + + /* + CONSTANT_Utf8_info { + u1 tag; + u2 length; + u1 bytes[length]; + } + */ + case CONSTANT_Utf8: { + String utf8_string = in.readUTF(); + + strings[i] = utf8_string; + } + break; + } // switch + } // for i + } catch (IOException e) { + return; + } + + for (Integer classNameIndex : classNameIndexes) { + String className = strings[classNameIndex].replace('\\', '.').replace('/', '.'); + + if (className.indexOf("[") != 0 && !collection.contains(className)) { + collection.add(className); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodePermission.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodePermission.java new file mode 100644 index 0000000..f33422f --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodePermission.java @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.security; + + +/** + * @author Mathew A. Nelson (original) + */ +@SuppressWarnings("serial") class RobocodePermission extends java.security.Permission { + + RobocodePermission(String name) { + super(name); + } + + /** + * Checks two Permission objects for equality. + *

+ * Do not use the {@code equals} method for making access control + * decisions; use the {@code implies} method. + * + * @param obj the object we are testing for equality with this object. + * @return true if both Permission objects are equivalent. + */ + @Override + public boolean equals(Object obj) { + return false; + } + + /** + * Returns the actions as a String. This is abstract + * so subclasses can defer creating a String representation until + * one is needed. Subclasses should always return actions in what they + * consider to be their + * canonical form. For example, two FilePermission objects created via + * the following: + *

+ *

+	 *   perm1 = new FilePermission(p1,"read,write");
+	 *   perm2 = new FilePermission(p2,"write,read");
+	 * 
+ *

+ * both return + * "read,write" when the {code getActions()} method is invoked. + * + * @return the actions of this Permission. + */ + @Override + public String getActions() { + return null; + } + + /** + * Returns the hash code value for this Permission object. + *

+ * The required {@code hashCode} behavior for Permission Objects is + * the following:

+ *

    + *
  • Whenever it is invoked on the same Permission object more than + * once during an execution of a Java application, the + * {@code hashCode} method + * must consistently return the same integer. This integer need not + * remain consistent from one execution of an application to another + * execution of the same application.

    + *

  • If two Permission objects are equal according to the {@code equals} + * method, then calling the {@code hashCode} method on each of the + * two Permission objects must produce the same integer result. + *
+ * + * @return a hash code value for this object. + */ + @Override + public int hashCode() { + return 0; + } + + /** + * Checks if the specified permission's actions are "implied by" + * this object's actions. + *

+ * This must be implemented by subclasses of Permission, as they are the + * only ones that can impose semantics on a Permission object. + *

+ *

The {@code implies} method is used by the AccessController to determine + * whether or not a requested permission is implied by another permission that + * is known to be valid in the current execution context. + * + * @param permission the permission to check against. + * @return true if the specified permission is implied by this object, + * false if not. + */ + @Override + public boolean implies(java.security.Permission permission) { + return false; + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodeSecurityManager.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodeSecurityManager.java new file mode 100644 index 0000000..3eb2988 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodeSecurityManager.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.security; + + +import net.sf.robocode.host.IHostedThread; +import net.sf.robocode.host.IThreadManager; +import net.sf.robocode.io.RobocodeProperties; + +import java.security.AccessControlException; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + * @author Pavel Savara (contributor) + */ +public class RobocodeSecurityManager extends SecurityManager { + + private final IThreadManager threadManager; + + public RobocodeSecurityManager(IThreadManager threadManager) { + super(); + this.threadManager = threadManager; + + ThreadGroup tg = Thread.currentThread().getThreadGroup(); + + while (tg != null) { + threadManager.addSafeThreadGroup(tg); + tg = tg.getParent(); + } + // We need to exercise it in order to load all used classes on this thread + isSafeThread(Thread.currentThread()); + if (RobocodeProperties.isSecurityOn()) { + System.setSecurityManager(this); + } + } + + @Override + public void checkAccess(Thread t) { + if (RobocodeProperties.isSecurityOff()) { + return; + } + + Thread c = Thread.currentThread(); + + if (isSafeThread(c)) { + return; + } + super.checkAccess(t); + + // Threads belonging to other thread groups is not allowed to access threads belonging to other thread groups + // Bug fix [3021140] Possible for robot to kill other robot threads. + // In the following the thread group of the current thread must be in the thread group hierarchy of the + // attacker thread; otherwise an AccessControlException must be thrown. + + boolean found = false; + + ThreadGroup cg = c.getThreadGroup(); + ThreadGroup tg = t.getThreadGroup(); + + while (tg != null) { + if (tg == cg) { + found = true; + break; + } + try { + tg = tg.getParent(); + } catch (AccessControlException e) { + // We expect an AccessControlException due to missing RuntimePermission modifyThreadGroup + break; + } + } + if (!found) { + String message = "Preventing " + c.getName() + " from access to " + t.getName(); + IHostedThread robotProxy = threadManager.getLoadedOrLoadingRobotProxy(c); + + if (robotProxy != null) { + robotProxy.punishSecurityViolation(message); + } + throw new AccessControlException(message); + } + } + + @Override + public void checkAccess(ThreadGroup g) { + if (RobocodeProperties.isSecurityOff()) { + return; + } + Thread c = Thread.currentThread(); + + if (isSafeThread(c)) { + return; + } + super.checkAccess(g); + + final ThreadGroup cg = c.getThreadGroup(); + + if (cg == null) { + // What the heck is going on here? JDK 1.3 is sending me a dead thread. + // This crashes the entire jvm if I don't return here. + return; + } + + IHostedThread robotProxy = threadManager.getLoadedOrLoadingRobotProxy(c); + + if (robotProxy == null) { + throw new AccessControlException("Preventing " + c.getName() + " from access to " + g.getName()); + } + + if (cg.activeCount() > 5) { + String message = "Robots are only allowed to create up to 5 threads!"; + + robotProxy.punishSecurityViolation(message); + throw new AccessControlException(message); + } + } + + private boolean isSafeThread(Thread c) { + return threadManager.isSafeThread(c); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodeSecurityPolicy.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodeSecurityPolicy.java new file mode 100644 index 0000000..0a278b9 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobocodeSecurityPolicy.java @@ -0,0 +1,322 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.security; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.host.IHostedThread; +import net.sf.robocode.host.IThreadManager; +import net.sf.robocode.host.io.RobotFileSystemManager; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import net.sf.robocode.repository.IRepositoryManager; + +import java.io.File; +import java.io.FilePermission; +import java.io.IOException; +import java.net.MalformedURLException; +import java.security.*; +import java.util.*; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + * @author Pavel Savara (contributor) + */ +public class RobocodeSecurityPolicy extends Policy { + private static final boolean isFileReadSecutityOff = System.getProperty("OVERRIDEFILEREADSECURITY", "false").equals( + "true"); + private static final boolean isExperimental = System.getProperty("EXPERIMENTAL", "false").equals("true"); + private final Set allowedPackages = new HashSet(); + + private final Policy parentPolicy; + private final PermissionCollection allPermissions; + private Set untrustedCodeUrls; + + private final IThreadManager threadManager; + + public RobocodeSecurityPolicy(IThreadManager threadManager) { + this.parentPolicy = Policy.getPolicy(); + this.allPermissions = new Permissions(); + this.allPermissions.add(new AllPermission()); + this.threadManager = threadManager; + + allowedPackages.add("robocode.util"); + allowedPackages.add("robocode.robotinterfaces"); + allowedPackages.add("robocode.robotpaint"); + allowedPackages.add("robocode.robocodeGL"); + if (isExperimental) { + allowedPackages.add("robocode.robotinterfaces.peer"); + } + + initUrls(); + + if (RobocodeProperties.isSecurityOn()) { + Policy.setPolicy(this); + } + } + + @Override + public PermissionCollection getPermissions(ProtectionDomain domain) { + return getPermissions(domain.getCodeSource()); + } + + @Override + public PermissionCollection getPermissions(final CodeSource codeSource) { + if (RobocodeProperties.isSecurityOff()) { + return allPermissions; + } + + final String source = codeSource.getLocation().toString(); + + if (untrustedCodeUrls.contains(source)) { + return new Permissions(); + } + + return AccessController.doPrivileged(new PrivilegedAction() { + public PermissionCollection run() { + return parentPolicy.getPermissions(codeSource); + } + }); + } + + @Override + public boolean implies(ProtectionDomain domain, final Permission permission) { + if (RobocodeProperties.isSecurityOff()) { + return true; + } + final String source = domain.getCodeSource().getLocation().toString(); + + if (!untrustedCodeUrls.contains(source)) { + return true; + } + + return AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return impliesRobot(permission); + } + }); + } + + private boolean impliesRobot(Permission perm) { + // For development purposes, allow read any file if override is set. + final String actions = perm.getActions(); + final String name = perm.getName(); + + if (perm instanceof FilePermission && actions.equals("read") && isFileReadSecutityOff) { + return true; + } + + // Allow reading of properties. + if (perm instanceof PropertyPermission && actions.equals("read")) { + return true; + } + + if (perm instanceof RobocodePermission) { + if (name.equals("System.out") || name.equals("System.err") || name.equals("System.in")) { + return true; + } + } + + // Ok, we need to figure out who our robot is. + Thread c = Thread.currentThread(); + + IHostedThread robotProxy = threadManager.getLoadedOrLoadingRobotProxy(c); + + if (robotProxy == null) { + Logger.logError("Preventing unknown thread " + Thread.currentThread().getName() + " from access: " + perm); + return false; + } + + // Attempt to stop the window from displaying + if (perm instanceof java.awt.AWTPermission) { + final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm; + + robotProxy.punishSecurityViolation(message); + + // this is hack, because security exception is not enough + throw new ThreadDeath(); + } + + // FilePermission access request. + if (perm instanceof FilePermission) { + FilePermission filePermission = (FilePermission) perm; + // Get the fileSystemManager + RobotFileSystemManager fileSystemManager = robotProxy.getRobotFileSystemManager(); + + // Robot wants access to read something + if (filePermission.getActions().equals("read")) { + return impliesRobotFileRead(robotProxy, fileSystemManager, filePermission); + + } // Robot wants access to write something + else if (filePermission.getActions().equals("write")) { + return impliesRobotFileWrite(robotProxy, fileSystemManager, filePermission); + + } // Robot wants access to write something + else if (filePermission.getActions().equals("delete")) { + return impliesRobotFileDelete(robotProxy, fileSystemManager, filePermission); + + } + } + + // check package access + if (perm instanceof RuntimePermission && name.startsWith("accessClassInPackage.")) { + return impliesRobotPackageAccess(robotProxy, name.substring(21)); + } + + // Permission denied. + final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + perm; + + robotProxy.punishSecurityViolation(message); + return false; + } + + private boolean impliesRobotPackageAccess(IHostedThread robotProxy, String packageName) { + if (packageName.startsWith("robocode.control") || packageName.startsWith("net.sf.robocode")) { + if (allowedPackages.contains(packageName)) { + return true; + } + final String message = "Preventing " + Thread.currentThread().getName() + + " from access to the internal Robocode package: " + packageName; + + robotProxy.punishSecurityViolation(message); + return false; + } + return true; + } + + private boolean impliesRobotFileDelete(IHostedThread robotProxy, RobotFileSystemManager fileSystemManager, FilePermission filePermission) { + // If there is no writable directory, deny access + if (fileSystemManager.getWritableDirectory() == null) { + final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission + + ". Robots that are not in a package may not delete any files."; + + robotProxy.punishSecurityViolation(message); + return false; + } + // If this is a writable file, permit access + if (fileSystemManager.isWritable(filePermission.getName())) { + return true; + } // else it's not writable, deny access. + + // We are deleting our data directory. + if (fileSystemManager.getWritableDirectory().toString().equals(filePermission.getName())) { + return true; + } + // Not a writable directory. + final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission + + ". You may only delete files in your own data directory: " + fileSystemManager.getWritableDirectory(); + + robotProxy.punishSecurityViolation(message); + return false; + } + + private boolean impliesRobotFileWrite(IHostedThread robotProxy, RobotFileSystemManager fileSystemManager, FilePermission filePermission) { + // There isn't one. Deny access. + if (!threadManager.checkRobotFileStream()) { + final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission + + ". You must use a RobocodeOutputStream."; + + robotProxy.punishSecurityViolation(message); + return false; + } + + // If there is no writable directory, deny access + if (fileSystemManager.getWritableDirectory() == null) { + final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission + + ". Robots that are not in a package may not write any files."; + + robotProxy.punishSecurityViolation(message); + return false; + } + // If this is a writable file, permit access + if (fileSystemManager.isWritable(filePermission.getName())) { + return true; + } // else it's not writable, deny access. + + // We are creating the directory. + if (fileSystemManager.getWritableDirectory().toString().equals(filePermission.getName())) { + return true; + } + // Not a writable directory. + final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission + + ". You may only write files in your own data directory: " + fileSystemManager.getWritableDirectory(); + + robotProxy.punishSecurityViolation(message); + return false; + } + + private boolean impliesRobotFileRead(IHostedThread robotProxy, RobotFileSystemManager fileSystemManager, FilePermission filePermission) { + // If there is no readable directory, deny access. + if (fileSystemManager.getReadableDirectory() == null) { + final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission + + ". Robots that are not in a package may not read any files."; + + robotProxy.punishSecurityViolation(message); + return false; + } + // If this is a writtable file, return. + if (fileSystemManager.isWritable(filePermission.getName())) { + return true; + } + // If this is a readable file, return. + if (fileSystemManager.isReadable(filePermission.getName())) { + return true; + } + // Else disable robot + final String message = "Preventing " + robotProxy.getStatics().getName() + " from access: " + filePermission + + ". You may only read files in your own root package directory."; + + robotProxy.punishSecurityViolation(message); + return false; + } + + @Override + public void refresh() { + initUrls(); + parentPolicy.refresh(); + } + + private void initUrls() { + untrustedCodeUrls = new HashSet(); + untrustedCodeUrls.add(RobotClassLoader.UNTRUSTED_URL); + + String classPath = System.getProperty("robocode.class.path"); + StringTokenizer tokenizer = new StringTokenizer(classPath, File.pathSeparator); + + // TODO load URLs from new repository roots, don't forget about all robot .jar files + // TODO or check it directly against repository ? + try { + final List robots = new ArrayList(); + IRepositoryManager repositoryManager = Container.getComponent(IRepositoryManager.class); + + if (repositoryManager != null) { + robots.add(repositoryManager.getRobotsDirectory().toURI().toString()); + for (File devel : repositoryManager.getDevelDirectories()) { + robots.add(devel.toURI().toString()); + } + } + + while (tokenizer.hasMoreTokens()) { + String u = new File(tokenizer.nextToken()).getCanonicalFile().toURI().toString(); + + if (robots.contains(u)) { + if (!untrustedCodeUrls.contains(u)) { + untrustedCodeUrls.add(u); + } + } + } + } catch (MalformedURLException e) { + Logger.logError(e); + } catch (IOException e) { + Logger.logError(e); + } + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotThreadManager.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotThreadManager.java new file mode 100644 index 0000000..d409324 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/RobotThreadManager.java @@ -0,0 +1,343 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.security; + + +import net.sf.robocode.host.IHostedThread; +import net.sf.robocode.host.IThreadManager; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import static net.sf.robocode.io.Logger.logError; +import static net.sf.robocode.io.Logger.logMessage; +import static net.sf.robocode.io.Logger.logWarning; +import robocode.exception.RobotException; + +import java.lang.reflect.InvocationTargetException; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.HashMap; +import java.util.Map; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Pavel Savara (contributor) + */ +public class RobotThreadManager { + + private final IHostedThread robotProxy; + private Thread runThread; + private ThreadGroup runThreadGroup; + private Object awtForThreadGroup; + private final Map disposeAppContextThreadMap = new HashMap(); + + public RobotThreadManager(IHostedThread robotProxy) { + this.robotProxy = robotProxy; + createThreadGroup(); + } + + public void cleanup() { + try { + if (runThread == null || !runThread.isAlive()) { + if (!discardAWT()) { + runThreadGroup.destroy(); + } + } else { + Logger.logWarning("Could not destroy " + runThread.getName()); + } + } catch (Exception e) { + Logger.logError("Could not destroy " + runThreadGroup.getName(), e); + } + } + + public void initAWT() { + if (awtForThreadGroup == null) { + awtForThreadGroup = AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return createNewAppContext(); + } + }); + } + } + + private boolean discardAWT() { + boolean res = false; + + if (awtForThreadGroup != null && !(awtForThreadGroup instanceof Integer)) { + res = disposeAppContext(awtForThreadGroup); + awtForThreadGroup = null; + } + return res; + } + + public void checkRunThread() { + if (Thread.currentThread() != runThread) { + throw new RobotException("You cannot take action in this thread!"); + } + } + + public void start(IThreadManager threadManager) { + try { + threadManager.addThreadGroup(runThreadGroup, robotProxy); + + runThread = new Thread(runThreadGroup, robotProxy, robotProxy.getStatics().getName()); + runThread.setDaemon(true); + runThread.setPriority(Thread.NORM_PRIORITY - 1); + runThread.setContextClassLoader(this.robotProxy.getRobotClassloader()); + runThread.start(); + } catch (Exception e) { + logError("Exception starting thread", e); + } + } + + /** + * @return true as peaceful stop + */ + public boolean waitForStop() { + boolean isAlive = false; + + if (runThread != null && runThread.isAlive()) { + runThread.interrupt(); + waitForStop(runThread); + isAlive = runThread.isAlive(); + } + + Thread[] threads = new Thread[100]; + + runThreadGroup.enumerate(threads); + + for (Thread thread : threads) { + if (thread != null && thread != runThread && thread.isAlive()) { + thread.interrupt(); + waitForStop(thread); + isAlive |= thread.isAlive(); + } + } + + if (isAlive) { + if (RobocodeProperties.isSecurityOn()) { + logError("Robot " + robotProxy.getStatics().getName() + " is not stopping. Forcing a stop."); + + // Force the robot to stop + return forceStop(); + } else { + logError( + "Robot " + robotProxy.getStatics().getName() + + " is still running. Not stopping it because security is off."); + } + } + + return true; + } + + /** + * @return true as peaceful stop + */ + public boolean forceStop() { + int res = stopSteps(runThread); + + Thread[] threads = new Thread[100]; + + runThreadGroup.enumerate(threads); + + for (Thread thread : threads) { + if (thread != null && thread != runThread && thread.isAlive()) { + res += stopSteps(thread); + } + } + if (res > 0) { + robotProxy.println("SYSTEM: This robot has been stopped. No score will be generated."); + + // recycle thread group + createThreadGroup(); + } + runThread = null; + return res == 0; + } + + /** + * @param t thread to stop + * @return 0 as peaceful stop + */ + private int stopSteps(Thread t) { + if (t != null && t.isAlive()) { + interrupt(t); + if (t.isAlive()) { + stop(t); + } + if (t.isAlive()) { + // noinspection deprecation + // t.suspend(); + logWarning("Unable to stop thread: " + runThread.getName()); + } else { + logMessage(robotProxy.getStatics().getName() + " has been stopped."); + } + return 1; + } + return 0; + } + + @SuppressWarnings("deprecation") + private void stop(Thread t) { + if (t != null) { + // noinspection deprecation + t.stop(); + try { + t.join(1500); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + } + } + } + + private void interrupt(Thread t) { + if (t != null) { + try { + t.setPriority(Thread.MIN_PRIORITY); + } catch (NullPointerException e) { + logError("Sometimes this occurs in the Java core?!", e); + } + t.interrupt(); + try { + t.join(500); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + } + } + } + + private void waitForStop(Thread thread) { + for (int j = 0; j < 100 && thread.isAlive(); j++) { + if (j == 50) { + logMessage( + "Waiting for robot " + robotProxy.getStatics().getName() + " to stop thread " + thread.getName()); + } + try { + Thread.sleep(10); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + break; // We are in a loop + } + } + } + + private void createThreadGroup() { + runThreadGroup = new ThreadGroup(robotProxy.getStatics().getName()); + + // bit lower than battle have + runThreadGroup.setMaxPriority(Thread.NORM_PRIORITY - 1); + } + + private Object createNewAppContext() { + // Add the current thread to our disposeAppContextThreadMap if it does not exit already + if (!disposeAppContextThreadMap.containsKey(Thread.currentThread())) { + disposeAppContextThreadMap.put(Thread.currentThread(), new Disposal()); + } + + // same as SunToolkit.createNewAppContext(); + // we can't assume that we are always on Suns JVM, so we can't reference it directly + // why we call that ? Because SunToolkit is caching AWTQueue instance form main thread group and use it on robots threads + // and he is not asking us for checkAwtEventQueueAccess above + try { + final Class sunToolkit = ClassLoader.getSystemClassLoader().loadClass("sun.awt.SunToolkit"); + + // We need to wait for the sun.awt.AppContext.dispose() to complete for the current thread before creating + // a new AppContext for it. Otherwise the AWT EventQueue fires events like WINDOW_CLOSE to our main window + // which closes the entire application due to a System.exit() + + Disposal disposal = disposeAppContextThreadMap.get(Thread.currentThread()); + + synchronized (disposal) { + while (disposal.isDisposing) { + try { + disposal.wait(); + } catch (InterruptedException e) { + return -1; + } + } + } + + // Call sun.awt.SunToolkit.createNewAppContext() to create a new AppContext for the current thread + return sunToolkit.getDeclaredMethod("createNewAppContext").invoke(null); + + } catch (ClassNotFoundException e) { + // we are not on sun JVM + return -1; + } catch (NoSuchMethodException e) { + throw new Error("Looks like SunVM but unable to assure secured AWTQueue, sorry", e); + } catch (InvocationTargetException e) { + throw new Error("Looks like SunVM but unable to assure secured AWTQueue, sorry", e); + } catch (IllegalAccessException e) { + throw new Error("Looks like SunVM but unable to assure secured AWTQueue, sorry", e); + } + // end: same as SunToolkit.createNewAppContext(); + } + + private boolean disposeAppContext(final Object appContext) { + // This method should must not be used when the AWT is running in headless mode! + // Bugfix [2833271] IllegalThreadStateException with the AWT-Shutdown thread. + // Read more about headless mode here: + // http://java.sun.com/developer/technicalArticles/J2SE/Desktop/headless/ + + // This check makes sure we exit, if the AWT is running in headless mode + if (System.getProperty("java.awt.headless", "false").equals("true")) { + return false; + } + + // same as AppContext.dispose(); + try { + final Class sunToolkit = ClassLoader.getSystemClassLoader().loadClass("sun.awt.AppContext"); + + // We run this in a thread, as invoking the AppContext.dispose() method sometimes takes several + // seconds, and thus causes the cleanup of a battle to hang, which is annoying when trying to restart + // a battle. + new Thread(new Runnable() { + public void run() { + Disposal disposal = disposeAppContextThreadMap.get(Thread.currentThread()); + + try { + // Signal that the AppContext for the current thread is being disposed (start) + if (disposal != null) { + synchronized (disposal) { + disposal.isDisposing = true; + disposal.notifyAll(); + } + } + // Call sun.awt.AppContext.dispose(appContext) to dispose the AppContext for the current thread + sunToolkit.getDeclaredMethod("dispose").invoke(appContext); + + } catch (Exception e) { + logError(e); + } finally { + // Signal that the AppContext for the current thread has been disposed (finish) + if (disposal != null) { + synchronized (disposal) { + disposal.isDisposing = false; + disposal.notifyAll(); + } + } + } + } + }, "DisposeAppContext").start(); + + return true; + } catch (ClassNotFoundException e) { + logError(e); + } + return false; + // end: same as AppContext.dispose(); + } + + private static class Disposal { + boolean isDisposing; + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/SecureInputStream.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/SecureInputStream.java new file mode 100644 index 0000000..4a04866 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/SecureInputStream.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.security; + + +import java.io.IOException; +import java.io.InputStream; +import java.security.AccessController; + + +/** + * @author Mathew A. Nelson (original) + */ +public class SecureInputStream extends java.io.InputStream { + private RobocodePermission inputPermission = null; + private InputStream in = null; + + /** + * SecureInputStream constructor comment. + * + * @param in original + */ + public SecureInputStream(InputStream in) { + super(); + this.in = in; + this.inputPermission = new RobocodePermission("System.in"); + } + + @Override + public final int available() throws IOException { + checkAccess(); + return in.available(); + } + + private void checkAccess() { + AccessController.checkPermission(inputPermission); + } + + @Override + public final void close() throws IOException { + checkAccess(); + in.close(); + } + + @Override + public final synchronized void mark(int readlimit) { + checkAccess(); + in.mark(readlimit); + } + + @Override + public final boolean markSupported() { + checkAccess(); + return in.markSupported(); + } + + /** + * Reads the next byte of data from the input stream. The value byte is + * returned as an {@code int} in the range 0 to 255. If no byte is available + * because the end of the stream has been reached, the value -1 is returned. + * This method blocks until input data is available, the end of the stream + * is detected, or an exception is thrown. + *

+ *

A subclass must provide an implementation of this method. + * + * @return the next byte of data, or -1 if the end of the stream is reached. + * @throws IOException if an I/O error occurs. + */ + @Override + public final int read() throws java.io.IOException { + checkAccess(); + return in.read(); + } + + @Override + public final int read(byte[] b) throws IOException { + checkAccess(); + return in.read(b); + } + + @Override + public final int read(byte[] b, int off, int len) throws IOException { + checkAccess(); + return in.read(b, off, len); + } + + @Override + public final synchronized void reset() throws IOException { + checkAccess(); + in.reset(); + } + + @Override + public final long skip(long n) throws IOException { + checkAccess(); + return in.skip(n); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/SecurePrintStream.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/SecurePrintStream.java new file mode 100644 index 0000000..730bcd7 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/SecurePrintStream.java @@ -0,0 +1,293 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.security; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.host.IHostManager; + +import java.io.OutputStream; +import java.io.PrintStream; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class SecurePrintStream extends PrintStream { + + public SecurePrintStream(OutputStream out, boolean autoFlush) { + super(out, autoFlush); + } + + @Override + public final boolean checkError() { + PrintStream out = checkAccess(); + + return (out == this) ? super.checkError() : out.checkError(); + } + + @Override + public final void close() { + PrintStream out = checkAccess(); + + if (out == this) { + super.close(); + } else { + out.close(); + } + } + + @Override + public final void flush() { + PrintStream out = checkAccess(); + + if (out == this) { + super.flush(); + } else { + out.flush(); + } + } + + @Override + public final void print(char[] s) { + PrintStream out = checkAccess(); + + if (out == this) { + super.print(s); + } else { + out.print(s); + } + } + + @Override + public final void print(char c) { + PrintStream out = checkAccess(); + + if (out == this) { + super.print(c); + } else { + out.print(c); + } + } + + @Override + public final void print(double d) { + PrintStream out = checkAccess(); + + if (out == this) { + super.print(d); + } else { + out.print(d); + } + } + + @Override + public final void print(float f) { + PrintStream out = checkAccess(); + + if (out == this) { + super.print(f); + } else { + out.print(f); + } + } + + @Override + public final void print(int i) { + PrintStream out = checkAccess(); + + if (out == this) { + super.print(i); + } else { + out.print(i); + } + } + + @Override + public final void print(long l) { + PrintStream out = checkAccess(); + + if (out == this) { + super.print(l); + } else { + out.print(l); + } + } + + @Override + public final void print(Object obj) { + PrintStream out = checkAccess(); + + if (out == this) { + super.print(obj); + } else { + out.print(obj); + } + } + + @Override + public final void print(String s) { + PrintStream out = checkAccess(); + + if (out == this) { + super.print(s); + } else { + out.print(s); + } + } + + @Override + public final void print(boolean b) { + PrintStream out = checkAccess(); + + if (out == this) { + super.print(b); + } else { + out.print(b); + } + } + + @Override + public final void println() { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(); + } else { + out.println(); + } + } + + @Override + public final void println(char[] x) { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(x); + } else { + out.println(x); + } + } + + @Override + public final void println(char x) { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(x); + } else { + out.println(x); + } + } + + @Override + public final void println(double x) { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(x); + } else { + out.println(x); + } + } + + @Override + public final void println(float x) { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(x); + } else { + out.println(x); + } + } + + @Override + public final void println(int x) { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(x); + } else { + out.println(x); + } + } + + @Override + public final void println(long x) { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(x); + } else { + out.println(x); + } + } + + @Override + public final void println(Object x) { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(x); + } else { + out.println(x); + } + } + + @Override + public final void println(String x) { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(x); + } else { + out.println(x); + } + } + + @Override + public final void println(boolean x) { + PrintStream out = checkAccess(); + + if (out == this) { + super.println(x); + } else { + out.println(x); + } + } + + @Override + public final void write(byte[] buf, int off, int len) { + PrintStream out = checkAccess(); + + if (out == this) { + super.write(buf, off, len); + } else { + out.write(buf, off, len); + } + } + + @Override + public final void write(int b) { + PrintStream out = checkAccess(); + + if (out == this) { + super.write(b); + } else { + out.write(b); + } + } + + private PrintStream checkAccess() { + PrintStream out = Container.getComponent(IHostManager.class).getRobotOutputStream(); + + return (out == null) ? this : out; + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/ThreadManager.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/ThreadManager.java new file mode 100644 index 0000000..6e47b48 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/security/ThreadManager.java @@ -0,0 +1,213 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.security; + + +import net.sf.robocode.host.IHostedThread; +import net.sf.robocode.host.IThreadManager; +import net.sf.robocode.host.io.RobotFileOutputStream; +import net.sf.robocode.host.io.RobotFileSystemManager; +import robocode.exception.RobotException; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.security.AccessController; +import java.security.PrivilegedAction; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +public class ThreadManager implements IThreadManager { + + private final PrintStream syserr = System.err; + + private final List safeThreads = new CopyOnWriteArrayList(); + private final List safeThreadGroups = new CopyOnWriteArrayList(); + private final List groups = new CopyOnWriteArrayList(); + private final List outputStreamThreads = new CopyOnWriteArrayList(); + private final List robots = new CopyOnWriteArrayList(); + + private Thread robotLoaderThread; + private IHostedThread loadingRobot; + + public ThreadManager() {} + + public void addSafeThread(Thread safeThread) { + safeThreads.add(safeThread); + } + + public void removeSafeThread(Thread safeThread) { + safeThreads.remove(safeThread); + } + + public void addSafeThreadGroup(ThreadGroup safeThreadGroup) { + safeThreadGroups.add(safeThreadGroup); + } + + public void addThreadGroup(ThreadGroup g, IHostedThread robotProxy) { + if (!groups.contains(g)) { + groups.add(g); + robots.add(robotProxy); + } + } + + public synchronized IHostedThread getLoadingRobot() { + return loadingRobot; + } + + public synchronized IHostedThread getLoadingRobotProxy(Thread t) { + if (t != null && robotLoaderThread != null + && (t.equals(robotLoaderThread) + || (t.getThreadGroup() != null && t.getThreadGroup().equals(robotLoaderThread.getThreadGroup())))) { + return loadingRobot; + } + return null; + } + + public synchronized IHostedThread getLoadedOrLoadingRobotProxy(Thread t) { + IHostedThread robotProxy = getRobotProxy(t); + + if (robotProxy == null) { + robotProxy = getLoadingRobotProxy(t); + } + return robotProxy; + } + + public IHostedThread getRobotProxy(Thread t) { + ThreadGroup g = t.getThreadGroup(); + + if (g == null) { + return null; + } + int index = groups.indexOf(g); + + if (index == -1) { + return null; + } + return robots.get(index); + } + + public void reset() { + groups.clear(); + robots.clear(); + } + + public synchronized void setLoadingRobot(IHostedThread newLoadingRobotProxy) { + if (newLoadingRobotProxy == null) { + this.robotLoaderThread = null; + loadingRobot = null; + } else { + this.robotLoaderThread = Thread.currentThread(); + loadingRobot = newLoadingRobotProxy; + } + } + + public boolean isSafeThread() { + return isSafeThread(Thread.currentThread()); + } + + public FileOutputStream createRobotFileStream(String fileName, boolean append) throws IOException { + final Thread c = Thread.currentThread(); + + final IHostedThread robotProxy = getRobotProxy(c); + + if (robotProxy == null) { + syserr.println("RobotProxy is null"); + return null; + } + if (!robotProxy.getStatics().isAdvancedRobot()) { + throw new RobotException("Only advanced robots could create files"); + } + + final File dir = robotProxy.getRobotFileSystemManager().getWritableDirectory(); + + if (!dir.exists()) { + robotProxy.println("SYSTEM: Creating a data directory for you."); + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + outputStreamThreads.add(c); + if (!dir.exists() && !dir.mkdirs()) { + syserr.println("Can't create dir " + dir.toString()); + } + return null; + } + }); + } + + final RobotFileSystemManager fileSystemManager = robotProxy.getRobotFileSystemManager(); + + File f = new File(fileName); + long len; + + if (f.exists()) { + len = f.length(); + } else { + fileSystemManager.checkQuota(); + len = 0; + } + + if (!append) { + fileSystemManager.adjustQuota(-len); + } + + outputStreamThreads.add(c); + return new RobotFileOutputStream(fileName, append, fileSystemManager); + } + + public boolean checkRobotFileStream() { + final Thread c = Thread.currentThread(); + + synchronized (outputStreamThreads) { + if (outputStreamThreads.contains(c)) { + outputStreamThreads.remove(c); + return true; + } + } + return false; + } + + public boolean isSafeThread(Thread c) { + try { + if (safeThreads.contains(c)) { + return true; + } + + for (ThreadGroup tg : safeThreadGroups) { + if (c.getThreadGroup() == tg) { + safeThreads.add(c); + return true; + } + } + + return false; + } catch (Exception e) { + syserr.println("Exception checking safe thread: "); + e.printStackTrace(syserr); + return false; + } + } + + public PrintStream getRobotOutputStream() { + Thread c = Thread.currentThread(); + + if (isSafeThread(c)) { + return null; + } + + IHostedThread robotProxy = getLoadedOrLoadingRobotProxy(c); + + return (robotProxy != null) ? robotProxy.getOut() : null; + } +} diff --git a/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/serialization/RobocodeObjectInputStream.java b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/serialization/RobocodeObjectInputStream.java new file mode 100644 index 0000000..fd4824c --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/main/java/net/sf/robocode/host/serialization/RobocodeObjectInputStream.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.serialization; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectStreamClass; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobocodeObjectInputStream extends ObjectInputStream { + + private ClassLoader classLoader; + + public RobocodeObjectInputStream(InputStream in, ClassLoader classLoader) throws IOException { + super(in); + this.classLoader = classLoader; + } + + @Override + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { + String name = desc.getName(); + + try { + return Class.forName(name, false, classLoader); + } catch (ClassNotFoundException ex) { + return super.resolveClass(desc); + } + } +} diff --git a/代码/workspace_robo4/robocode.host/src/test/java/net/sf/robocode/host/jarjar/JarJarTest.java b/代码/workspace_robo4/robocode.host/src/test/java/net/sf/robocode/host/jarjar/JarJarTest.java new file mode 100644 index 0000000..6cf90e1 --- /dev/null +++ b/代码/workspace_robo4/robocode.host/src/test/java/net/sf/robocode/host/jarjar/JarJarTest.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.host.jarjar; + + +import org.junit.Test; +import org.junit.Assert; + +import java.net.URL; +import java.net.URLConnection; +import java.net.URLClassLoader; +import java.io.InputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +import net.sf.robocode.io.URLJarCollector; +import net.sf.robocode.io.JarJar; + + +/** + * @author Pavel Savara (original) + */ +public class JarJarTest { + static { + JarJarURLConnection.register(); + } + + @Test + public void run() throws IOException { + + String clas = "Hello.class"; + String inner = "Inner.jar"; + String outer = "file:src/test/resources/Outer.jar"; + + final String separ = "!/"; + URL u = new URL("jar:jarjar:" + outer + JarJar.SEPARATOR + inner + separ + clas); + final URLConnection urlConnection = URLJarCollector.openConnection(u); + final InputStream inputStream = urlConnection.getInputStream(); + InputStreamReader isr = new InputStreamReader(inputStream); + char[] c = new char[4]; + + int len = isr.read(c); + + Assert.assertEquals(len, 4); + Assert.assertEquals('T', c[0]); + Assert.assertEquals('e', c[1]); + Assert.assertEquals('s', c[2]); + Assert.assertEquals('t', c[3]); + Assert.assertFalse(isr.ready()); + isr.close(); + inputStream.close(); + } + + @Test + public void runClassLoader() throws IOException, ClassNotFoundException { + String clas = "tested.robots.Ahead"; + String inner = "Inner.jar"; + String outer = "file:src/test/resources/Outer.jar"; + final String separ = "!/"; + final String root = "jar:jarjar:" + outer + JarJar.SEPARATOR + inner + separ; + URL u = new URL(root); + + ClassLoader ucl = new URLClassLoader(new URL[] { u}); + + ucl.loadClass(clas); + } +} diff --git a/代码/workspace_robo4/robocode.host/src/test/resources/Outer.jar b/代码/workspace_robo4/robocode.host/src/test/resources/Outer.jar new file mode 100644 index 0000000000000000000000000000000000000000..4b539ff162e604aedc14b2f2c7639013f92064c8 GIT binary patch literal 611 zcmWIWW@Zs#U|`^2Si_NFHPUM}PD=QKUbM{h>8`NX=2vXfP4z4;-uG^yJ4y|{D5-L!s3&mq2qdsbPd?cpWMa^} zgNcoar=dbhImqCkNg}@n2gA*6vjw9!uvTntnqs_xX`y1kQFpfqTNwhp8JR>FaHk7k b(f|SlFo~2(0=!w-Kw^wQXbz;sm_R%L@}U0s literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.iml b/代码/workspace_robo4/robocode.iml new file mode 100644 index 0000000..aaf2c03 --- /dev/null +++ b/代码/workspace_robo4/robocode.iml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.installer/.classpath b/代码/workspace_robo4/robocode.installer/.classpath new file mode 100644 index 0000000..faff71b --- /dev/null +++ b/代码/workspace_robo4/robocode.installer/.classpath @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.installer/.project b/代码/workspace_robo4/robocode.installer/.project new file mode 100644 index 0000000..c76d339 --- /dev/null +++ b/代码/workspace_robo4/robocode.installer/.project @@ -0,0 +1,14 @@ + + + robocode.installer + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.installer/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.installer/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.installer/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.installer/pom.xml b/代码/workspace_robo4/robocode.installer/pom.xml new file mode 100644 index 0000000..d9e283c --- /dev/null +++ b/代码/workspace_robo4/robocode.installer/pom.xml @@ -0,0 +1,27 @@ + + + 4.0.0 + robocode.installer + Robocode Installer + + net.sf.robocode + robocode + ${robocode.version} + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + net.sf.robocode.installer.AutoExtract + + + + + + + diff --git a/代码/workspace_robo4/robocode.installer/robocode.installer.iml b/代码/workspace_robo4/robocode.installer/robocode.installer.iml new file mode 100644 index 0000000..613ddb1 --- /dev/null +++ b/代码/workspace_robo4/robocode.installer/robocode.installer.iml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.ipr b/代码/workspace_robo4/robocode.ipr new file mode 100644 index 0000000..a27683a --- /dev/null +++ b/代码/workspace_robo4/robocode.ipr @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.iws b/代码/workspace_robo4/robocode.iws new file mode 100644 index 0000000..03c854e --- /dev/null +++ b/代码/workspace_robo4/robocode.iws @@ -0,0 +1,418 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.repository/.classpath b/代码/workspace_robo4/robocode.repository/.classpath new file mode 100644 index 0000000..ea90720 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.repository/.project b/代码/workspace_robo4/robocode.repository/.project new file mode 100644 index 0000000..3ea6809 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/.project @@ -0,0 +1,17 @@ + + + robocode.repository + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + robocode.core + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.repository/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.repository/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.repository/pom.xml b/代码/workspace_robo4/robocode.repository/pom.xml new file mode 100644 index 0000000..57259bb --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + robocode.repository + Robocode Repository + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + net.sf.robocode + robocode.core + ${project.version} + + + net.sf.robocode + codesize + 1.1 + + + diff --git a/代码/workspace_robo4/robocode.repository/robocode.repository.iml b/代码/workspace_robo4/robocode.repository/robocode.repository.iml new file mode 100644 index 0000000..6b1701e --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/robocode.repository.iml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/IRepository.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/IRepository.java new file mode 100644 index 0000000..d8401b3 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/IRepository.java @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Map; + +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.root.IRepositoryRoot; + + +/** + * Interface for a repository containing meta-data for robot and team items.

+ * + * Items can be retrieved from the reposition by using {@link IRepository#getItem(String)} using "friendly URLs" + * that identifies the individual item. See {@link IRepositoryItem#getFriendlyURLs()}. An item has typically several + * friendly URLs that identifies it, e.g. a file URL to a local property file or class file, or a URL to a JAR entry. + * + * @author Flemming N. Larsen (original) + */ +public interface IRepository { + + /** + * Loads data into this repository, previously saved by {@link #save(OutputStream)}. + * + * @param in is an input stream used for reading the data. + * + * @see #save(OutputStream) + */ + public void load(InputStream in); + + /** + * Saves the data in this repository to an output stream. + * + * @param out is the output stream used for writing the data. + * + * @see #load(InputStream) + */ + public void save(OutputStream out); + + /** + * Adds or updates an item.

+ * + * If the item is not present in the repository, it will be added; otherwise it will be updated, if the specified + * item has a never version than the existing item in the repository.

+ * + * This method will store the item under each friendly URL (keys) by using {@link IRepositoryItem#getFriendlyURLs()}. + * + * @param item is the item to add or update. + * + * @see #getItem(String) + * @see #getItems() + */ + void addOrUpdateItem(IRepositoryItem item); + + /** + * Returns an item stored in this repository identified by a friendly URL (key). + * + * @param friendlyUrl is a key to the item used when the item was stored using {@link IRepositoryItem#getFriendlyURLs()}. + * @return an item from the repository identified by the friendly URL or null if the item does not exist. + * + * @see #addOrUpdateItem(IRepositoryItem) + * @see #getItems() + */ + IRepositoryItem getItem(String friendlyUrl); + + /** + * Returns all items stored in this repository. + * @return a map containing items, where the keys are friendly URLs used for identifying the items. + * + * @see #getItem(String) + */ + Map getItems(); + + /** + * Returns all repository roots stored in this repository.

+ * + * @return a map containing repository roots, where the keys are URLs used for identifying the individual + * repository root. + * + * @see IRepositoryRoot + */ + Map getRoots(); + + /** + * Removes a repository root from this repository. + * + * @param url is the URL (key) of the repository root to remove. + */ + void removeRoot(String url); + + /** + * Removes all items from this repository that belongs to a specific repository root. + * + * @param root is the repository root containing the items to remove. + */ + void removeItemsFromRoot(IRepositoryRoot root); +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/Module.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/Module.java new file mode 100644 index 0000000..47d1834 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/Module.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import net.sf.robocode.core.BaseModule; +import net.sf.robocode.core.Container; +import net.sf.robocode.repository.items.handlers.ClassHandler; +import net.sf.robocode.repository.items.handlers.PropertiesHandler; +import net.sf.robocode.repository.items.handlers.SourceHandler; +import net.sf.robocode.repository.items.handlers.TeamHandler; +import net.sf.robocode.repository.root.handlers.ClassPathHandler; +import net.sf.robocode.repository.root.handlers.JarHandler; + + +/** + * @author Pavel Savara (original) + */ +public class Module extends BaseModule { + static { + Container.cache.addComponent(IRepositoryManager.class, RepositoryManager.class); + + // file handlers + Container.cache.addComponent("TeamHandler", TeamHandler.class); + Container.cache.addComponent("PropertiesHandler", PropertiesHandler.class); + Container.cache.addComponent("ClassHandler", ClassHandler.class); + Container.cache.addComponent("SourceHandler", SourceHandler.class); + + // root handlers + Container.cache.addComponent("JarHandler", JarHandler.class); + Container.cache.addComponent("ClassPathHandler", ClassPathHandler.class); + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/Repository.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/Repository.java new file mode 100644 index 0000000..cfe3bf1 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/Repository.java @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.root.BaseRoot; +import net.sf.robocode.repository.root.IRepositoryRoot; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * Repository containing robot and team repositoryItems. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +class Repository implements IRepository { + + private Map roots = new ConcurrentHashMap(); + private Map repositoryItems = new ConcurrentHashMap(); + private Map removedItems = new ConcurrentHashMap(); + + /** + * {@inheritDoc} + */ + public void save(OutputStream out) { + Set uniqueItems = new HashSet(); + Set uniqueRoots = new HashSet(); + + for (IRepositoryItem repositoryItem : repositoryItems.values()) { + uniqueItems.add(repositoryItem); + } + + for (IRepositoryRoot root : roots.values()) { + uniqueRoots.add(root); + } + + ObjectOutputStream oos = null; + try { + oos = new ObjectOutputStream(out); + oos.writeObject(uniqueRoots); + oos.writeObject(uniqueItems); + } catch (IOException e) { + Logger.logError("Can't save robot database", e); + } finally { + FileUtil.cleanupStream(oos); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public void load(InputStream in) { + Set uniqueItems; + Set uniqueRoots; + + ObjectInputStream ois = null; + try { + ois = new ObjectInputStream(in); + + uniqueRoots = (Set) ois.readObject(); + uniqueItems = (Set) ois.readObject(); + + for (IRepositoryRoot root : uniqueRoots) { + ((BaseRoot) root).setRepository(this); + + String key = root.getURL().toString(); + key = URLDecoder.decode(key, "UTF-8"); + + roots.put(key, root); + } + for (IRepositoryItem repositoryItem : uniqueItems) { + addOrUpdateItem(repositoryItem); + } + } catch (IOException e) { + Logger.logError("Can't load robot database: " + e.getMessage()); + } catch (ClassNotFoundException e) { + Logger.logError("Can't load robot database: " + e.getMessage()); + } finally { + FileUtil.cleanupStream(ois); + } + } + + /** + * {@inheritDoc} + */ + public void addOrUpdateItem(IRepositoryItem repositoryItem) { + Collection friendlyUrls = repositoryItem.getFriendlyURLs(); + if (friendlyUrls != null) { + // Add or update the item so it can be found using later using any friendly URL + for (String friendly : friendlyUrls) { + if (friendly != null) { + IRepositoryItem existingItem = repositoryItems.get(friendly); + // Add the item if it does not exist already, or update it if the version is newer + // than the existing item. + if (existingItem == null || repositoryItem.compareTo(existingItem) > 0) { + repositoryItems.put(friendly, repositoryItem); + } + } + } + } + } + + /** + * {@inheritDoc} + */ + public IRepositoryItem getItem(String friendlyUrl) { + IRepositoryItem repositoryItem = repositoryItems.get(friendlyUrl); + if (repositoryItem == null) { + repositoryItem = removedItems.get(friendlyUrl); + } + return repositoryItem; + } + + /** + * {@inheritDoc} + */ + public Map getItems() { + return Collections.unmodifiableMap(repositoryItems); + } + + /** + * {@inheritDoc} + */ + public Map getRoots() { + return Collections.unmodifiableMap(roots); + } + + /** + * {@inheritDoc} + */ + public void removeRoot(String friendlyUrl) { + roots.remove(friendlyUrl); + } + + /** + * {@inheritDoc} + */ + public void removeItemsFromRoot(IRepositoryRoot root) { + Collection> itemsToRemove = new ArrayList>(); + + for (Map.Entry entry : repositoryItems.entrySet()) { + if (entry.getValue().getRoot().equals(root)) { + itemsToRemove.add(entry); + } + } + + for (Map.Entry entry : itemsToRemove) { + String key = entry.getKey(); + + removedItems.put(key, entry.getValue()); + repositoryItems.remove(key); + } + } + + /** + * Replaces the repository roots with new repository roots. + * + * @param newRoots is the new repository roots for this repository. + */ + // Only for the RepositoryManager + public void setRoots(Map newRoots) { + + // Remove all items from current roots + for (IRepositoryRoot root : roots.values()) { + if (!newRoots.containsKey(root.getURL().toString())) { + removeItemsFromRoot(root); + } + } + + // Set the new roots + roots = newRoots; + + // Clear items to be removed + removedItems.clear(); + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/RepositoryManager.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/RepositoryManager.java new file mode 100644 index 0000000..a97ad9b --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/RepositoryManager.java @@ -0,0 +1,480 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.URLJarCollector; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.items.RobotItem; +import net.sf.robocode.repository.items.TeamItem; +import net.sf.robocode.repository.items.RepositoryItem; +import net.sf.robocode.repository.packager.JarCreator; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.repository.root.handlers.RootHandler; +import net.sf.robocode.security.HiddenAccess; +import net.sf.robocode.settings.ISettingsListener; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.IWindowManager; +import robocode.control.RobotSpecification; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + + +/** + * @author Pavel Savara (original) + */ +public class RepositoryManager implements IRepositoryManager { // NO_UCD (use default) + + private static final String DATABASE_FILENAME = "robot.database"; + + private final ISettingsManager properties; + private Repository repository; + + public RepositoryManager(ISettingsManager properties) { // NO_UCD (unused code) + this.properties = properties; + properties.addPropertyListener(new SettingsListener()); + } + + // ------------------------------------------ + // interfaces + // ------------------------------------------ + + @Override + public File getRobotsDirectory() { + return FileUtil.getRobotsDir(); + } + + @Override + public List getDevelDirectories() { + List develDirectories = new ArrayList(); + + for (String path : properties.getOptionsEnabledDevelopmentPaths()) { + try { + develDirectories.add(new File(path).getCanonicalFile()); + } catch (IOException e) { + Logger.logError(e); + } + } + return develDirectories; + } + + public void refresh(String friendlyUrl) { + if (!updateItemRoot(friendlyUrl, true)) { + refresh(true); + } + URLJarCollector.gc(); + } + + public boolean refresh() { + return refresh(false); + } + + public boolean refresh(boolean force) { + boolean refreshed = update(getRobotsDirectory(), getDevelDirectories(), force); + if (refreshed) { + setStatus("Saving robot database"); + save(); + } + + setStatus(""); + URLJarCollector.gc(); + + return refreshed; + } + + private boolean update(File robotsDir, Collection devDirs, boolean force) { + final int prev = repository.getItems().size(); + + RootHandler.openHandlers(); + try { + Map newRoots = new HashMap(); + + RootHandler.visitDirectories(robotsDir, false, newRoots, repository, force); + for (File dir : devDirs) { + RootHandler.visitDirectories(dir, true, newRoots, repository, force); + } + repository.setRoots(newRoots); + } finally { + RootHandler.closeHandlers(); + } + + return prev != repository.getItems().size(); + } + + private boolean updateItemRoot(String friendlyUrl, boolean force) { + IRepositoryItem repositoryItem = repository.getItems().get(friendlyUrl); + if (repositoryItem != null) { + repositoryItem.getRoot().updateItem(repositoryItem, force); + return true; + } + return false; + } + + private void save() { + FileOutputStream fos = null; + try { + fos = new FileOutputStream(new File(getRobotsDirectory(), DATABASE_FILENAME)); + repository.save(fos); + } catch (IOException e) { + Logger.logError("Can't save robot database", e); + } finally { + FileUtil.cleanupStream(fos); + } + } + + private Repository load() { + Repository repository = new Repository(); + + FileInputStream fis = null; + try { + File file = new File(getRobotsDirectory(), DATABASE_FILENAME); + if (file.exists()) { + fis = new FileInputStream(file); + repository.load(fis); + } + } catch (IOException e) { + Logger.logError("Can't load robot database", e); + repository = null; + } finally { + FileUtil.cleanupStream(fis); + } + return repository; + } + + public void reload(boolean rebuild) { + // Bug fix [2867326] - Lockup on start if too many bots in robots dir (cont'd). + URLJarCollector.enableGc(true); + URLJarCollector.gc(); + + if (rebuild) { + Logger.logMessage("Rebuilding robot database..."); + repository = new Repository(); + } else if (repository == null) { + setStatus("Reading robot database"); + repository = load(); + if (repository == null) { + setStatus("Building robot database"); + repository = new Repository(); + } + } + refresh(true); + setStatus(""); + } + + public RobotSpecification[] getSpecifications() { + checkDbExists(); + final Collection list = getAllValidItems(); + Collection res = new ArrayList(); + + for (IRobotSpecItem s : list) { + res.add(s.createRobotSpecification()); + } + return res.toArray(new RobotSpecification[res.size()]); + } + + /** + * Expand teams, validate robots + * @param selectedRobots, names of robots and teams, comma separated + * @return robots in teams + */ + public RobotSpecification[] loadSelectedRobots(RobotSpecification[] selectedRobots) { + checkDbExists(); + Collection battlingRobotsList = new ArrayList(); + int teamNum = 0; + + for (RobotSpecification spec: selectedRobots) { + IRobotSpecItem item = (IRobotSpecItem) HiddenAccess.getFileSpecification(spec); + + if (item == null) { + item = getRobot(spec.getNameAndVersion()); + } + loadItem(battlingRobotsList, spec, item, teamNum); + teamNum++; + } + return battlingRobotsList.toArray(new RobotSpecification[battlingRobotsList.size()]); + } + + /** + * Expand teams, validate robots + * @param selectedRobots, names of robots and teams, comma separated + * @return robots in teams + */ + public RobotSpecification[] loadSelectedRobots(String selectedRobots) { + checkDbExists(); + Collection battlingRobotsList = new ArrayList(); + final Collection list = getValidItems(selectedRobots); + int teamNum = 0; + + for (IRobotSpecItem item: list) { + loadItem(battlingRobotsList, null, item, teamNum); + teamNum++; + } + return battlingRobotsList.toArray(new RobotSpecification[battlingRobotsList.size()]); + } + + private boolean loadItem(Collection battlingRobotsList, RobotSpecification spec, IRobotSpecItem item, int teamNum) { + String teamId = String.format("%4d", teamNum); + + if (item != null) { + if (item.isTeam()) { + teamId = item.getFullClassNameWithVersion() + "[" + teamId + "]"; + final Collection members = getRobotItems((TeamItem) item); + + for (IRobotSpecItem member : members) { + final RobotItem robot = (RobotItem) member; + + boolean tested = false; + + for (RobotSpecification loaded : battlingRobotsList) { + if (HiddenAccess.getFileSpecification(loaded).equals(robot)) { + tested = true; + break; + } + } + + if (tested || robot.validate()) { + battlingRobotsList.add(robot.createRobotSpecification(null, teamId)); + } + } + } else { + final RobotItem robot = (RobotItem) item; + + if (robot.validate()) { + battlingRobotsList.add(robot.createRobotSpecification(spec, null)); + } else { + Logger.logError("Could not load robot: " + robot.getFullClassName()); + return false; + } + } + return true; + } + return false; + } + + public List getSelectedSpecifications(String selectedRobots) { + checkDbExists(); + return getValidItems(selectedRobots); + } + + private Collection getAllValidItems() { + final ArrayList res = new ArrayList(); + + for (IRepositoryItem repositoryItem : repository.getItems().values()) { + final IRobotSpecItem spec = (IRobotSpecItem) repositoryItem; + if (repositoryItem.isValid() && !res.contains(spec)) { + res.add(spec); + } + } + return res; + } + + private List getValidItems(String friendlyUrls) { + List result = new ArrayList(); + StringTokenizer tokenizer = new StringTokenizer(friendlyUrls, ","); + + while (tokenizer.hasMoreTokens()) { + String friendlyUrl = tokenizer.nextToken().trim(); + + IRepositoryItem repositoryItem = repository.getItem(friendlyUrl); + if (repositoryItem != null) { + if (repositoryItem.isValid()) { + result.add((IRobotSpecItem) repositoryItem); + } else { + Logger.logError("Can't load '" + friendlyUrl + "' because it is an invalid robot or team."); + } + } else { + Logger.logError("Can't find '" + friendlyUrl + '\''); + } + } + return result; + } + + public List getRepositoryItems(boolean onlyWithSource, boolean onlyWithPackage, boolean onlyRobots, boolean onlyDevelopment, boolean onlyNotDevelopment, boolean ignoreTeamRobots, boolean onlyInJar) { + checkDbExists(); + + final List res = new ArrayList(); + + for (IRepositoryItem repositoryItem : repository.getItems().values()) { + final IRobotSpecItem spec = (IRobotSpecItem) repositoryItem; + + if (!repositoryItem.isValid()) { + continue; + } + if (onlyWithSource && !spec.isSourceIncluded()) { + continue; + } + if (onlyWithPackage && spec.getFullPackage() == null) { + continue; + } + if (onlyInJar && !spec.isInJAR()) { + continue; + } + if (onlyRobots && !(repositoryItem instanceof RobotItem)) { + continue; + } + if (onlyDevelopment && !spec.isDevelopmentVersion()) { + continue; + } + if (onlyNotDevelopment && spec.isDevelopmentVersion()) { + continue; + } + if (res.contains(spec)) { + continue; + } + res.add(spec); + } + Collections.sort(res); + return res; + } + + public boolean verifyRobotName(String robotName, String shortClassName) { + return RobotItem.verifyRobotName(robotName, shortClassName, true); + } + + public int extractJar(IRobotSpecItem item) { + if (!item.isInJAR()) { + return -2; + } + ((RepositoryItem) item).getRoot().extractJAR(); + return 0; + } + + public void createTeam(File target, TeamProperties teamProps) throws IOException { + checkDbExists(); + + TeamItem.createOrUpdateTeam(target, teamProps); + refresh(target.toURI().toString()); + } + + public String createPackage(File jarFile, List selectedRobots, RobotProperties robotProps) { + checkDbExists(); + List robotItems = getAllRobotItems(selectedRobots); + TeamItem teamItem = getTeamItem(selectedRobots); + + String res = JarCreator.createPackage(jarFile, robotItems, teamItem, robotProps); + refresh(jarFile.toURI().toString()); + + return res; + } + + private Collection getRobotItems(TeamItem team) { + Collection result = new ArrayList(); + StringTokenizer teamTokenizer = new StringTokenizer(team.getMembers(), ","); + + while (teamTokenizer.hasMoreTokens()) { + String botNameAndVersion = teamTokenizer.nextToken(); + int versionIndex = botNameAndVersion.indexOf(' '); + String botPath = versionIndex < 0 ? botNameAndVersion : botNameAndVersion.substring(0, versionIndex); + + botPath = botPath.replace('.', '/').replaceAll("\\*", ""); + + // first load from same classPath + String teamBot = team.getRoot().getURL() + botPath; + IRepositoryItem res = repository.getItem(teamBot); + + if (res != null && res instanceof RobotItem) { + result.add((RobotItem) res); + continue; + } + + // try general search + res = repository.getItem(botNameAndVersion); + if (res != null && res instanceof RobotItem) { + result.add((RobotItem) res); + continue; + } + + // not found + Logger.logError("Can't find robot: " + botNameAndVersion); + } + return result; + } + + private List getAllRobotItems(Collection items) { + List result = new ArrayList(); + + for (IRobotSpecItem item : items) { + if (item.isTeam()) { + result.addAll(getRobotItems((TeamItem) item)); + } else { + result.add((RobotItem) item); + } + } + return result; + } + + private static TeamItem getTeamItem(Collection items) { + for (IRobotSpecItem item : items) { + if (item.isTeam()) { + return (TeamItem) item; + } + } + return null; + } + + private IRobotSpecItem getRobot(String fullClassNameWithVersion) { + final IRepositoryItem repositoryItem = repository.getItem(fullClassNameWithVersion); + + if (repositoryItem == null || !repositoryItem.isValid()) { + return null; + } + return (IRobotSpecItem) repositoryItem; + } + + private void setStatus(String message) { + IWindowManager windowManager = Container.getComponent(IWindowManager.class); + + if (windowManager != null) { + windowManager.setStatus(message); + } + if (message.length() > 0) { + Logger.logMessage(message); + } + } + + private void checkDbExists() { + if (repository == null) { + reload(false); + } + } + + // ------------------------------------------ + // settings listener + // ------------------------------------------ + + private class SettingsListener implements ISettingsListener { + + private Collection lastEnabledDevelPaths; + + public void settingChanged(String property) { + if (property.equals(ISettingsManager.OPTIONS_DEVELOPMENT_PATH) + || property.equals(ISettingsManager.OPTIONS_DEVELOPMENT_PATH_EXCLUDED)) { + + Collection enabledDevelPaths = properties.getOptionsEnabledDevelopmentPaths(); + + if (lastEnabledDevelPaths == null || !enabledDevelPaths.equals(lastEnabledDevelPaths)) { + lastEnabledDevelPaths = enabledDevelPaths; + reload(true); + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/IRepositoryItem.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/IRepositoryItem.java new file mode 100644 index 0000000..c83e9d1 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/IRepositoryItem.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items; + + +import net.sf.robocode.repository.root.IRepositoryRoot; + +import java.net.URL; +import java.util.Set; + + +/** + * @author Pavel Savara (original) + */ +public interface IRepositoryItem extends Comparable { + URL getItemURL(); + IRepositoryRoot getRoot(); + Set getFriendlyURLs(); + + /** + * Updates the repository item if specified 'last modified' date is newer than the one recorded on this item, + * or if it is a forced update. + * + * @param lastModified is a 'last modified' date (millis since 1970). If this parameter is newer than the one + * previously set on this item, then this item will be updated. + * @param force is a flag specifying if this item is forced to be updated. + * If this parameter is true, then this item will be updated. + */ + void update(long lastModified, boolean force); + + long getLastModified(); + boolean isValid(); +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RepositoryItem.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RepositoryItem.java new file mode 100644 index 0000000..d8e9592 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RepositoryItem.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items; + + +import net.sf.robocode.repository.root.IRepositoryRoot; + +import java.io.Serializable; +import java.net.URL; + + +/** + * @author Pavel Savara (original) + */ +public abstract class RepositoryItem implements IRepositoryItem, Serializable { + private static final long serialVersionUID = 1L; + + protected URL itemUrl; + protected IRepositoryRoot root; + protected long lastModified; + protected boolean isValid; + + RepositoryItem(URL itemURL, IRepositoryRoot root) { + this.itemUrl = itemURL; + this.root = root; + this.lastModified = 0; + } + + public URL getItemURL() { + return itemUrl; + } + + public IRepositoryRoot getRoot() { + return root; + } + + public boolean isInJAR() { + return root.isJAR(); + } + + public long getLastModified() { + return lastModified; + } + + public boolean isValid() { + return isValid; + } + + public void setValid(boolean valid) { + isValid = valid; + } + + @Override + public int hashCode() { + return 31 + ((itemUrl == null) ? 0 : itemUrl.hashCode()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || !(obj instanceof RepositoryItem)) { + return false; + } + RepositoryItem other = (RepositoryItem) obj; + if (itemUrl == null && other.itemUrl != null) { + return false; + } + return itemUrl.equals(other.itemUrl); + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RobotItem.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RobotItem.java new file mode 100644 index 0000000..d9b00a6 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RobotItem.java @@ -0,0 +1,608 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import net.sf.robocode.io.URLJarCollector; +import static net.sf.robocode.io.Logger.logError; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.repository.RobotProperties; +import net.sf.robocode.repository.RobotType; +import net.sf.robocode.repository.root.ClasspathRoot; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.security.HiddenAccess; +import net.sf.robocode.core.Container; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.version.IVersionManager; +import robocode.control.RobotSpecification; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashSet; +import java.util.Set; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobotItem extends RobotSpecItem implements IRobotItem { + private static final long serialVersionUID = 1L; + + // Allowed maximum length for a robot's full package name + private static final int MAX_FULL_PACKAGE_NAME_LENGTH = 32; + // Allowed maximum length for a robot's short class name + private static final int MAX_SHORT_CLASS_NAME_LENGTH = 32; + + protected static final String ROBOT_PLATFORM = "robot.platform"; + private static final String ROBOT_CLASSNAME = "robot.classname"; + private static final String ROBOT_VERSION = "robot.version"; + private static final String ROBOT_DESCRIPTION = "robot.description"; + private static final String ROBOT_AUTHOR_NAME = "robot.author.name"; + private static final String ROBOT_WEBPAGE = "robot.webpage"; + private static final String ROBOCODE_VERSION = "robocode.version"; + private static final String ROBOT_INCLUDE_SOURCE = "robot.include.source"; + private static final String ROBOT_INCLUDE_DATA = "robot.include.data"; + private static final String ROBOT_CODESIZE = "robot.codesize"; + + // File extensions + private static final String CLASS_EXTENSION = ".class"; + private static final String PROPERTIES_EXTENSION = ".properties"; + private static final String HTML_EXTENSION = ".html"; + + private static final boolean ALWAYS_USE_CACHE_FOR_DATA = System.getProperty("ALWAYSUSECACHEFORDATA", "false").equals( + "true"); + + private RobotType robotType; + + private URL classPathURL; + private Set sourcePathURLs; // This is a Set in order to avoid duplicates + + private URL classURL; + private URL propertiesURL; + + private String className; + protected boolean isPropertiesLoaded; + + public RobotItem(URL itemURL, IRepositoryRoot root) { + super(itemURL, root); + + isValid = true; + + classPathURL = root.getURL(); + sourcePathURLs = new HashSet(); + } + + private void populate() { + populatePropertiesURLFromClassURL(); + populateClassURLFromPropertiesURL(); + loadProperties(); + } + + public void setClassURL(URL classUrl) { + this.classURL = classUrl; + populate(); + } + + public void setPropertiesURL(URL propertiesUrl) { + this.propertiesURL = propertiesUrl; + populate(); + } + + public void setClassPathURL(URL classPathUrl) { + this.classPathURL = classPathUrl; + } + + public void addSourcePathURL(URL sourcePathUrl) { + sourcePathURLs.add(sourcePathUrl); + } + + // ------------------------------------- + // URL initialization + // ------------------------------------- + + private void populatePropertiesURLFromClassURL() { + if (propertiesURL == null && classURL != null) { + final String path = classURL.toString().replaceFirst("\\" + CLASS_EXTENSION, PROPERTIES_EXTENSION); + + try { + propertiesURL = new URL(path); + } catch (MalformedURLException e) { + Logger.logError(e); + } + if (isInvalidURL(propertiesURL)) { + propertiesURL = null; + } + } + } + + private void populateClassURLFromPropertiesURL() { + if (classURL == null && propertiesURL != null) { + final String path = propertiesURL.toString().replaceAll("\\" + PROPERTIES_EXTENSION, CLASS_EXTENSION); + + try { + classURL = new URL(path); + } catch (MalformedURLException e) { + Logger.logError(e); + } + if (isInvalidURL(classURL)) { + classURL = null; + } + } + } + + private void populateClassNameFromClassURL() { + populate(); + + if (className == null && classURL != null) { + final String path = classURL.toString(); + + // .dll file? + int index = (path.toLowerCase().indexOf(".dll!/")); + + if (index > 0) { + className = path.substring(index + 6); + return; + } + + // Class within .jar or regular file path? + + index = path.lastIndexOf('!'); + + if (index > 0) { + // .jar file + className = path.substring(index + 2); + } else { + // file path + className = path.substring(root.getURL().toString().length()); + } + + // Remove the file extension from the class name + index = className.lastIndexOf('.'); + + if (index > 0) { + className = className.substring(0, index); + } + + // Replace all file separators with dots (from file path the package/namespace) + className = className.replaceAll("[\\\\\\/]", "."); + } + } + + private void populateHtmlURL() { + populate(); + + if (htmlURL == null && classURL != null) { + try { + htmlURL = new URL(classURL.toString().replaceFirst(CLASS_EXTENSION, HTML_EXTENSION)); + } catch (MalformedURLException ignore) {} + } + if (htmlURL == null && propertiesURL != null) { + try { + htmlURL = new URL(propertiesURL.toString().replaceFirst(PROPERTIES_EXTENSION, HTML_EXTENSION)); + } catch (MalformedURLException ignore) {} + } + if (isInvalidURL(htmlURL)) { + htmlURL = null; + } + } + + private boolean isInvalidURL(URL url) { + if (url != null) { + InputStream is = null; + try { + URLConnection conn = URLJarCollector.openConnection(url); + is = conn.getInputStream(); + return false; + } catch (IOException e) { + return true; + } finally { + FileUtil.cleanupStream(is); + } + } + return true; + } + + // / ------------------------------------- + // / public + // / ------------------------------------- + + public boolean isTeam() { + return false; + } + + public URL getHtmlURL() { + // Lazy + if (htmlURL == null) { + populateHtmlURL(); + } + return htmlURL; + } + + public URL getPropertiesURL() { + if (propertiesURL == null) { + populatePropertiesURLFromClassURL(); + } + return propertiesURL; + } + + public Set getFriendlyURLs() { + populate(); + + Set urls = new HashSet(); + + URL url = null; + if (classURL != null) { + url = classURL; + } else if (propertiesURL != null) { + url = propertiesURL; + } + if (url != null) { + String sUrl = url.toString(); + String urlNoType = sUrl.substring(0, sUrl.lastIndexOf('.')); + + String path = url.getPath(); + String pathNoType = path.substring(0, path.lastIndexOf('.')); + + urls.add(urlNoType); + urls.add(pathNoType); + } + if (getFullClassName() != null) { + if (RobocodeProperties.isTestingOn()) { + urls.add(getFullClassName()); + } else { + urls.add(getUniqueFullClassName()); + } + urls.add(getUniqueFullClassNameWithVersion()); + } + if (root.isJAR()) { + urls.add(root.getURL().toString()); + } + if (root instanceof ClasspathRoot) { + String friendly = ((ClasspathRoot) root).getFriendlyProjectURL(itemUrl); + + if (friendly != null) { + urls.add(friendly); + } + } + return urls; + } + + /** + * {@inheritDoc} + */ + public void update(long lastModified, boolean force) { + if (lastModified > this.lastModified || force) { + if (force) { + isValid = true; + } + + // trying to guess all correct file locations + populate(); + + this.lastModified = lastModified; + if (classURL == null) { + isValid = false; + } + loadProperties(); + if (root.isJAR() && !isPropertiesLoaded) { + isValid = false; + } + if (isValid) { + validateType(false); + } + if (isValid) { + verifyName(); + } + } + } + + protected void validateType(boolean resolve) { + populate(); + + final IHostManager hostManager = Container.getComponent(IHostManager.class); + + robotType = hostManager.getRobotType(this, resolve, classURL != null); + if (!robotType.isValid()) { + isValid = false; + } + } + + // Stronger than update + public boolean validate() { + validateType(true); + return isValid; + } + + // Note that ROBOCODE_CLASSNAME can be invalid, an hence can't be trusted when loaded! + // Hence, we read the fullClassName field instead and NOT the ROBOCODE_CLASSNAME property. + private boolean loadProperties() { + if (!isPropertiesLoaded && propertiesURL != null) { + InputStream ios = null; + try { + URLConnection con = URLJarCollector.openConnection(propertiesURL); + + ios = con.getInputStream(); + properties.load(ios); + isPropertiesLoaded = true; + return true; + } catch (IOException e) { + return false; + } finally { + FileUtil.cleanupStream(ios); + } + } + return false; + } + + private boolean verifyName() { + String robotName = getFullClassName(); + String shortClassName = getShortClassName(); + + final boolean valid = verifyRobotName(robotName, shortClassName, false); + + if (!valid) { + isValid = false; + } + return valid; + } + + public static boolean verifyRobotName(String fullClassName, String shortClassName, boolean silent) { + if (fullClassName == null || fullClassName.length() == 0 || fullClassName.contains("$")) { + return false; + } + + int lIndex = fullClassName.indexOf("."); + if (lIndex > 0) { + String rootPackage = fullClassName.substring(0, lIndex); + + if (rootPackage.equalsIgnoreCase("robocode")) { + if (!silent) { + logError("Robot " + fullClassName + " ignored. You cannot use package " + rootPackage); + } + return false; + } + if (rootPackage.length() > MAX_FULL_PACKAGE_NAME_LENGTH) { + if (!silent) { + logError( + "Robot " + fullClassName + " has package name too long. " + MAX_FULL_PACKAGE_NAME_LENGTH + + " characters maximum please."); + } + return false; + } + } + if (shortClassName != null && shortClassName.length() > MAX_SHORT_CLASS_NAME_LENGTH) { + if (!silent) { + logError( + "Robot " + fullClassName + " has classname too long. " + MAX_SHORT_CLASS_NAME_LENGTH + + " characters maximum please."); + } + return false; + } + return true; + } + + public void storeProperties(OutputStream os, RobotProperties robotProps) throws IOException { + if (className != null) { + properties.setProperty(ROBOT_CLASSNAME, className); + } + if (robotProps.getVersion() != null) { + properties.setProperty(ROBOT_VERSION, robotProps.getVersion()); + } + if (robotProps.getDescription() != null) { + properties.setProperty(ROBOT_DESCRIPTION, robotProps.getDescription()); + } + if (robotProps.getAuthor() != null) { + properties.setProperty(ROBOT_AUTHOR_NAME, robotProps.getAuthor()); + } + if (robotProps.getWebPage() != null) { + properties.setProperty(ROBOT_WEBPAGE, robotProps.getWebPage().toExternalForm()); + } + if (robotProps.getCodeSize() != null) { + properties.setProperty(ROBOT_CODESIZE, "" + robotProps.getCodeSize()); + } + properties.setProperty(ROBOT_INCLUDE_SOURCE, "" + robotProps.isIncludeSource()); + + String version = Container.getComponent(IVersionManager.class).getVersion(); + properties.setProperty(ROBOCODE_VERSION, version); + + saveProperties(os); + + saveProperties(); + } + + private void saveProperties(OutputStream os) throws IOException { + properties.store(os, "Robocode Robot"); + } + + private void saveProperties() { + File file = new File(root.getPath(), className.replaceAll("\\.", "/") + PROPERTIES_EXTENSION); + FileOutputStream fos = null; + + try { + fos = new FileOutputStream(file); + saveProperties(fos); + } catch (IOException e) { + e.printStackTrace(); + } finally { + FileUtil.cleanupStream(fos); + } + populatePropertiesURLFromClassURL(); + } + + public boolean isJuniorRobot() { + return robotType.isJuniorRobot(); + } + + public boolean isStandardRobot() { + return robotType.isStandardRobot(); + } + + public boolean isAdvancedRobot() { + return robotType.isAdvancedRobot(); + } + + public boolean isTeamRobot() { + return robotType.isTeamRobot(); + } + + public boolean isDroid() { + return robotType.isDroid(); + } + + public boolean isSentryRobot() { + return robotType.isSentryRobot(); + } + + public boolean isInteractiveRobot() { + return robotType.isInteractiveRobot(); + } + + public boolean isPaintRobot() { + return robotType.isPaintRobot(); + } + + public URL getClassPathURL() { + return classPathURL; + } + + public URL[] getSourcePathURLs() { + // If no source path URL exists, we must use the class path URL + if (sourcePathURLs.size() == 0) { + return new URL[] { classPathURL }; + } + return sourcePathURLs.toArray(new URL[] {}); + } + + public String getFullClassName() { + // Lazy + if (className == null) { + populateClassNameFromClassURL(); + } + return className; + } + + public String getVersion() { + return properties.getProperty(ROBOT_VERSION, null); + } + + public String getDescription() { + return properties.getProperty(ROBOT_DESCRIPTION, null); + } + + public String getAuthorName() { + return properties.getProperty(ROBOT_AUTHOR_NAME, null); + } + + public String getPlatform() { + return properties.getProperty(ROBOT_PLATFORM, "Java"); + } + + public URL getWebpage() { + try { + String webPage = properties.getProperty(ROBOT_WEBPAGE, null); + if (webPage == null || webPage.trim().isEmpty()) { + return null; + } + return new URL(webPage); + } catch (MalformedURLException e) { + return null; + } + } + + public Integer getCodeSize() { + String value = properties.getProperty(ROBOT_CODESIZE); + if (value == null) { + return null; + } + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + return null; + } + } + + public boolean getIncludeSource() { + return properties.getProperty(ROBOT_INCLUDE_SOURCE, "true").equalsIgnoreCase("true"); + } + + public boolean getIncludeData() { + return properties.getProperty(ROBOT_INCLUDE_DATA, "true").equalsIgnoreCase("true"); + } + + public boolean isSourceIncluded() { + return sourcePathURLs.size() > 0; + } + + public String getRobocodeVersion() { + return properties.getProperty(ROBOCODE_VERSION, null); + } + + public String getReadableDirectory() { + String path; + if (root.isJAR()) { + String jarFile = getClassPathURL().getFile(); + jarFile = jarFile.substring(jarFile.lastIndexOf('/') + 1, jarFile.length()); + path = FileUtil.getRobotsDataDir().getPath(); + if (jarFile.length() > 0) { + path += File.separator + jarFile + '_'; + } + } else { + path = getClassPathURL().getFile(); + } + if (getFullPackage() != null) { + path += File.separator + getFullPackage().replace('.', File.separatorChar); + } + return path; + } + + public String getWritableDirectory() { + String path; + if (root.isJAR()) { + String jarFile = getClassPathURL().getFile(); + jarFile = jarFile.substring(jarFile.lastIndexOf('/') + 1, jarFile.length()); + path = FileUtil.getRobotsDataDir().getPath(); + if (jarFile.length() > 0) { + path += File.separator + jarFile + '_'; + } + } else { + path = ALWAYS_USE_CACHE_FOR_DATA ? FileUtil.getRobotsDataDir().getPath() : getClassPathURL().getFile(); + } + if (getFullPackage() != null) { + path += File.separator + getFullPackage().replace('.', File.separatorChar); + } + return path; + } + + public RobotSpecification createRobotSpecification(RobotSpecification battleRobotSpec, String teamId) { + RobotSpecification specification; + + if (battleRobotSpec != null) { + specification = battleRobotSpec; + } else { + specification = createRobotSpecification(); + } + if (teamId != null) { + HiddenAccess.setTeamId(specification, teamId); + } + return specification; + } + + public String toString() { + return itemUrl.toString(); + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RobotSpecItem.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RobotSpecItem.java new file mode 100644 index 0000000..953d63d --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/RobotSpecItem.java @@ -0,0 +1,259 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items; + + +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.security.HiddenAccess; +import net.sf.robocode.util.AlphanumericComparator; +import robocode.control.RobotSpecification; + +import java.net.URL; +import java.util.Properties; +import java.util.StringTokenizer; + + +/** + * @author Pavel Savara (original) + */ +public abstract class RobotSpecItem extends RepositoryItem implements IRobotSpecItem { + private static final long serialVersionUID = 1L; + + protected Properties properties = new Properties(); + protected URL htmlURL; + + RobotSpecItem(URL itemURL, IRepositoryRoot root) { + super(itemURL, root); + } + + public abstract URL getPropertiesURL(); + + public abstract String getFullClassName(); + + public abstract String getVersion(); + + public abstract URL getWebpage(); + + public abstract String getAuthorName(); + + public abstract String getRobocodeVersion(); + + public abstract String getDescription(); + + public abstract URL getHtmlURL(); + + public boolean isDevelopmentVersion() { + return root.isDevelopmentRoot() + && !(getFullClassName().startsWith("sample") || getFullClassName().startsWith("tested.")); + } + + public String getRootPath() { + return root.getURL().toString(); + } + + public String getRootPackage() { + int lIndex = getFullClassName().indexOf("."); + String rootPackage = null; + + if (lIndex > 0) { + rootPackage = getFullClassName().substring(0, lIndex); + } + return rootPackage; + } + + public String getFullPackage() { + if (getFullClassName() == null) { + return null; + } + final int index = getFullClassName().lastIndexOf('.'); + + return (index >= 0) ? getFullClassName().substring(0, index) : null; + } + + // same as package but with slash + public String getRelativePath() { + final int index = getFullClassName().lastIndexOf('.'); + + return (index < 0) ? "" : getFullClassName().substring(0, index).replaceAll("\\.", "/"); + } + + public String getShortClassName() { + if (getFullClassName() == null) { + return null; + } + final int index = getFullClassName().lastIndexOf('.'); + + if (index == -1) { + return getFullClassName(); + } + return getFullClassName().substring(index + 1); + } + + public String getFullClassNameWithVersion() { + String fullClassName = getFullClassName(); + + if (getVersion() != null) { + fullClassName += " " + getVersion(); + } + return fullClassName; + } + + public String getUniqueFullClassName() { + String uniqueFullClassName = getFullClassName(); + + if (isDevelopmentVersion()) { + uniqueFullClassName += '*'; + } + return uniqueFullClassName; + } + + public String getUniqueFullClassNameWithVersion() { + String uniqueFullClassName = (getVersion() == null) ? getFullClassName() : getFullClassNameWithVersion(); + + if (isDevelopmentVersion()) { + uniqueFullClassName += '*'; + } + return uniqueFullClassName; + } + + public String getUniqueShortClassNameWithVersion() { + String uniqueShortClassName = (getVersion() == null) ? getShortClassName() : getShortClassNameWithVersion(); + + if (isDevelopmentVersion()) { + uniqueShortClassName += '*'; + } + return uniqueShortClassName; + } + + public String getUniqueVeryShortClassNameWithVersion() { + String veryShortClassName = (getVersion() == null) + ? getVeryShortClassName() + : getVeryShortClassNameWithVersion(); + + if (isDevelopmentVersion()) { + veryShortClassName += '*'; + } + return veryShortClassName; + } + + public String getShortClassNameWithVersion() { + String shortClassName = getShortClassName(); + + if (getVersion() != null) { + shortClassName += " " + getVersion(); + } + return shortClassName; + } + + public String getVeryShortClassNameWithVersion() { + String veryShortClassName = getVeryShortClassName(); + + if (getVersion() != null) { + veryShortClassName += " " + getVersion(); + } + return veryShortClassName; + } + + public String getVeryShortClassName() { + String veryShortClassName = getShortClassName(); + + if (veryShortClassName.length() > 12) { + veryShortClassName = veryShortClassName.substring(0, 12) + "..."; + } + return veryShortClassName; + } + + public RobotSpecification createRobotSpecification() { + return HiddenAccess.createSpecification(this, getUniqueFullClassName(), getAuthorName(), + (getWebpage() != null) ? getWebpage().toString() : null, getVersion(), getRobocodeVersion(), + root.getURL().toString(), getFullClassName(), getDescription()); + } + + public int compareTo(Object other) { + if (other == this) { + return 0; + } + if (other instanceof IRobotSpecItem) { + IRobotSpecItem otherRI = (IRobotSpecItem) other; + + return compare(getFullPackage(), getFullClassName(), getVersion(), otherRI.getFullPackage(), + otherRI.getFullClassName(), otherRI.getVersion()); + } + + // for IgnoredItem + return 0; + } + + private static int compare(String p1, String c1, String v1, String p2, String c2, String v2) { + AlphanumericComparator alphaNumComparator = new AlphanumericComparator(); + + // Compare packages + int result = alphaNumComparator.compare(p1, p2); + + if (result != 0) { + return result; + } + + // Same package, so compare classes + result = alphaNumComparator.compare(c1, c2); + if (result != 0) { + return result; + } + + // Same robot, so compare versions + if (v1 == null && v2 == null) { + return 0; + } + if (v1 == null) { + return 1; + } + if (v2 == null) { + return -1; + } + + if (v1.equals(v2)) { + return 0; + } + + if (v1.indexOf(".") < 0 || v2.indexOf(".") < 0) { + return alphaNumComparator.compare(v1, v2); + } + + // Dot separated versions. + StringTokenizer s1 = new StringTokenizer(v1, "."); + StringTokenizer s2 = new StringTokenizer(v2, "."); + + while (s1.hasMoreTokens() && s2.hasMoreTokens()) { + String tok1 = s1.nextToken(); + String tok2 = s2.nextToken(); + + try { + int i1 = Integer.parseInt(tok1); + int i2 = Integer.parseInt(tok2); + + if (i1 != i2) { + return i1 - i2; + } + } catch (NumberFormatException e) { + int tc = alphaNumComparator.compare(tok1, tok2); + + if (tc != 0) { + return tc; + } + } + } + if (s1.hasMoreTokens()) { + return 1; + } + if (s2.hasMoreTokens()) { + return -1; + } + return 0; + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/TeamItem.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/TeamItem.java new file mode 100644 index 0000000..1f5b8fc --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/TeamItem.java @@ -0,0 +1,258 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.RobocodeProperties; +import net.sf.robocode.io.URLJarCollector; +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.repository.RobotProperties; +import net.sf.robocode.repository.TeamProperties; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.core.Container; +import net.sf.robocode.version.IVersionManager; + +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + + +/** + * @author Pavel Savara (original) + */ +public class TeamItem extends RobotSpecItem implements IRobotSpecItem { + private static final long serialVersionUID = 1L; + + private static final String TEAM_DESCRIPTION = "team.description"; + private static final String TEAM_AUTHOR_NAME = "team.author.name"; + private static final String TEAM_VERSION = "team.version"; + private static final String TEAM_WEBPAGE = "team.webpage"; + private static final String TEAM_MEMBERS = "team.members"; + private static final String ROBOCODE_VERSION = "robocode.version"; + + private final String fullTeamName; + + public TeamItem(URL itemURL, IRepositoryRoot root) { + super(itemURL, root); + String tUrl = itemURL.toString(); + + tUrl = tUrl.substring(0, tUrl.lastIndexOf(".team")); + final int versionSeparator = tUrl.lastIndexOf(" "); + final int rootLen = root.getURL().toString().length(); + + if (versionSeparator != -1) { + fullTeamName = tUrl.substring(rootLen, versionSeparator).replace('/', '.').replace('\\', '.'); + } else { + fullTeamName = tUrl.substring(rootLen).replace('/', '.').replace('\\', '.'); + } + if (loadProperties()) { + isValid = true; + } + } + + private void htmlURLFromPropertiesURL() { + try { + htmlURL = new URL(itemUrl.toString().replaceAll("\\.team", ".html")); + + // test that html file exists + final URLConnection conn = URLJarCollector.openConnection(htmlURL); + + conn.getInputStream().close(); + } catch (IOException ignored) { + // doesn't exist + htmlURL = null; + } + } + + public Set getFriendlyURLs() { + Set urls = new HashSet(); + + if (itemUrl != null) { + String url = itemUrl.toString(); + String urlNoType = url.substring(0, url.lastIndexOf('.')); + + String path = itemUrl.getPath(); + String pathNoType = path.substring(0, path.lastIndexOf('.')); + + urls.add(urlNoType); + urls.add(pathNoType); + } + if (RobocodeProperties.isTestingOn()) { + urls.add(getFullClassName()); + } else { + urls.add(getUniqueFullClassName()); + } + urls.add(getUniqueFullClassNameWithVersion()); + + return urls; + } + + /** + * {@inheritDoc} + */ + public void update(long lastModified, boolean force) { + if (lastModified > this.lastModified || force) { + this.lastModified = lastModified; + loadProperties(); + } + } + + private boolean loadProperties() { + if (itemUrl != null) { + InputStream ios = null; + + try { + final URLConnection connection = URLJarCollector.openConnection(itemUrl); + + ios = connection.getInputStream(); + + properties.load(ios); + return true; + } catch (IOException e) { + Logger.logError(e); + } finally { + FileUtil.cleanupStream(ios); + } + } + return false; + } + + public URL getHtmlURL() { + // lazy + if (htmlURL == null) { + htmlURLFromPropertiesURL(); + } + return htmlURL; + } + + public URL getPropertiesURL() { + return itemUrl; + } + + public boolean isTeam() { + return true; + } + + public String getFullClassName() { + return fullTeamName; + } + + public String getMembers() { + return properties.getProperty(TEAM_MEMBERS, null); + } + + public String getVersion() { + return properties.getProperty(TEAM_VERSION, null); + } + + public String getDescription() { + return properties.getProperty(TEAM_DESCRIPTION, null); + } + + public String getAuthorName() { + return properties.getProperty(TEAM_AUTHOR_NAME, null); + } + + public URL getWebpage() { + try { + return new URL(properties.getProperty(TEAM_WEBPAGE, null)); + } catch (MalformedURLException e) { + return null; + } + } + + public boolean getIncludeSource() { + return false; + } + + public boolean getIncludeData() { + return false; + } + + public boolean isSourceIncluded() { + return false; + } + + public String getRobocodeVersion() { + return properties.getProperty(ROBOCODE_VERSION, null); + } + + public String toString() { + return itemUrl.toString(); + } + + public void storeProperties(OutputStream os, RobotProperties props) throws IOException { + if (props.getVersion() != null) { + properties.setProperty(TEAM_VERSION, props.getVersion()); + } + if (props.getDescription() != null) { + properties.setProperty(TEAM_DESCRIPTION, props.getDescription()); + } + if (props.getAuthor() != null) { + properties.setProperty(TEAM_AUTHOR_NAME, props.getAuthor()); + } + if (props.getWebPage() != null) { + properties.setProperty(TEAM_WEBPAGE, props.getWebPage().toExternalForm()); + } + properties.setProperty(ROBOCODE_VERSION, Container.getComponent(IVersionManager.class).getVersion()); + + properties.store(os, "Robocode Robot Team"); + } + + public static void createOrUpdateTeam(File target, TeamProperties props) throws IOException { + FileOutputStream os = null; + + try { + Properties team = loadTeamProperties(target); + + if (props.getMembers() != null) { + team.setProperty(TEAM_MEMBERS, props.getMembers()); + } + if (props.getAuthor() != null) { + team.setProperty(TEAM_AUTHOR_NAME, props.getAuthor()); + } + if (props.getDescription() != null) { + team.setProperty(TEAM_DESCRIPTION, props.getDescription()); + } + if (props.getWebPage() != null) { + team.setProperty(TEAM_WEBPAGE, props.getWebPage().toExternalForm()); + } + String version = Container.getComponent(IVersionManager.class).getVersion(); + team.setProperty(ROBOCODE_VERSION, version); + + os = new FileOutputStream(target); + team.store(os, "Robocode robot team"); + } finally { + FileUtil.cleanupStream(os); + } + } + + private static Properties loadTeamProperties(File target) { + Properties team = new Properties(); + + if (target.exists()) { + FileInputStream fis = null; + + try { + fis = new FileInputStream(target); + team.load(fis); + } catch (Exception e) { + Logger.logError(e); + } finally { + FileUtil.cleanupStream(fis); + } + } + return team; + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/ClassHandler.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/ClassHandler.java new file mode 100644 index 0000000..d1389a0 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/ClassHandler.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items.handlers; + + +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.items.RobotItem; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.util.UrlUtil; + +import java.net.URL; + + +/** + * Item handler for accepting and registering Java class files. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class ClassHandler extends ItemHandler { + + /** + * {@inheritDoc} + */ + @Override + protected IRepositoryItem acceptItem(URL itemURL, IRepositoryRoot root, IRepository repository) { + // Accept and register the item if it is a Java class file, but not an inner class file + String name = itemURL.toString().toLowerCase(); + if (name.endsWith(".class") && !name.contains("$")) { + return register(itemURL, root, repository); + } + return null; + } + + /** + * Registers the class file with the specified URL as a RobotItem. + * + * @param classFileUrl is the URL of the class file to register. + * @param root is the repository root containing the class file to register. + * @param repository is the repository, where the class file is automatically added or updated, + * when the class file is registered. + * @return a RobotItem that has been created or updated in the repository. + */ + private RobotItem register(URL classFileUrl, IRepositoryRoot root, IRepository repository) { + RobotItem item = null; + + // Check if the class file is already registered in the repository + String friendlyUrl = UrlUtil.removeFileExtension(classFileUrl.toString()); + + IRepositoryItem repositoryItem = repository.getItem(friendlyUrl); + if (repositoryItem instanceof RobotItem) { + item = (RobotItem) repositoryItem; + } + + // If the class file has not been registered then create a new RobotItem based on the class file URL + if (item == null) { + item = new RobotItem(classFileUrl, root); + } + + // Set the class path URL and class URL on the RobotItem + item.setClassPathURL(root.getURL()); + item.setClassURL(classFileUrl); + + // Add or update the item in the repository and return it + repository.addOrUpdateItem(item); + return item; + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/ItemHandler.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/ItemHandler.java new file mode 100644 index 0000000..8567bff --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/ItemHandler.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items.handlers; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.root.IRepositoryRoot; + +import java.net.URL; +import java.util.List; + + +/** + * Abstract item handler used for accepting and registering specific item types. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public abstract class ItemHandler { + + /** + * Tests whether or not the item with at the specified item URL is accepted and can be handled by this item handler. + * + * @param itemUrl is the URL of the item to test. + * @param root is the repository root containing the item to test. + * @param repository is the repository, where the item is automatically added or updated, if the item is accepted. + * @return a repository item that has been created or updated in the repository or null if the item was not + * accepted by this item handler. + */ + protected abstract IRepositoryItem acceptItem(URL itemUrl, IRepositoryRoot root, IRepository repository); + + /** + * Tests whether or not the item with at the specified item URL is accepted and can be handled by any + * available item handler. + * + * @param itemUrl is the URL of the item to test. + * @param root is the repository root containing the item to test. + * @param repository is the repository, where the item is automatically added or updated, if the item is accepted. + * @return a repository item that has been created or updated in the repository or null if the item was not + * accepted by an item handler. + */ + public final static IRepositoryItem registerItem(URL itemUrl, IRepositoryRoot root, IRepository repository) { + // Test if any available item handler will accept and register the item + List itemHandlers = Container.getComponents(ItemHandler.class); + for (ItemHandler handler : itemHandlers) { + IRepositoryItem repositoryItem = handler.acceptItem(itemUrl, root, repository); + if (repositoryItem != null) { + return repositoryItem; + } + } + return null; + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/PropertiesHandler.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/PropertiesHandler.java new file mode 100644 index 0000000..f7d168b --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/PropertiesHandler.java @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items.handlers; + + +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.items.RobotItem; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.util.UrlUtil; +import net.sf.robocode.core.Container; + +import java.net.URL; + + +/** + * Handler for accepting and registering Java properties files. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class PropertiesHandler extends ItemHandler { + + /** + * {@inheritDoc} + */ + @Override + protected IRepositoryItem acceptItem(URL itemURL, IRepositoryRoot root, IRepository repository) { + // Accept and register the item if it is a Java properties file + String name = itemURL.toString().toLowerCase(); + if (name.endsWith(".properties")) { + return register(itemURL, root, repository); + } + return null; + } + + /** + * Registers the properties file with the specified URL as a RobotItem. + * + * @param propertiesFileUrl is the URL of the properties file to register. + * @param root is the repository root containing the properties file to register. + * @param repository is the repository, where the properties file is automatically added or updated, + * when the properties file is registered. + * @return a RobotItem that has been created or updated in the repository. + */ + private RobotItem register(URL propertiesFileUrl, IRepositoryRoot root, IRepository repository) { + RobotItem item = null; + + // Check if the properties file is already registered in the repository + String friendlyUrl = UrlUtil.removeFileExtension(propertiesFileUrl.toString()); + + IRepositoryItem repositoryItem = repository.getItem(friendlyUrl); + if (repositoryItem instanceof RobotItem) { + item = (RobotItem) repositoryItem; + } + + // If the properties file has not been registered then create a new RobotItem based on the properties file URL + if (item == null) { + item = createRobotItem(propertiesFileUrl, root, repository); + } + + // Add or update the item in the repository and return it + if (item != null) { + repository.addOrUpdateItem(item); + } + return item; + } + + /** + * Creates a new RobotItem based on the properties file URL. + * This method will dispatch creating and registering the properties file to another handler, + * if the platform is not Java. + * + * @param propertiesFileUrl is the URL of the properties file. + * @param root is the repository root containing the properties file to create the RobotItem from. + * @param repository is the repository, where the properties file is automatically added or updated, + * when the properties file is registered. + * @return a new RobotItem that has been created or null if the RobotItem could not be created. + */ + private RobotItem createRobotItem(URL propertiesFileUrl, IRepositoryRoot root, IRepository repository) { + // Create a RobotItem based on the properties file URL + RobotItem item = new RobotItem(propertiesFileUrl, root); + + // Check if the robot is for the Java platform + String platform = item.getPlatform(); + if (platform.equalsIgnoreCase("Java")) { + // Java platform -> set the properties URL on the RobotItem + item.setPropertiesURL(propertiesFileUrl); + } else { + // Another platform -> Look for another properties handler + PropertiesHandler otherHandler = Container.getComponent(PropertiesHandler.class, + platform + "PropertiesHandler"); + + // If the another properties handler was found then let create the RobotItem; otherwise return null + return (otherHandler == null) ? null : otherHandler.createRobotItem(propertiesFileUrl, root, repository); + } + return item; + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/SourceHandler.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/SourceHandler.java new file mode 100644 index 0000000..86176a9 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/SourceHandler.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items.handlers; + + +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.items.RobotItem; +import net.sf.robocode.repository.root.ClasspathRoot; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.util.UrlUtil; + +import java.net.URL; + + +/** + * Item handler for accepting and registering source files, e.g. Java source files. + * + * @author Flemming N. Larsen (original) + */ +public class SourceHandler extends ItemHandler { + + /** + * {@inheritDoc} + */ + @Override + protected IRepositoryItem acceptItem(URL itemURL, IRepositoryRoot root, IRepository repository) { + // Accept and register the item if it is a Java source file, but not an inner Java source file (e.g. mechanical generated) + String name = itemURL.toString().toLowerCase(); + if (name.endsWith(".java") && !name.contains("$")) { + return register(itemURL, root, repository); + } + return null; + } + + /** + * Registers the source file with the specified URL as a RobotItem. + * + * @param sourceFileUrl is the URL of the source file to register. + * @param root is the repository root containing the source file to register. + * @param repository is the repository, where the source file is automatically added or updated, + * when the source file is registered. + * @return a RobotItem that has been created or updated in the repository. + */ + private RobotItem register(URL sourceFileUrl, IRepositoryRoot root, IRepository repository) { + RobotItem item = null; + + // Check if the source file is already registered in the repository with a project URL + if (root instanceof ClasspathRoot) { + String projectUrl = ((ClasspathRoot) root).getFriendlyProjectURL(sourceFileUrl); + if (projectUrl != null) { + IRepositoryItem repositoryItem = repository.getItem(projectUrl); + if (repositoryItem instanceof RobotItem) { + item = (RobotItem) repositoryItem; + } + } + } + + // If no project URL was registered with the source file then check if the source file is registered + // in the repository. + if (item == null) { + String friendlyUrl = UrlUtil.removeFileExtension(sourceFileUrl.toString()); + + IRepositoryItem repositoryItem = repository.getItem(friendlyUrl); + if (repositoryItem instanceof RobotItem) { + item = (RobotItem) repositoryItem; + } + } + + // If the source file has not been registered then create a new RobotItem based on the source file URL + if (item == null) { + item = new RobotItem(sourceFileUrl, root); + } + + // Add the root URL as source path with the RobotIteam + item.addSourcePathURL(root.getURL()); + + // Add or update the item in the repository and return it + repository.addOrUpdateItem(item); + return item; + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/TeamHandler.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/TeamHandler.java new file mode 100644 index 0000000..7b5fcfd --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/items/handlers/TeamHandler.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.items.handlers; + + +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.items.TeamItem; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.util.UrlUtil; + +import java.net.URL; + + +/** + * Item handler for accepting and registering robot team files. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class TeamHandler extends ItemHandler { + + /** + * {@inheritDoc} + */ + @Override + protected IRepositoryItem acceptItem(URL itemURL, IRepositoryRoot root, IRepository repository) { + // Accept and register the item if it is a robot team file + String name = itemURL.toString().toLowerCase(); + if (name.endsWith(".team")) { + return register(itemURL, root, repository); + } + return null; + } + + /** + * Registers the team file with the specified URL as a TeamItem. + * + * @param teamFileUrl is the URL of the team file to register. + * @param root is the repository root containing the team file to register. + * @param repository is the repository, where the team file is automatically added or updated, + * when the team file is registered. + * @return a TeamItem that has been created or updated in the repository. + */ + private TeamItem register(URL teamFileUrl, IRepositoryRoot root, IRepository repository) { + TeamItem item = null; + + // Check if the team file is already registered in the repository + String friendlyUrl = UrlUtil.removeFileExtension(teamFileUrl.toString()); + + IRepositoryItem repositoryItem = repository.getItem(friendlyUrl); + if (repositoryItem instanceof TeamItem) { + item = (TeamItem) repositoryItem; + } + + // If the team file has not been registered then create a new TeamItem based on the team file URL + if (item == null) { + item = new TeamItem(teamFileUrl, root); + } + + // Add or update the item in the repository and return it + repository.addOrUpdateItem(item); + return item; + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/packager/JarCreator.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/packager/JarCreator.java new file mode 100644 index 0000000..fb96df8 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/packager/JarCreator.java @@ -0,0 +1,267 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.packager; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.host.IHostManager; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.CodeSizeCalculator; +import net.sf.robocode.repository.IRobotItem; +import net.sf.robocode.repository.RobotProperties; +import net.sf.robocode.repository.items.RobotItem; +import net.sf.robocode.repository.items.TeamItem; +import net.sf.robocode.version.IVersionManager; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.net.URL; +import java.net.URLDecoder; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class JarCreator { + + public static String createPackage(File jarFile, List robotItems, TeamItem teamItem, RobotProperties props) { + JarOutputStream jarOut = null; + FileOutputStream fos = null; + Set jarEntries = new HashSet(); + try { + fos = new FileOutputStream(jarFile); + jarOut = new JarOutputStream(fos, createManifest(robotItems)); + + String rVersion = Container.getComponent(IVersionManager.class).getVersion(); + jarOut.setComment(rVersion + " - Robocode version"); + + boolean isTeam = teamItem != null; + + // Add robot items + addRobotItemToJar(jarOut, jarEntries, robotItems, props, isTeam); + + // Add team item, if it exists + if (isTeam) { + addTeamItemToJar(jarOut, jarEntries, teamItem, props); + } + } catch (IOException e) { + Logger.logError(e); + } finally { + FileUtil.cleanupStream(jarOut); + FileUtil.cleanupStream(fos); + } + + StringBuilder sb = new StringBuilder(); + for (String entry : jarEntries) { + sb.append(entry).append('\n'); + } + appendCodeSize(jarFile, sb); + return sb.toString(); + } + + private static Manifest createManifest(List robots) { + Manifest manifest; + + manifest = new Manifest(); + manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); + StringBuilder robotsString = new StringBuilder(); + + for (int i = 0; i < robots.size(); i++) { + robotsString.append(robots.get(i).getFullClassName()); + if (i < robots.size() - 1) { + robotsString.append(','); + } + } + manifest.getMainAttributes().put(new Attributes.Name("robots"), robotsString.toString()); + return manifest; + } + + private static void addRobotItemToJar(JarOutputStream target, Set jarEntries, List robotItems, RobotProperties props, boolean isTeam) throws IOException { + for (IRobotItem robotItem : robotItems) { + String path = robotItem.getRelativePath() + '/' + robotItem.getShortClassName() + ".properties"; + + // Add the code size to the robot properties before storing them + String classPath = robotItem.getClassPathURL().getPath(); // Takes the dev.path into account! + File dir = new File(classPath, robotItem.getRelativePath()); + Integer codeSize = CodeSizeCalculator.getDirectoryCodeSize(dir); + props.setCodeSize(codeSize); + + if (!isTeam) { + // Store local .properties file + FileOutputStream fis = null; + try { + File file = new File(classPath, path); + fis = new FileOutputStream(file); + robotItem.storeProperties(fis, props); + } finally { + FileUtil.cleanupStream(fis); + } + } + // Package robot files (.class, .properties, .java) into jar file + addRobotFilesToJar(target, jarEntries, robotItem, props); + } + } + + private static void addTeamItemToJar(JarOutputStream target, Set jarEntries, TeamItem teamItem, RobotProperties props) throws IOException { + String robotPathWithoutFileExt = teamItem.getRelativePath() + '/' + teamItem.getShortClassName(); + + File file = new File(FileUtil.getRobotsDir(), robotPathWithoutFileExt); + + // Store .team file into local robot dir + FileOutputStream fis = null; + try { + fis = new FileOutputStream(file); + teamItem.storeProperties(fis, props); + } finally { + FileUtil.cleanupStream(fis); + } + // Store .team file into jar file + addToJar(target, jarEntries, FileUtil.getRobotsDir().getPath(), robotPathWithoutFileExt, ".team"); + } + + private static void addRobotFilesToJar(JarOutputStream target, Set jarEntries, IRobotItem robotItem, RobotProperties props) throws IOException { + IHostManager host = Container.getComponent(IHostManager.class); + for (String className : host.getReferencedClasses(robotItem)) { + if (!className.startsWith("java") && !className.startsWith("robocode")) { + String robotPath = className.replace('.', '/'); + addRobotFilesToJar(target, jarEntries, robotPath, robotItem, props); + } + } + } + + private static void addRobotFilesToJar(JarOutputStream target, Set jarEntries, String robotPathWithoutFileExt, IRobotItem robotItem, RobotProperties props) throws IOException { + addClassFileToJar(target, jarEntries, robotPathWithoutFileExt, robotItem); + addPropertiesFileToJar(target, jarEntries, robotPathWithoutFileExt, robotItem); + addJavaFileToJar(target, jarEntries, robotPathWithoutFileExt, robotItem, props); + addDataDirToJar(target, jarEntries, robotPathWithoutFileExt, robotItem, props); + } + + private static void addClassFileToJar(JarOutputStream target, Set jarEntries, String robotPathWithoutFileExt, IRobotItem robotItem) throws IOException { + String classRootPath = robotItem.getClassPathURL().getPath(); + addToJar(target, jarEntries, classRootPath, robotPathWithoutFileExt, ".class"); + } + + private static void addPropertiesFileToJar(JarOutputStream target, Set jarEntries, String robotPathWithoutFileExt, IRobotItem robotItem) throws IOException { + String classRootPath = robotItem.getClassPathURL().getPath(); + addToJar(target, jarEntries, classRootPath, robotPathWithoutFileExt, ".properties"); + } + + private static void addJavaFileToJar(JarOutputStream target, Set jarEntries, String robotFilePath, IRobotItem robotItem, RobotProperties props) throws IOException { + if (props.isIncludeSource() && !robotFilePath.contains("$")) { + for (URL sourcePathURL : robotItem.getSourcePathURLs()) { + addToJar(target, jarEntries, sourcePathURL.getPath(), robotFilePath, ".java"); + } + } + } + + private static void addDataDirToJar(JarOutputStream target, Set jarEntries, String robotPathWithoutFileExt, IRobotItem robotItem, RobotProperties props) throws IOException { + if (props.isIncludeData()) { + String rootPath = robotItem.getRootPath().replace('\\', '/'); + if (rootPath.startsWith("file:/")) { + rootPath = rootPath.substring("file:/".length()); + } + addToJar(target, jarEntries, rootPath, robotPathWithoutFileExt, ".data"); + } + } + + private static void addToJar(JarOutputStream target, Set jarEntries, String rootPath, String robotPathWithoutFileExt, String fileExt) throws IOException { + String filePath = robotPathWithoutFileExt + fileExt; + try { + rootPath = URLDecoder.decode(rootPath, "UTF-8"); + } catch (UnsupportedEncodingException e) { + Logger.logError(e); + } + File file = new File(rootPath, filePath); + if (file.exists() && !jarEntries.contains(filePath)) { + addFileToJar(file, filePath, target); + jarEntries.add(filePath); + } + } + + private static void addFileToJar(File source, String entryPath, JarOutputStream target) throws IOException { + // Jar/zip files only allows '/' as file separator + String path = entryPath.replace("\\", "/"); + + // No jar/zip entry must start with an '/' + while (path.startsWith("/")) { + path = path.substring(1); + } + + if (source.isDirectory()) { + // Directory entries must end with an '/' + if (!path.isEmpty() && !path.endsWith("/")) { + path += "/"; + } + // Add all files in the directory to the target jar + for (File nestedFile: source.listFiles()) { + String newEntryPath = entryPath + '/' + nestedFile.getName(); + addFileToJar(nestedFile, newEntryPath, target); + } + } else { + JarEntry entry = new JarEntry(path); + entry.setTime(source.lastModified()); + target.putNextEntry(entry); + + // Source is a file + + FileInputStream fis = null; + BufferedInputStream bis = null; + try { + fis = new FileInputStream(source); + bis = new BufferedInputStream(fis); + + byte[] buffer = new byte[1024]; + while (true) { + int count = bis.read(buffer); + if (count == -1) { + break; + } + target.write(buffer, 0, count); + } + } finally { + target.closeEntry(); + + FileUtil.cleanupStream(bis); + FileUtil.cleanupStream(fis); + } + } + } + + private static void appendCodeSize(File jarFile, StringBuilder sb) { + Integer codesize = CodeSizeCalculator.getJarFileCodeSize(jarFile); + if (codesize != null) { + String weightClass = null; + + if (codesize >= 1500) { + weightClass = "MegaBot (codesize >= 1500 bytes)"; + } else if (codesize >= 750) { + weightClass = "MiniBot (codesize < 1500 bytes)"; + } else if (codesize >= 250) { + weightClass = "MicroBot (codesize < 750 bytes)"; + } else { + weightClass = "NanoBot (codesize < 250 bytes)"; + } + sb.append("\n\n---- Codesize ----\n"); + sb.append("Codesize: ").append(codesize).append(" bytes\n"); + sb.append("Robot weight class: ").append(weightClass).append('\n'); + } + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/packager/JarExtractor.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/packager/JarExtractor.java new file mode 100644 index 0000000..1997f1c --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/packager/JarExtractor.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.packager; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.URLJarCollector; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.InputStream; +import java.io.IOException; +import java.io.FileOutputStream; +import java.util.jar.JarInputStream; +import java.util.jar.JarEntry; +import java.net.URLConnection; +import java.net.URL; + + +/** + * @author Pavel Savara (original) + */ +public class JarExtractor { + public static void extractJar(URL url) { + File dest = FileUtil.getRobotsDir(); + InputStream is = null; + BufferedInputStream bis = null; + JarInputStream jarIS = null; + + try { + final URLConnection con = URLJarCollector.openConnection(url); + + is = con.getInputStream(); + bis = new BufferedInputStream(is); + jarIS = new JarInputStream(bis); + + JarEntry entry = jarIS.getNextJarEntry(); + + while (entry != null) { + if (entry.isDirectory()) { + File dir = new File(dest, entry.getName()); + + if (!dir.exists() && !dir.mkdirs()) { + Logger.logError("Cannot create dir: " + dir); + } + } else { + extractFile(dest, jarIS, entry); + } + entry = jarIS.getNextJarEntry(); + } + } catch (IOException e) { + Logger.logError(e); + } finally { + FileUtil.cleanupStream(jarIS); + FileUtil.cleanupStream(bis); + FileUtil.cleanupStream(is); + } + } + + public static void extractFile(File dest, JarInputStream jarIS, JarEntry entry) throws IOException { + File out = new File(dest, entry.getName()); + File parentDirectory = new File(out.getParent()); + + if (!parentDirectory.exists() && !parentDirectory.mkdirs()) { + Logger.logError("Cannot create dir: " + parentDirectory); + } + FileOutputStream fos = null; + BufferedOutputStream bos = null; + byte buf[] = new byte[2048]; + + try { + fos = new FileOutputStream(out); + bos = new BufferedOutputStream(fos); + + int num; + + while ((num = jarIS.read(buf, 0, 2048)) != -1) { + bos.write(buf, 0, num); + } + } finally { + FileUtil.cleanupStream(bos); + FileUtil.cleanupStream(fos); + } + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/parsers/ClasspathFileParser.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/parsers/ClasspathFileParser.java new file mode 100644 index 0000000..b464500 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/parsers/ClasspathFileParser.java @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.parsers; + + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + + +/** + * Class used for parsing a .classpath file in an Eclipse project. + * + * @author Flemming N. Larsen (original) + */ +public class ClasspathFileParser { + + private ClasspathHandler classpathHandler = new ClasspathHandler(); + + public void parse(URL url) { + try { + SAXParserFactory.newInstance().newSAXParser().parse(url.toString(), classpathHandler); + } catch (SAXException ignore) {} catch (IOException ignore) {} catch (ParserConfigurationException ignore) {} + } + + public String[] getSourcePaths() { + return classpathHandler.sourcePaths.toArray(new String[] {}); + } + + public String getClassPath() { + return classpathHandler.outputPath; + } + + private static class ClasspathHandler extends DefaultHandler { + String outputPath = null; + List sourcePaths = new ArrayList(); + + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if ("classpathentry".equals(qName)) { + String kind = attributes.getValue("kind"); + + if ("src".equals(kind)) { + sourcePaths.add(attributes.getValue("path")); + } else if ("output".equals(kind)) { + outputPath = attributes.getValue("path"); + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/BaseRoot.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/BaseRoot.java new file mode 100644 index 0000000..14b6c89 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/BaseRoot.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.root; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.ui.IWindowManager; + +import java.io.File; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URL; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public abstract class BaseRoot implements Serializable, IRepositoryRoot { + private static final long serialVersionUID = 1L; + + protected transient IRepository repository; + protected final File rootPath; + protected final URL rootURL; + + public BaseRoot(IRepository repository, File rootPath) { + this.repository = repository; + this.rootPath = rootPath; + + URL url = null; + try { + url = rootPath.toURI().toURL(); + } catch (MalformedURLException e) { + Logger.logError(e); + } + this.rootURL = url; + } + + public URL getURL() { + return rootURL; + } + + public File getPath() { + return rootPath; + } + + public void setRepository(IRepository repository) { + this.repository = repository; + } + + public String toString() { + return rootURL != null ? rootURL.toString() : null; + } + + public void extractJAR() { + throw new UnsupportedOperationException(); + } + + public boolean equals(Object obj) { + if (obj instanceof IRepositoryRoot) { + return ((IRepositoryRoot) obj).getURL().equals(rootURL); + } + return false; + } + + protected static void setStatus(String message) { + IWindowManager windowManager = net.sf.robocode.core.Container.getComponent(IWindowManager.class); + if (windowManager != null) { + windowManager.setStatus(message); + } + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/ClasspathRoot.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/ClasspathRoot.java new file mode 100644 index 0000000..974b510 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/ClasspathRoot.java @@ -0,0 +1,138 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.root; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.items.handlers.ItemHandler; +import net.sf.robocode.util.UrlUtil; + +import java.io.File; +import java.io.FileFilter; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + + +/** + * Represents a classpath root. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public final class ClasspathRoot extends BaseRoot implements IRepositoryRoot { + private static final long serialVersionUID = 1L; + + private final File projectPath; + + public ClasspathRoot(IRepository repository, File rootPath, File projectPath) { + super(repository, rootPath); + this.projectPath = projectPath; + } + + /** + * {@inheritDoc} + */ + public void updateItems(boolean force) { + setStatus("Updating classpath: " + rootPath.toString()); + + // We remove all items from the root so we don't need to check, which items that might have been deleted. + // This is fast to do, as items are simple referenced by friendly URLs in a map. + // Items will be re-added or updated later in this method. + repository.removeItemsFromRoot(this); + + // Retrieve all items accessible from this classpath root along with their 'last modified' date + List items = new ArrayList(); + List itemsLastModification = new ArrayList(); + + visitDirectory(rootPath, items, itemsLastModification); + + // Run thru all found repository items and update these according to their 'last modified' date + for (int i = 0; i < items.size(); i++) { + IRepositoryItem repositoryItem = items.get(i); + repositoryItem.update(itemsLastModification.get(i), force); + } + } + + private void visitDirectory(File path, final List items, final List itemsLastModification) { + + path.listFiles( + new FileFilter() { + public boolean accept(File pathname) { + if (pathname.isFile()) { + try { + IRepositoryItem repositoryItem = ItemHandler.registerItem(pathname.toURI().toURL(), + ClasspathRoot.this, repository); + if (repositoryItem != null) { + items.add(repositoryItem); + itemsLastModification.add(pathname.lastModified()); + } + } catch (MalformedURLException e) { + Logger.logError(e); + } + } + return false; + } + }); + + // find sub-directories + File[] subDirs = path.listFiles( + new FileFilter() { + public boolean accept(File pathname) { + return pathname.isDirectory() && !pathname.getName().toLowerCase().endsWith(".data") + && !pathname.getName().toLowerCase().endsWith(".robotcache"); + } + }); + + if (subDirs != null) { + for (File subDir : subDirs) { + visitDirectory(subDir, items, itemsLastModification); + } + } + } + + public void updateItem(IRepositoryItem item, boolean force) { + setStatus("Updating classpath: " + rootPath); + + File file = new File(item.getItemURL().toString()); + item.update(file.lastModified(), force); + } + + public boolean isChanged(IRepositoryItem repositoryItem) { + File file = new File(repositoryItem.getItemURL().toString()); + return file.lastModified() > repositoryItem.getLastModified(); + } + + public boolean isDevelopmentRoot() { + return true; + } + + public boolean isJAR() { + return false; + } + + public String getFriendlyProjectURL(URL itemURL) { + String url = null; + + if (projectPath != null) { + try { + String rootPath = projectPath.toURI().toURL().toString(); + String itemPath = itemURL.toString().substring(getURL().toString().length()); + + url = rootPath + UrlUtil.removeFileExtension(itemPath); + + } catch (MalformedURLException e) { + Logger.logError(e); + } + } + return url; + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/IRepositoryRoot.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/IRepositoryRoot.java new file mode 100644 index 0000000..fb99e70 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/IRepositoryRoot.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.root; + + +import net.sf.robocode.repository.items.IRepositoryItem; + +import java.io.File; +import java.net.URL; + + +/** + * @author Pavel Savara (original) + */ +public interface IRepositoryRoot { + URL getURL(); + File getPath(); + + /** + * Updates all items accessible from this repository root. + * Only items that needs to be updated will be updated, e.g. by checking the 'last modified' date on the item. + * + * @param force is a flag specifying if the items are forced to be updated. + * If this parameter is true, then all items will be updated. + */ + void updateItems(boolean force); + + void updateItem(IRepositoryItem repositoryItem, boolean force); + + boolean isJAR(); + boolean isDevelopmentRoot(); + void extractJAR(); +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/JarRoot.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/JarRoot.java new file mode 100644 index 0000000..18f7cf6 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/JarRoot.java @@ -0,0 +1,177 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.root; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.URLJarCollector; +import net.sf.robocode.io.JarJar; +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.packager.JarExtractor; +import net.sf.robocode.repository.items.IRepositoryItem; +import net.sf.robocode.repository.items.RobotItem; +import net.sf.robocode.repository.items.handlers.ItemHandler; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + + +/** + * Represents a JAR file. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public final class JarRoot extends BaseRoot implements IRepositoryRoot { + private static final long serialVersionUID = 1L; + + private final String jarPath; // without a separator ("/!") + private final URL jarUrl; + + private long lastModified; + + public JarRoot(IRepository repository, File rootPath) { + super(repository, rootPath); + String jarPath = null; + URL jarUrl = null; + try { + jarPath = "jar:" + rootPath.toURI().toString(); + jarUrl = new URL(jarPath + "!/"); + } catch (MalformedURLException e) { + Logger.logError(e); + } + this.jarPath = jarPath; + this.jarUrl = jarUrl; + } + + /** + * {@inheritDoc} + */ + public void updateItems(boolean force) { + setStatus("Updating JAR: " + rootPath.toString()); + + long lastModified = rootPath.lastModified(); + + if (lastModified > this.lastModified) { + repository.removeItemsFromRoot(this); + this.lastModified = lastModified; + + List repositoryItems = new ArrayList(); + + visitItems(repositoryItems); + for (IRepositoryItem repositoryItem : repositoryItems) { + repositoryItem.update(lastModified, force); + } + } + } + + private void visitItems(List repositoryItems) { + String root = jarPath; + InputStream is = null; + BufferedInputStream bis = null; + JarInputStream jarIS = null; + + try { + URLConnection con = URLJarCollector.openConnection(rootURL); + + is = con.getInputStream(); + bis = new BufferedInputStream(is); + jarIS = new JarInputStream(bis); + readJarStream(repositoryItems, root, jarIS); + + } catch (Exception e) { + Logger.logError(rootURL + " is probably corrupted (" + e.getClass().getName() + " " + e.getMessage() + ")"); + } finally { + FileUtil.cleanupStream(jarIS); + FileUtil.cleanupStream(bis); + FileUtil.cleanupStream(is); + } + } + + private void readJarStream(List repositoryItems, String root, JarInputStream jarIS) throws IOException { + JarEntry entry = jarIS.getNextJarEntry(); + + while (entry != null) { + String name = entry.getName().toLowerCase(); + + if (!entry.isDirectory()) { + if (name.contains(".data/") && !name.contains(".robotcache/")) { + JarExtractor.extractFile(FileUtil.getRobotsDataDir(), jarIS, entry); + } else { + if (name.endsWith(".jar") || name.endsWith(".zip")) { + JarInputStream inner = null; + + try { + inner = new JarInputStream(jarIS); + readJarStream(repositoryItems, "jar:jar" + root + JarJar.SEPARATOR + entry.getName(), inner); + } finally { + if (inner != null) { + inner.closeEntry(); + } + } + } else { + createItem(repositoryItems, new URL(root + "!/"), entry); + } + } + } + entry = jarIS.getNextJarEntry(); + } + } + + private void createItem(List repositoryItems, URL root, JarEntry entry) { + try { + String pUrl = root.toString() + entry.getName(); + IRepositoryItem repositoryItem = ItemHandler.registerItem(new URL(pUrl), JarRoot.this, repository); + + if (repositoryItem != null) { + if (repositoryItem instanceof RobotItem) { + RobotItem robotItem = (RobotItem) repositoryItem; + + robotItem.setClassPathURL(root); + } + repositoryItems.add(repositoryItem); + } + } catch (MalformedURLException e) { + Logger.logError(e); + } + } + + public void updateItem(IRepositoryItem repositoryItem, boolean force) { + repositoryItem.update(rootPath.lastModified(), force); + } + + public boolean isChanged(IRepositoryItem repositoryItem) { + return rootPath.lastModified() > lastModified; + } + + public URL getURL() { + return jarUrl; + } + + public boolean isDevelopmentRoot() { + return false; + } + + public boolean isJAR() { + return true; + } + + public void extractJAR() { + JarExtractor.extractJar(rootURL); + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/ClassPathHandler.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/ClassPathHandler.java new file mode 100644 index 0000000..fb5b16e --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/ClassPathHandler.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.root.handlers; + + +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.parsers.ClasspathFileParser; +import net.sf.robocode.repository.root.ClasspathRoot; +import net.sf.robocode.repository.root.IRepositoryRoot; + +import java.io.File; +import java.net.MalformedURLException; +import java.util.Map; + + +/** + * Handler for registering class path roots. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class ClassPathHandler extends RootHandler { + public void visitDirectory(File dir, boolean isDevel, Map newRoots, IRepository repository, boolean force) { + if (isDevel) { + File classpathFile = new File(dir, ".classpath"); + + if (classpathFile.exists()) { + ClasspathFileParser classpathParser = new ClasspathFileParser(); + + boolean parsed = true; + + try { + classpathParser.parse(classpathFile.toURI().toURL()); + } catch (MalformedURLException e) { + parsed = false; + } + if (parsed) { + String classPath = classpathParser.getClassPath(); + + if (classPath != null) { + File classPathDir = new File(dir, classPath); + + handleDirectory(classPathDir, dir, newRoots, repository, force); + } + + for (String sourcePath : classpathParser.getSourcePaths()) { + if (sourcePath != null) { + File sourcePathDir = new File(dir, sourcePath); + + handleDirectory(sourcePathDir, dir, newRoots, repository, force); + } + } + + return; // we are done! + } + } + } + handleDirectory(dir, null, newRoots, repository, force); + } + + private void handleDirectory(File dir, File projectDir, Map newRoots, IRepository repository, boolean force) { + String key; + + try { + key = dir.toURI().toURL().toString(); + } catch (MalformedURLException e) { + return; + } + + IRepositoryRoot root = repository.getRoots().get(key); + if (root == null) { + root = new ClasspathRoot(repository, dir, projectDir); + } else { + repository.removeRoot(key); + } + + root.updateItems(force); + newRoots.put(key, root); + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/JarHandler.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/JarHandler.java new file mode 100644 index 0000000..d27d0c3 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/JarHandler.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.root.handlers; + + +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.root.IRepositoryRoot; +import net.sf.robocode.repository.root.JarRoot; +import net.sf.robocode.io.Logger; +import net.sf.robocode.io.URLJarCollector; + +import java.io.File; +import java.io.FileFilter; +import java.net.MalformedURLException; +import java.util.Map; + + +/** + * @author Pavel Savara (original) + */ +public class JarHandler extends RootHandler { + public void visitDirectory(File dir, boolean isDevel, Map newRoots, IRepository repository, boolean force) { + if (!isDevel) { + // find jar files + final File[] jars = dir.listFiles(new FileFilter() { + public boolean accept(File pathname) { + String path = pathname.toString().toLowerCase(); + return pathname.isFile() && (path.endsWith(".jar") || path.endsWith(".zip")); + } + }); + + if (jars == null) { + return; // Avoid NPE by returning + } + + // update jar files + for (File jar : jars) { + String key; + + try { + key = "jar:" + jar.toURI().toURL().toString() + "!/"; + } catch (MalformedURLException e) { + e.printStackTrace(); + continue; + } + IRepositoryRoot root = repository.getRoots().get(key); + if (root == null) { + root = new JarRoot(repository, jar); + } else { + repository.removeRoot(key); + } + + root.updateItems(force); + newRoots.put(key, root); + + try { + URLJarCollector.closeJarURLConnection(jar.toURI().toURL()); + } catch (MalformedURLException e) { + Logger.logError(e); + } + URLJarCollector.gc(); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/RootHandler.java b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/RootHandler.java new file mode 100644 index 0000000..f9e3f09 --- /dev/null +++ b/代码/workspace_robo4/robocode.repository/src/main/java/net/sf/robocode/repository/root/handlers/RootHandler.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.repository.root.handlers; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.repository.IRepository; +import net.sf.robocode.repository.root.IRepositoryRoot; + +import java.io.File; +import java.util.List; +import java.util.Map; + + +/** + * @author Pavel Savara (original) + */ +public abstract class RootHandler { + public abstract void visitDirectory(File dir, boolean isDevel, Map newRoots, IRepository repository, boolean force); + + public void open() {} + + public void close() {} + + public static void visitDirectories(File dir, boolean isDevel, Map newRoots, IRepository repository, boolean force) { + // walk thru all plugins + final List itemHandlerList = Container.getComponents(RootHandler.class); + + for (RootHandler handler : itemHandlerList) { + handler.visitDirectory(dir, isDevel, newRoots, repository, force); + } + } + + public static void openHandlers() { + List rootHandlers = Container.getComponents(RootHandler.class); + for (RootHandler handler : rootHandlers) { + handler.open(); + } + } + + public static void closeHandlers() { + List rootHandlers = Container.getComponents(RootHandler.class); + for (RootHandler handler : rootHandlers) { + handler.close(); + } + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/.classpath b/代码/workspace_robo4/robocode.roborumble/.classpath new file mode 100644 index 0000000..a355dc2 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/.classpath @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.roborumble/.project b/代码/workspace_robo4/robocode.roborumble/.project new file mode 100644 index 0000000..9bd56e1 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/.project @@ -0,0 +1,20 @@ + + + robocode.roborumble + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + robocode.battle + robocode.core + robocode.host + robocode.repository + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.roborumble/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.roborumble/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.roborumble/MeleeRumble.launch b/代码/workspace_robo4/robocode.roborumble/MeleeRumble.launch new file mode 100644 index 0000000..593e4df --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/MeleeRumble.launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.roborumble/RoboRumble.launch b/代码/workspace_robo4/robocode.roborumble/RoboRumble.launch new file mode 100644 index 0000000..b1e6cf8 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/RoboRumble.launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.roborumble/TeamRumble.launch b/代码/workspace_robo4/robocode.roborumble/TeamRumble.launch new file mode 100644 index 0000000..8aa9b19 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/TeamRumble.launch @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.roborumble/pom.xml b/代码/workspace_robo4/robocode.roborumble/pom.xml new file mode 100644 index 0000000..9b66c50 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + robocode.roborumble + Roborumble Client + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + net.sf.robocode + robocode.core + ${project.version} + + + net.sf.robocode + codesize + 1.1 + + + net.sf.robocode + robocode.battle + ${project.version} + runtime + + + + + + org.apache.maven.plugins + maven-jar-plugin + + roborumble + + + roborumble.RoboRumbleAtHome + + + + + + + diff --git a/代码/workspace_robo4/robocode.roborumble/robocode.roborumble.iml b/代码/workspace_robo4/robocode.roborumble/robocode.roborumble.iml new file mode 100644 index 0000000..986c6f3 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/robocode.roborumble.iml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/BattlesRunner.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/BattlesRunner.java new file mode 100644 index 0000000..433cff6 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/BattlesRunner.java @@ -0,0 +1,235 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.roborumble.battlesengine; + + +import net.sf.robocode.io.Logger; +import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; +import robocode.control.*; +import robocode.control.events.BattleAdaptor; +import robocode.control.events.BattleCompletedEvent; +import robocode.control.events.BattleErrorEvent; + +import java.io.*; +import java.util.*; + + +/** + * The BattlesRunner is running battles. + * Reads a file with the battles to be runned and outputs the results in another file. + * Controlled by properties files. + * + * @author Albert Prez (original) + * @author Flemming N. Larsen (contributor) + * @author Joachim Hofer (contributor) + */ +public class BattlesRunner { + private final String inputfile; + private final int numrounds; + private final int fieldlen; + private final int fieldhei; + private final String outfile; + private final String user; + private String game; + private static RobotResults[] lastResults; + private static IRobocodeEngine engine; + + public BattlesRunner(String propertiesfile) { + // Read parameters + Properties parameters = getProperties(propertiesfile); + + inputfile = parameters.getProperty("INPUT", ""); + numrounds = Integer.parseInt(parameters.getProperty("ROUNDS", "10")); + fieldlen = Integer.parseInt(parameters.getProperty("FIELDL", "800")); + fieldhei = Integer.parseInt(parameters.getProperty("FIELDH", "600")); + outfile = parameters.getProperty("OUTPUT", ""); + user = parameters.getProperty("USER", ""); + + game = propertiesfile; + while (game.indexOf("/") != -1) { + game = game.substring(game.indexOf("/") + 1); + } + game = game.substring(0, game.indexOf(".")); + + initialize(); + } + + private void initialize() { + if (engine == null) { + engine = new RobocodeEngine(); + engine.addBattleListener(new BattleObserver()); + } + } + + public String getVersion() { + return (engine != null) ? engine.getVersion() : null; + } + + public void runBattlesImpl(boolean melee) { + // Initialize objects + BattlefieldSpecification field = new BattlefieldSpecification(fieldlen, fieldhei); + BattleSpecification battle = new BattleSpecification(numrounds, field, (new RobotSpecification[2])); + + // Read input file + ArrayList robots = new ArrayList(); + if (readRobots(robots)) { + return; + } + + // open output file + PrintStream outtxt = getRedirectedOutput(); + if (outtxt == null) { + return; + } + + // run battle + int index = 0; + + while (index < robots.size()) { + String[] param = (robots.get(index)).split(","); + + String enemies = getEnemies(melee, param); + + System.out.println("Fighting battle " + (index) + " ... " + enemies); + + final RobotSpecification[] robotsList = engine.getLocalRepository(enemies); + + if (robotsList.length > 1) { + final String team0 = robotsList[0].getTeamId(); + final String teamLast = robotsList[robotsList.length - 1].getTeamId(); + + if (team0 == null || !team0.equals(teamLast)) { + final BattleSpecification specification = new BattleSpecification(battle.getNumRounds(), + battle.getBattlefield(), robotsList); + + lastResults = null; + engine.runBattle(specification, true); + if (lastResults != null && lastResults.length > 1) { + dumpResults(outtxt, lastResults, param[param.length - 1], melee); + } + } + } else { + System.err.println("Skipping battle because can't load robots: " + enemies); + } + index++; + } + + // close + outtxt.close(); + } + + private String getEnemies(boolean melee, String[] param) { + String enemies; + + if (melee) { + StringBuilder eb = new StringBuilder(); + + for (int i = 0; i < param.length - 1; i++) { + if (i > 0) { + eb.append(','); + } + eb.append(param[i]); + } + enemies = eb.toString(); + } else { + enemies = param[0] + "," + param[1]; + } + return enemies; + } + + private PrintStream getRedirectedOutput() { + try { + return new PrintStream(new BufferedOutputStream(new FileOutputStream(outfile, true)), true); + } catch (IOException e) { + System.out.println("Not able to open output file ... Aborting"); + System.out.println(e); + return null; + } + } + + private boolean readRobots(ArrayList robots) { + BufferedReader br = null; + try { + FileReader fr = new FileReader(inputfile); + br = new BufferedReader(fr); + + String record; + while ((record = br.readLine()) != null) { + robots.add(record); + } + } catch (IOException e) { + System.out.println("Battles input file not found ... Aborting"); + System.out.println(e); + return true; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignore) {} + } + } + return false; + } + + private void dumpResults(PrintStream outtxt, RobotResults[] results, String last, boolean melee) { + final String BOT_INDEX_PATTERN = "\\[.*\\]"; + + for (int i = 0; i < results.length; i++) { + for (int j = 0; j < results.length; j++) { + if (i < j) { + RobotSpecification bot1 = results[i].getRobot(); + RobotSpecification bot2 = results[j].getRobot(); + + String name1 = bot1.getTeamId() != null + ? bot1.getTeamId().replaceAll(BOT_INDEX_PATTERN, "") + : bot1.getNameAndVersion(); + String name2 = bot2.getTeamId() != null + ? bot2.getTeamId().replaceAll(BOT_INDEX_PATTERN, "") + : bot2.getNameAndVersion(); + int points1 = results[i].getScore(); + int points2 = results[j].getScore(); + int bullets1 = results[i].getBulletDamage(); + int bullets2 = results[j].getBulletDamage(); + int survival1 = results[i].getFirsts(); + int survival2 = results[j].getFirsts(); + + outtxt.println( + game + "," + numrounds + "," + fieldlen + "x" + fieldhei + "," + user + "," + + System.currentTimeMillis() + "," + last); + outtxt.println(name1 + "," + points1 + "," + bullets1 + "," + survival1); + outtxt.println(name2 + "," + points2 + "," + bullets2 + "," + survival2); + } + } + } + if (melee) { + System.out.println( + "RESULT = " + results[0].getRobot().getNameAndVersion() + " wins, " + + results[1].getRobot().getNameAndVersion() + " is second."); + } else { + RobotSpecification winnerBot = results[0].getRobot(); + String winnerBotName = winnerBot.getTeamId() != null + ? winnerBot.getTeamId().replaceAll(BOT_INDEX_PATTERN, "") + : winnerBot.getNameAndVersion(); + + System.out.println( + "RESULT = " + winnerBotName + " wins " + results[0].getScore() + " to " + results[1].getScore()); + } + } + + class BattleObserver extends BattleAdaptor { + @Override + public void onBattleError(final BattleErrorEvent event) { + Logger.realErr.println(event.getError()); + } + + @Override + public void onBattleCompleted(final BattleCompletedEvent event) { + lastResults = RobotResults.convertResults(event.getSortedResults()); + } + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/CompetitionsSelector.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/CompetitionsSelector.java new file mode 100644 index 0000000..96a9e88 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/CompetitionsSelector.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.roborumble.battlesengine; + + +import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; +import static net.sf.robocode.roborumble.util.PropertiesUtil.storeProperties; + +import java.io.File; +import java.util.Properties; + +import net.sf.robocode.repository.CodeSizeCalculator; + + +/** + * This class is used to control which competitions a robot is allowed to + * participate in. + * Reads a file with the battles to be runned and outputs the results in + * another file. + * Controlled by properties files. + * + * @author Albert Prez (original) + * @author Flemming N. Larsen (contributor) + */ +public class CompetitionsSelector { + private final String repository; + private final String sizesfile; + private final Properties sizes; + + public CompetitionsSelector(String sizesfile, String repository) { + this.repository = repository; + // open sizes file + this.sizesfile = sizesfile; + + sizes = getProperties(sizesfile); + } + + public boolean checkCompetitorForSize(String botName, long maxSize) { + String name = botName.replace(' ', '_'); + + // Read sizes + long codeSize = Long.parseLong(sizes.getProperty(name, "0")); + + // Find out the size if not in the file + boolean fileNeedsUpdate = false; + + if (codeSize == 0) { + File f = new File(repository + name + ".jar"); + if (f.exists()) { + fileNeedsUpdate = true; // Bug-362 + + Integer jarFileCodeSize = CodeSizeCalculator.getJarFileCodeSize(f); + if (jarFileCodeSize != null) { + codeSize = jarFileCodeSize; + sizes.setProperty(name, Long.toString(codeSize)); + } + } + } + + // If the file needs update, then save the file + if (fileNeedsUpdate && codeSize > 0) { + storeProperties(sizes, sizesfile, "Bots code size"); + } + + // Check the code size + return (codeSize < maxSize); // Bug-362 + } + + public boolean checkCompetitorsForSize(String bot1, String bot2, long maxsize) { + return checkCompetitorForSize(bot1, maxsize) && checkCompetitorForSize(bot2, maxsize); + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/PrepareBattles.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/PrepareBattles.java new file mode 100644 index 0000000..b594e67 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/battlesengine/PrepareBattles.java @@ -0,0 +1,579 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.roborumble.battlesengine; + + +import static net.sf.robocode.roborumble.util.ExcludesUtil.*; +import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.Random; + + +/** + * PrepareBattles is used for preparing battles. + * Controlled by properties files. + * + * @author Albert Prez (original) + * @author Flemming N. Larsen (contributor) + * @author Jerome Lavigne (contributor) + */ +public class PrepareBattles { + + private final String botsrepository; + private final String participantsfile; + private final String battlesfile; + private final int numbattles; + private final CompetitionsSelector size; + private final String runonly; + private final Properties generalratings; + private final Properties miniratings; + private final Properties microratings; + private final Properties nanoratings; + private final String priority; + private final int prioritynum; + private final int meleebots; + + private final static Random RANDOM = new Random(); + + public PrepareBattles(String propertiesfile) { + // Read parameters + Properties parameters = getProperties(propertiesfile); + + botsrepository = parameters.getProperty("BOTSREP", ""); + participantsfile = parameters.getProperty("PARTICIPANTSFILE", ""); + battlesfile = parameters.getProperty("INPUT", ""); + numbattles = Integer.parseInt(parameters.getProperty("NUMBATTLES", "100")); + String sizesfile = parameters.getProperty("CODESIZEFILE", ""); + + size = new CompetitionsSelector(sizesfile, botsrepository); + runonly = parameters.getProperty("RUNONLY", "GENERAL"); + prioritynum = Integer.parseInt(parameters.getProperty("BATTLESPERBOT", "500")); + meleebots = Integer.parseInt(parameters.getProperty("MELEEBOTS", "10")); + generalratings = getProperties(parameters.getProperty("RATINGS.GENERAL", "")); + miniratings = getProperties(parameters.getProperty("RATINGS.MINIBOTS", "")); + microratings = getProperties(parameters.getProperty("RATINGS.MICROBOTS", "")); + nanoratings = getProperties(parameters.getProperty("RATINGS.NANOBOTS", "")); + priority = parameters.getProperty("PRIORITYBATTLESFILE", ""); + + // Read and prepare exclude filters + setExcludes(parameters); + } + + public boolean createBattlesList() { + List names = new ArrayList(); + + // Read participants + + BufferedReader br = null; + + try { + FileReader fr = new FileReader(participantsfile); + + br = new BufferedReader(fr); + String participant; + + while ((participant = br.readLine()) != null) { + if (participant.indexOf(",") != -1) { + String name = participant.substring(0, participant.indexOf(",")); + + if (isExcluded(name)) { + continue; // ignore excluded participant + } + String jar = name.replace(' ', '_') + ".jar"; + boolean exists = (new File(botsrepository + jar)).exists(); + + if (exists) { + if ((runonly.equals("MINI") && size.checkCompetitorForSize(name, 1500)) + || (runonly.equals("MICRO") && size.checkCompetitorForSize(name, 750)) + || (runonly.equals("NANO") && size.checkCompetitorForSize(name, 250)) + || (!runonly.equals("MINI") && !runonly.equals("MICRO") && !runonly.equals("NANO"))) { + names.add(name); + } + } + } + } + } catch (IOException e) { + System.out.println("Participants file not found ... Aborting"); + System.out.println(e); + return false; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignored) {} + } + } + // Open battles file + PrintStream outtxt; + + try { + outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(battlesfile)), false); + } catch (IOException e) { + System.out.println("Not able to open battles file " + battlesfile + " ... Aborting"); + System.out.println(e); + return false; + } + // Create the participants file + Random random = new Random(); + int count = 0; + + while (count < numbattles && names.size() > 1) { + int bot1 = random.nextInt(names.size()); + int bot2 = random.nextInt(names.size()); + + if (bot1 != bot2) { + outtxt.println(names.get(bot1) + "," + names.get(bot2) + "," + runonly); + count++; + } + } + outtxt.close(); + return true; + } + + public boolean createSmartBattlesList() { + List namesAll = new ArrayList(); + List namesMini = new ArrayList(); + List namesMicro = new ArrayList(); + List namesNano = new ArrayList(); + List namesNoRanking = new ArrayList(); + List priorityAll = new ArrayList(); + List priorityMini = new ArrayList(); + List priorityMicro = new ArrayList(); + List priorityNano = new ArrayList(); + + List priorityBattles = new ArrayList(); + + // Read participants + + BufferedReader br = null; + + try { + FileReader fr = new FileReader(participantsfile); + + br = new BufferedReader(fr); + String participant; + + while ((participant = br.readLine()) != null) { + if (participant.indexOf(",") != -1) { + String name = participant.substring(0, participant.indexOf(",")); + + if (isExcluded(name)) { + continue; // ignore excluded participant + } + String jar = name.replace(' ', '_') + ".jar"; + boolean exists = (new File(botsrepository + jar)).exists(); + + if (exists) { + namesAll.add(name); + if (size.checkCompetitorForSize(name, 1500)) { + namesMini.add(name); + } + if (size.checkCompetitorForSize(name, 750)) { + namesMicro.add(name); + } + if (size.checkCompetitorForSize(name, 250)) { + namesNano.add(name); + } + if (robotHasPriority(name, generalratings)) { + priorityAll.add(name); + } + if (size.checkCompetitorForSize(name, 1500) && robotHasPriority(name, miniratings)) { + priorityMini.add(name); + } + if (size.checkCompetitorForSize(name, 750) && robotHasPriority(name, microratings)) { + priorityMicro.add(name); + } + if (size.checkCompetitorForSize(name, 250) && robotHasPriority(name, nanoratings)) { + priorityNano.add(name); + } + if (!isRobotInRatings(name)) { + namesNoRanking.add(name); + } + } + } + } + } catch (IOException e) { + System.out.println("Participants file not found ... Aborting"); + System.out.println(e); + return false; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignored) {} + } + } + + // Read priority battles + + br = null; + + try { + FileReader fr = new FileReader(priority); + + br = new BufferedReader(fr); + String record; + + while ((record = br.readLine()) != null) { + String[] items = record.split(","); + + if (items.length == 3) { + // Check that competitors exist + String jar1 = items[0].replace(' ', '_') + ".jar"; + boolean exists1 = (new File(botsrepository + jar1)).exists() && namesAll.contains(items[0]); + String jar2 = items[1].replace(' ', '_') + ".jar"; + boolean exists2 = (new File(botsrepository + jar2)).exists() && namesAll.contains(items[1]); + + // Add battles to priority battles list + if (exists1 && exists2 && !priorityBattles.contains(record)) { + priorityBattles.add(record); + } else { + System.out.println("Ignoring: " + record); + } + } + } + } catch (IOException e) { + System.out.println("Priority battles file not found ... "); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignore) {} + } + } + + // Delete priority battles (avoid duplication) + File r = new File(priority); + + if (r.exists() && !r.delete()) { + System.out.println("Cannot delete: " + priority); + } + + // Open battles file + PrintStream outtxt; + + try { + outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(battlesfile)), false); + } catch (IOException e) { + System.out.println("Not able to open battles file " + battlesfile + " ... Aborting"); + System.out.println(e); + return false; + } + + // Create the participants file + int count = 0; + + // Add priority battles + while (count < numbattles && count < priorityBattles.size()) { + String battle = priorityBattles.get(count); + outtxt.println(battle); + count++; + } + // Add bots with less than 500 battles, or a random battle if all bots have enough battles + if (namesAll.size() > 1) { + while (count < numbattles) { + String[] bots; + if (namesNoRanking.size() > 0) { + // Bug [3547611] - New bots not given priority + List listWithSingleItem = new ArrayList(); + String bot = namesNoRanking.get(0); + listWithSingleItem.add(bot); + bots = getRandomBots(listWithSingleItem, namesAll); + namesNoRanking.remove(0); + } else if (priorityAll.size() > 0) { + bots = getRandomBots(priorityAll, namesAll); + } else if (priorityMini.size() > 0 && namesMini.size() > 1) { + bots = getRandomBots(priorityMini, namesMini); + } else if (priorityMicro.size() > 0 && namesMicro.size() > 1) { + bots = getRandomBots(priorityMicro, namesMicro); + } else if (priorityNano.size() > 0 && namesNano.size() > 1) { + bots = getRandomBots(priorityNano, namesNano); + } else { + bots = getRandomBots(namesAll, namesAll); + } + if (bots != null) { + outtxt.println(bots[0] + "," + bots[1] + "," + runonly); + count++; + } + } + } + outtxt.close(); + return true; + } + + private String[] getRandomBots(List list1, List list2) { + int bot1 = RANDOM.nextInt(list1.size()); + int bot2 = RANDOM.nextInt(list2.size()); + + while ((list1.get(bot1)).equals(list2.get(bot2))) { + bot1 = RANDOM.nextInt(list1.size()); + bot2 = RANDOM.nextInt(list2.size()); + } + String[] bots = new String[2]; + + bots[0] = list1.get(bot1); + bots[1] = list2.get(bot2); + return bots; + } + + private boolean robotHasPriority(String name, Properties ratings) { + if (name == null || ratings == null) { + return false; + } + String bot = name.replaceAll(" ", "_"); + String values = ratings.getProperty(bot); + + if (values == null) { + return false; // must be false (Bug 3474173) + } + String[] value = values.split(","); + double battles = Double.parseDouble(value[1]); + + return (battles < prioritynum); + } + + private boolean isRobotInRatings(String name) { + if (name == null || name.trim().length() == 0) { + return false; + } + String bot = name.replaceAll(" ", "_"); + + Properties[] ratingLists = new Properties[] { generalratings, miniratings, microratings, nanoratings }; + + for (Properties ratings : ratingLists) { + if (ratings.getProperty(bot) != null) { + return true; + } + } + return false; + } + + public boolean createMeleeBattlesList() { + List namesAll = new ArrayList(); + List namesMini = new ArrayList(); + List namesMicro = new ArrayList(); + List namesNano = new ArrayList(); + List namesNoRanking = new ArrayList(); + List priorityAll = new ArrayList(); + List priorityMini = new ArrayList(); + List priorityMicro = new ArrayList(); + List priorityNano = new ArrayList(); + + List priorityPairs = new ArrayList(); + + // Read participants + + BufferedReader br = null; + + try { + FileReader fr = new FileReader(participantsfile); + + br = new BufferedReader(fr); + String participant; + + while ((participant = br.readLine()) != null) { + if (participant.indexOf(",") != -1) { + String name = participant.substring(0, participant.indexOf(",")); + + if (isExcluded(name)) { + continue; // ignore excluded participant + } + String jar = name.replace(' ', '_') + ".jar"; + boolean exists = (new File(botsrepository + jar)).exists(); + + if (exists) { + namesAll.add(name); + if (size.checkCompetitorForSize(name, 1500)) { + namesMini.add(name); + } + if (size.checkCompetitorForSize(name, 750)) { + namesMicro.add(name); + } + if (size.checkCompetitorForSize(name, 250)) { + namesNano.add(name); + } + if (robotHasPriority(name, generalratings)) { + priorityAll.add(name); + } + if (size.checkCompetitorForSize(name, 1500) && robotHasPriority(name, miniratings)) { + priorityMini.add(name); + } + if (size.checkCompetitorForSize(name, 750) && robotHasPriority(name, microratings)) { + priorityMicro.add(name); + } + if (size.checkCompetitorForSize(name, 250) && robotHasPriority(name, nanoratings)) { + priorityNano.add(name); + } + if (!isRobotInRatings(name)) { + namesNoRanking.add(name); + } + } + } + } + } catch (IOException e) { + System.out.println("Participants file not found ... Aborting"); + System.out.println(e); + return false; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignored) {} + } + } + + // Read priority battles + + br = null; + + try { + FileReader fr = new FileReader(priority); + + br = new BufferedReader(fr); + String record; + + while ((record = br.readLine()) != null) { + String[] items = record.split(","); + + if (items.length == 3) { + // Check that competitors exist + String jar1 = items[0].replace(' ', '_') + ".jar"; + boolean exists1 = (new File(botsrepository + jar1)).exists() && namesAll.contains(items[0]); + String jar2 = items[1].replace(' ', '_') + ".jar"; + boolean exists2 = (new File(botsrepository + jar2)).exists() && namesAll.contains(items[1]); + + // Add battles to priority battles vector + if (exists1 && exists2 && !priorityPairs.contains(items)) { + priorityPairs.add(items); + } else { + System.out.println("Ignoring: " + record); + } + } + } + } catch (IOException e) { + System.out.println("Priority battles file not found ... "); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignore) {} + } + } + + // Delete priority battles (avoid duplication) + File r = new File(priority); + + if (r.exists() && !r.delete()) { + System.out.println("Cannot delete: " + priority); + } + + // Open battles file + PrintStream outtxt; + + try { + outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(battlesfile)), false); + } catch (IOException e) { + System.out.println("Not able to open battles file " + battlesfile + " ... Aborting"); + System.out.println(e); + return false; + } + + // Create the participants file + int count = 0; + + // Add bots with less than 500 battles, or a random battle if all bots have enough battles + if (namesAll.size() > meleebots) { + while (count < numbattles) { + String[] bots = null; + if (namesNoRanking.size() > 0) { + // Bug [3547611] - New bots not given priority + List listWithSingleItem = new ArrayList(); + String bot = namesNoRanking.get(0); + listWithSingleItem.add(bot); + bots = getRandomMeleeBots(listWithSingleItem, namesAll); + namesNoRanking.remove(0); + } else if (count < priorityPairs.size()) { + String[] prioritybots = priorityPairs.get(count); + bots = getRandomMeleeBots(prioritybots[0], prioritybots[1], namesAll); + } else if (priorityAll.size() > 0 && namesAll.size() >= meleebots) { + bots = getRandomMeleeBots(priorityAll, namesAll); + } else if (priorityMini.size() > 0 && namesMini.size() >= meleebots) { + bots = getRandomMeleeBots(priorityMini, namesMini); + } else if (priorityMicro.size() > 0 && namesMicro.size() >= meleebots) { + bots = getRandomMeleeBots(priorityMicro, namesMicro); + } else if (priorityNano.size() > 0 && namesNano.size() >= meleebots) { + bots = getRandomMeleeBots(priorityNano, namesNano); + } else if (namesAll.size() >= meleebots) { + bots = getRandomMeleeBots(namesAll, namesAll); + } + if (bots != null) { + StringBuilder battle = new StringBuilder(bots[0]); + + for (int i = 1; i < bots.length; i++) { + battle.append(',').append(bots[i]); + } + battle.append(',').append(runonly); + + outtxt.println(battle); + count++; + } + } + } + outtxt.close(); + return true; + } + + private String[] getRandomMeleeBots(List list1, List list2) { + String[] bots = new String[meleebots]; + + bots[0] = list1.get(RANDOM.nextInt(list1.size())); + int count = 1; + + while (count < meleebots) { + bots[count] = list2.get(RANDOM.nextInt(list2.size())); + boolean exists = false; + + for (int i = 0; i < count; i++) { + if (bots[i].equals(bots[count])) { + exists = true; + } + } + if (!exists) { + count++; + } + } + return bots; + } + + private String[] getRandomMeleeBots(String bot1, String bot2, List list2) { + String[] bots = new String[meleebots]; + + bots[0] = bot1; + bots[1] = bot2; + int count = 2; + + while (count < meleebots) { + bots[count] = list2.get(RANDOM.nextInt(list2.size())); + boolean exists = false; + + for (int i = 0; i < count; i++) { + if (bots[i].equals(bots[count])) { + exists = true; + } + } + if (!exists) { + count++; + } + } + return bots; + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/BotsDownload.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/BotsDownload.java new file mode 100644 index 0000000..b8c2d87 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/BotsDownload.java @@ -0,0 +1,625 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.roborumble.netengine; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.roborumble.battlesengine.CompetitionsSelector; +import static net.sf.robocode.roborumble.netengine.FileTransfer.DownloadStatus; +import static net.sf.robocode.roborumble.util.ExcludesUtil.*; +import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; +import java.util.Vector; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; + + +/** + * Class used for downloading participating robots from the Internet. + * Manages the download operations (participants and JAR files). + * Controlled by properties files. + * + * @author Albert Prez (original) + * @author Flemming N. Larsen (contributor) + */ +public class BotsDownload { + + // private String internetrepository; + private final String botsrepository; + private final String participantsfile; + private final String participantsurl; + private final String tempdir; + private final String tag; + private final String isteams; + private final String sizesfile; + private final CompetitionsSelector size; + private final String ratingsurl; + private String generalBots; + private final String miniBots; + private final String microBots; + private final String nanoBots; + private final String generalbotsfile; + private final String minibotsfile; + private final String microbotsfile; + private final String nanobotsfile; + private final String removeboturl; + + public BotsDownload(String propertiesfile) { + // Read parameters + Properties parameters = getProperties(propertiesfile); + + botsrepository = parameters.getProperty("BOTSREP", ""); + isteams = parameters.getProperty("TEAMS", "NOT"); + participantsurl = parameters.getProperty("PARTICIPANTSURL", ""); + participantsfile = parameters.getProperty("PARTICIPANTSFILE", ""); + tag = parameters.getProperty("STARTAG", "pre"); + tempdir = parameters.getProperty("TEMP", ""); + + // Code size + sizesfile = parameters.getProperty("CODESIZEFILE", ""); + size = new CompetitionsSelector(sizesfile, botsrepository); + + // Ratings files + ratingsurl = parameters.getProperty("RATINGS.URL", ""); + generalBots = propertiesfile; + while (generalBots.indexOf("/") != -1) { + generalBots = generalBots.substring(generalBots.indexOf("/") + 1); + } + generalBots = generalBots.substring(0, generalBots.indexOf(".")); + miniBots = parameters.getProperty("MINIBOTS", ""); + microBots = parameters.getProperty("MICROBOTS", ""); + nanoBots = parameters.getProperty("NANOBOTS", ""); + generalbotsfile = parameters.getProperty("RATINGS.GENERAL", ""); + minibotsfile = parameters.getProperty("RATINGS.MINIBOTS", ""); + microbotsfile = parameters.getProperty("RATINGS.MICROBOTS", ""); + nanobotsfile = parameters.getProperty("RATINGS.NANOBOTS", ""); + // remove old bots + removeboturl = parameters.getProperty("UPDATEBOTSURL", ""); + + // Read and prepare exclude filters + setExcludes(parameters); + } + + public boolean downloadRatings() { + File file; + + // delete previous files + if (generalbotsfile.length() != 0) { + file = new File(generalbotsfile); + if (file.exists() && !file.delete()) { + Logger.logError("Can't delete file: " + file); + } + } + if (minibotsfile.length() != 0) { + file = new File(minibotsfile); + if (file.exists() && !file.delete()) { + Logger.logError("Can't delete file: " + file); + } + } + if (microbotsfile.length() != 0) { + file = new File(microbotsfile); + if (file.exists() && !file.delete()) { + Logger.logError("Can't delete file: " + file); + } + } + if (nanobotsfile.length() != 0) { + file = new File(nanobotsfile); + if (file.exists() && !file.delete()) { + Logger.logError("Can't delete file: " + file); + } + } + // download new ones + if (ratingsurl.length() == 0) { + return false; + } + boolean downloaded = true; + + if (generalBots.length() != 0 && generalbotsfile.length() != 0) { + downloaded = downloadRatingsFile(generalBots, generalbotsfile) & downloaded; + } + if (miniBots.length() != 0 && minibotsfile.length() != 0) { + downloaded = downloadRatingsFile(miniBots, minibotsfile) & downloaded; + } + if (microBots.length() != 0 && microbotsfile.length() != 0) { + downloaded = downloadRatingsFile(microBots, microbotsfile) & downloaded; + } + if (nanoBots.length() != 0 && nanobotsfile.length() != 0) { + downloaded = downloadRatingsFile(nanoBots, nanobotsfile) & downloaded; + } + return downloaded; + } + + public boolean downloadParticipantsList() { + String begin = "<" + tag + ">"; + String end = ""; + Vector bots = new Vector(); + + InputStream in = null; + InputStreamReader inputStreamReader = null; + BufferedReader bufferedReader = null; + HttpURLConnection conn = null; + + try { + URL url = new URL(participantsurl); + + conn = FileTransfer.connectToHttpInputConnection(url); + + // Check that we received a HTTP_OK response code. + // Bugfix [2779557] - Client tries to remove all participants. + if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { + System.out.print("Unable to retrieve participants list. Response is " + conn.getResponseCode()); + if (conn.getResponseMessage() != null) { + System.out.print(": " + conn.getResponseMessage()); + } + System.out.println(); + + return false; // Error + } + + boolean arebots = false; + + in = FileTransfer.getInputStream(conn); + inputStreamReader = new InputStreamReader(in); + bufferedReader = new BufferedReader(inputStreamReader); + + for (String participant; (participant = bufferedReader.readLine()) != null;) { + if (participant.indexOf(begin) >= 0) { + arebots = true; + } else if (participant.indexOf(end) >= 0) { + arebots = false; + } else if (arebots) { + String bot = participant.split("[,]")[0]; + + if (!isExcluded(bot)) { + if (!verifyParticipantFormat(participant)) { + if (participant.trim().length() > 0) { + System.out.println("Participant ignored due to invalid line: " + bot); + } + } else { + bots.add(participant); + } + } else { + System.out.println("Ignored excluded: " + bot); + } + } + } + + // Prevent our local participants file to be overwritten, if the downloaded list is empty. + // Bugfix [2779557] - Client tries to remove all participants. + if (bots.size() == 0) { + System.out.println("The participants list is empty"); + return false; // Error + } + + final File dir = new File(participantsfile).getParentFile(); + + if (!dir.exists() && !dir.mkdirs()) { + Logger.logError("Can't create directory: " + dir); + } + + PrintStream outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(participantsfile)), false); + + for (String bot : bots) { + outtxt.println(bot); + } + outtxt.close(); + + } catch (IOException e) { + System.out.println("Unable to retrieve participants list:"); + System.out.println(e); + return false; // Error + } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException ignored) {} + } + if (conn != null) { + conn.disconnect(); + } + } + return true; // Success + } + + public void downloadMissingBots() { + Vector jars = new Vector(); + Vector ids = new Vector(); + Vector names = new Vector(); + + // Read participants + + BufferedReader br = null; + + try { + FileReader fr = new FileReader(participantsfile); + br = new BufferedReader(fr); + + for (String record; (record = br.readLine()) != null;) { + if (record.indexOf(",") >= 0) { + String id = record.substring(record.indexOf(",") + 1).trim(); + String name = record.substring(0, record.indexOf(",")).trim(); + String jar = name.replace(' ', '_') + ".jar"; + + jars.add(jar); + ids.add(id); + names.add(name); + } + } + } catch (IOException e) { + System.out.println("Participants file not found ... Aborting"); + System.out.println(e); + return; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignored) {} + } + } + + // check if the file exists in the repository and download if not present + for (int i = 0; i < jars.size(); i++) { + String botjar = jars.get(i); + String botid = ids.get(i); + String botname = names.get(i); + String botpath = botsrepository + botjar; + boolean exists = (new File(botpath)).exists(); + + if (!exists) { + boolean downloaded = downloadBot(botname, botjar, botid, botsrepository, tempdir); + if (!downloaded) { + System.out.println("Could not download " + botjar); + } + } + } + } + + public void updateCodeSize() { + if (sizesfile.length() != 0) { + BufferedReader br = null; + try { + FileReader fr = new FileReader(participantsfile); + br = new BufferedReader(fr); + + for (String record; (record = br.readLine()) != null;) { + String name = record.substring(0, record.indexOf(",")); + size.checkCompetitorForSize(name, 1500); + } + } catch (IOException e) { + System.out.println("Battles input file not found ... Aborting"); + System.out.println(e); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignored) {} + } + } + } + } + + private boolean downloadBot(String botname, String file, String id, String destination, String tempdir) { + String tempFileName = tempdir + file; + String repositoryFileName = destination + file; + + // check if the bot exists in the repository + + boolean exists = (new File(repositoryFileName)).exists(); + if (exists) { + System.out.println("The bot already exists in the repository."); + return false; + } + + // Download the bot + + String url; + String sessionId = null; + + if (id.indexOf("://") == -1) { + url = "http://robocoderepository.com/Controller.jsp?submitAction=downloadClass&id=" + id; + + sessionId = FileTransfer.getSessionId( + "http://robocoderepository.com/BotSearch.jsp?botName=''&authorName=''&uploadDate="); + } else { + url = id; + } + + DownloadStatus downloadStatus = FileTransfer.download(url, tempFileName, sessionId); + + if (downloadStatus == DownloadStatus.FILE_NOT_FOUND) { + System.out.println("Could not find " + botname + " from " + url); + return false; + } else if (downloadStatus == DownloadStatus.COULD_NOT_CONNECT) { + System.out.println("Could not connect to " + url); + return false; + } + + // Check the bot and save it into the repository + + if (checkJarFile(tempFileName, botname)) { + if (!FileTransfer.copy(tempFileName, repositoryFileName)) { + System.out.println("Unable to copy " + tempFileName + " into the repository"); + return false; + } + } else { + System.out.println("Downloaded file is wrong or corrupted: " + file); + return false; + } + + System.out.println("Downloaded " + botname + " into " + repositoryFileName); + return true; + } + + private boolean checkJarFile(String file, String botname) { + if (botname.indexOf(" ") == -1) { + System.out.println("Are you sure " + botname + " is a bot/team? Can't download it."); + return false; + } + + String bot = botname.substring(0, botname.indexOf(" ")); + + bot = bot.replace('.', '/'); + if (isteams.equals("YES")) { + bot += ".team"; + } else { + bot += ".properties"; + } + + try { + JarFile jarf = new JarFile(file); + ZipEntry zipe = jarf.getJarEntry(bot); + + if (zipe == null) { + System.out.println("Not able to read properties"); + return false; + } + InputStream properties = jarf.getInputStream(zipe); + + Properties parameters = getProperties(properties); + + if (!isteams.equals("YES")) { + String classname = parameters.getProperty("robot.classname", ""); + String version = parameters.getProperty("robot.version", ""); + + return (botname.equals(classname + " " + version)); + } + String version = parameters.getProperty("team.version", ""); + + return (botname.equals(botname.substring(0, botname.indexOf(" ")) + " " + version)); + } catch (Exception e) { + System.out.println(e); + return false; + } + } + + // ---------------------------------------------------------------------------------- + // download ratings file + // ---------------------------------------------------------------------------------- + private boolean downloadRatingsFile(String competition, String file) { + + InputStream in = null; + InputStreamReader inputStreamReader = null; + BufferedReader bufferedReader = null; + PrintStream outtxt = null; + + try { + URL url = new URL(ratingsurl + "?version=1&game=" + competition); + + HttpURLConnection conn = FileTransfer.connectToHttpInputConnection(url); + + final File dir = new File(file).getParentFile(); + + if (!dir.exists() && !dir.mkdirs()) { + Logger.logError("Can't create directory: " + dir); + } + + outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)), false); + + in = FileTransfer.getInputStream(conn); + inputStreamReader = new InputStreamReader(in); + bufferedReader = new BufferedReader(inputStreamReader); + + for (String str; (str = bufferedReader.readLine()) != null;) { + outtxt.println(str); + } + conn.disconnect(); + + } catch (IOException e) { + System.out.println("Unable to ratings for " + competition); + System.out.println(e); + return false; + } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException ignored) {} + } + if (outtxt != null) { + outtxt.close(); + } + } + return true; + } + + // ---------------------------------------------------------------------------------- + // download ratings file + // ---------------------------------------------------------------------------------- + + public void notifyServerForOldParticipants() { + // Load participants names + Set namesAll = new HashSet(); + Set namesMini = new HashSet(); + Set namesMicro = new HashSet(); + Set namesNano = new HashSet(); + + BufferedReader br = null; + try { + FileReader fr = new FileReader(participantsfile); + br = new BufferedReader(fr); + + for (String record; (record = br.readLine()) != null;) { + if (record.indexOf(",") != -1) { + String name = record.substring(0, record.indexOf(",")).replace(' ', '_'); + + namesAll.add(name); + if (size.checkCompetitorForSize(name, 1500)) { + namesMini.add(name); + } + if (size.checkCompetitorForSize(name, 750)) { + namesMicro.add(name); + } + if (size.checkCompetitorForSize(name, 250)) { + namesNano.add(name); + } + } + } + } catch (IOException e) { + System.out.println("Participants file not found when removing old participants ... Aborting"); + System.out.println(e); + return; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignored) {} + } + } + + // Load ratings files + Properties generalRatings = getProperties(generalbotsfile); + Properties miniRatings = getProperties(minibotsfile); + Properties microRatings = getProperties(microbotsfile); + Properties nanoRatings = getProperties(nanobotsfile); + + // Check general ratings + for (Enumeration e = generalRatings.propertyNames(); e.hasMoreElements();) { + String bot = (String) e.nextElement(); + + if (!(isExcluded(bot) || namesAll.contains(bot))) { + // Remove the bot from the ratings file + System.out.println("Removing entry ... " + bot + " from " + generalBots); + removeBot(generalBots, bot); + } + } + // Check mini ratings + for (Enumeration e = miniRatings.propertyNames(); e.hasMoreElements();) { + String bot = (String) e.nextElement(); + + if (!(isExcluded(bot) || namesMini.contains(bot))) { + // Remove the bot from the ratings file + System.out.println("Removing entry ... " + bot + " from " + miniBots); + removeBot(miniBots, bot); + } + } + + // Check micro ratings + for (Enumeration e = microRatings.propertyNames(); e.hasMoreElements();) { + String bot = (String) e.nextElement(); + + if (!(isExcluded(bot) || namesMicro.contains(bot))) { + // Remove the bot from the ratings file + System.out.println("Removing entry ... " + bot + " from " + microBots); + removeBot(microBots, bot); + } + } + + // Check nano ratings + for (Enumeration e = nanoRatings.propertyNames(); e.hasMoreElements();) { + String bot = (String) e.nextElement(); + + if (!(isExcluded(bot) || namesNano.contains(bot))) { + // Remove the bot from the ratings file + System.out.println("Removing entry ... " + bot + " from " + nanoBots); + removeBot(nanoBots, bot); + } + } + } + + private void removeBot(String game, String bot) { + if (removeboturl.length() == 0) { + System.out.println("UPDATEBOTS URL not defined!"); + return; + } + + String data = "version=1&game=" + game + "&name=" + bot.trim() + "&dummy=NA"; + + OutputStream out = null; + OutputStreamWriter outputStreamWriter = null; + PrintWriter wr = null; + InputStream in = null; + InputStreamReader inputStreamReader = null; + BufferedReader bufferedReader = null; + + try { + // Send data + URLConnection conn = FileTransfer.openOutputURLConnection(new URL(removeboturl)); + + out = FileTransfer.getOutputStream(conn); + outputStreamWriter = new OutputStreamWriter(out); + wr = new PrintWriter(outputStreamWriter); + + wr.println(data); + wr.flush(); + + // Get the response + in = FileTransfer.getInputStream(conn); + inputStreamReader = new InputStreamReader(in); + bufferedReader = new BufferedReader(inputStreamReader); + + for (String line; (line = bufferedReader.readLine()) != null;) { + System.out.println(line); + } + } catch (IOException e) { + System.out.println(e); + } finally { + if (wr != null) { + wr.close(); + } + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException ignored) {} + } + } + } + + // Checks if a participant format from the participant list is valid + private boolean verifyParticipantFormat(String participant) { + String[] split = participant.split("[,]"); + + boolean matches = false; + + if (split.length == 2) { + String robot = split[0].trim(); + String link = split[1].trim(); + + if (robot.matches("[\\w\\.]+[ ][\\w\\.-]+")) { + if (link.startsWith("http")) { + try { + new URL(link); + matches = true; + } catch (MalformedURLException e) { + matches = false; + } + } else if (link.matches("[\\d]+")) { + matches = true; + } + } + } + return matches; + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/ResultsUpload.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/ResultsUpload.java new file mode 100644 index 0000000..aaa5246 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/ResultsUpload.java @@ -0,0 +1,328 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.roborumble.netengine; + + +import net.sf.robocode.roborumble.battlesengine.CompetitionsSelector; +import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; + +import java.io.*; +import java.net.URL; +import java.net.URLConnection; +import java.util.Properties; +import java.util.Vector; + + +/** + * Class used for uploading results to a server. + * Controlled by properties files. + * + * @author Albert Prez (original) + * @author Flemming N. Larsen (contributor) + */ +public class ResultsUpload { + + private final String client; + private final String resultsfile; + private final String resultsurl; + private final String tempdir; + private String game; + private final String user; + private final String sizesfile; + private final String minibots; + private final String microbots; + private final String nanobots; + private final CompetitionsSelector size; + private final String battlesnumfile; + private final String priority; + private final String teams; + private final String melee; + + public ResultsUpload(String propertiesfile, String clientVersion) { + // Read parameters + Properties parameters = getProperties(propertiesfile); + + resultsfile = parameters.getProperty("OUTPUT", ""); + resultsurl = parameters.getProperty("RESULTSURL", ""); + tempdir = parameters.getProperty("TEMP", ""); + user = parameters.getProperty("USER", ""); + game = propertiesfile; + String botsrepository = parameters.getProperty("BOTSREP", ""); + + while (game.indexOf("/") != -1) { + game = game.substring(game.indexOf("/") + 1); + } + game = game.substring(0, game.indexOf(".")); + sizesfile = parameters.getProperty("CODESIZEFILE", ""); + minibots = parameters.getProperty("MINIBOTS", ""); + microbots = parameters.getProperty("MICROBOTS", ""); + nanobots = parameters.getProperty("NANOBOTS", ""); + battlesnumfile = parameters.getProperty("BATTLESNUMFILE", ""); + priority = parameters.getProperty("PRIORITYBATTLESFILE", ""); + client = clientVersion; + teams = parameters.getProperty("TEAMS", "NOT"); + melee = parameters.getProperty("MELEE", "NOT"); + + // Open competitions selector + size = new CompetitionsSelector(sizesfile, botsrepository); + } + + public void uploadResults() { + + boolean errorsfound = false; + + // Read the results file + + Vector results = new Vector(); + String match = ""; + String bot1 = ""; + String bot2; + int status = 0; + BufferedReader br = null; + + try { + FileReader fr = new FileReader(resultsfile); + + br = new BufferedReader(fr); + String record; + + while ((record = br.readLine()) != null) { + if (record.indexOf(game) != -1) { + match = record; + status = 0; + } else if (status == 0) { + bot1 = record; + status = 1; + } else if (status == 1) { + bot2 = record; + results.add(match); + results.add(bot1); + results.add(bot2); + } + } + } catch (IOException e) { + System.out.println("Can't open result file for upload"); + return; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignored) {} + } + } + + // Open the temp file to put the unuploaded results + PrintStream outtxt; + + try { + outtxt = new PrintStream(new BufferedOutputStream(new FileOutputStream(tempdir + "results.txt")), false); + } catch (IOException e) { + System.out.println("Not able to open output file ... Aborting"); + System.out.println(e); + return; + } + + // Open the file to put the battles number for each participant + PrintStream battlesnum; + + try { + battlesnum = new PrintStream(new BufferedOutputStream(new FileOutputStream(battlesnumfile)), false); + } catch (IOException e) { + System.out.println("Not able to open battles number file ... Aborting"); + System.out.println(e); + + outtxt.close(); + return; + } + + // Open the file to put the battles which have priority + PrintStream prioritybattles; + + try { + prioritybattles = new PrintStream(new BufferedOutputStream(new FileOutputStream(priority)), false); + } catch (IOException e) { + System.out.println("Not able to open priorities file ... Aborting"); + System.out.println(e); + + outtxt.close(); + battlesnum.close(); + return; + } + + // Post the results + + for (int i = 0; i < results.size() / 3; i++) { + + // Create the parameters String + String[] header = results.get(i * 3).split(","); + String[] first = results.get(i * 3 + 1).split(","); + String[] second = results.get(i * 3 + 2).split(","); + + // find the match mode + String matchtype = "GENERAL"; + + if (header.length >= 6) { + matchtype = header[5]; + } + + // if the match mode was general, then send the results to all competitions (assuming codesize is used). + // if its not, then send results only to smaller size competitions + + final String commonData = "&version=1" + "&client=" + client + "&teams=" + teams + "&melee=" + melee + + "&rounds=" + header[1] + "&field=" + header[2] + "&user=" + user + "&time=" + header[4] + "&fname=" + + first[0] + "&fscore=" + first[1] + "&fbulletd=" + first[2] + "&fsurvival=" + first[3] + "&sname=" + + second[0] + "&sscore=" + second[1] + "&sbulletd=" + second[2] + "&ssurvival=" + second[3]; + + String data = "game=" + game + commonData; + + if (matchtype.equals("GENERAL") || matchtype.equals("SERVER")) { + errorsfound = errorsfound | senddata(game, data, outtxt, true, results, i, battlesnum, prioritybattles); + } + + if (sizesfile.length() != 0) { // upload also related competitions + if (minibots.length() != 0 && !matchtype.equals("NANO") && !matchtype.equals("MICRO") + && size.checkCompetitorsForSize(first[0], second[0], 1500)) { + data = "game=" + minibots + commonData; + errorsfound = errorsfound + | senddata(minibots, data, outtxt, true, results, i, battlesnum, prioritybattles); + } + if (microbots.length() != 0 && !matchtype.equals("NANO") + && size.checkCompetitorsForSize(first[0], second[0], 750)) { + data = "game=" + microbots + commonData; + errorsfound = errorsfound + | senddata(microbots, data, outtxt, true, results, i, battlesnum, prioritybattles); + } + if (nanobots.length() != 0 && size.checkCompetitorsForSize(first[0], second[0], 250)) { + data = "game=" + nanobots + commonData; + errorsfound = errorsfound + | senddata(nanobots, data, outtxt, true, results, i, battlesnum, prioritybattles); + } + } + } + + // close files + outtxt.close(); + battlesnum.close(); + prioritybattles.close(); + + // delete results file + File r = new File(resultsfile); + boolean b = r.delete(); + + if (!b) { + System.out.println("Unable to delete results file."); + } + + // copy temp file into results file if there was some error + if (errorsfound) { + if (!FileTransfer.copy(tempdir + "results.txt", resultsfile)) { + System.out.println("Error when copying results errors file."); + } + } + } + + private void saveError(PrintStream outtxt, String match, String bot1, String bot2, boolean saveonerror) { + if (saveonerror) { + outtxt.println(match); + outtxt.println(bot1); + outtxt.println(bot2); + } + System.out.println("Unable to upload results " + match + " " + bot1 + " " + bot2); + } + + private boolean senddata(String game, String data, PrintStream outtxt, boolean saveonerror, Vector results, int i, PrintStream battlesnum, PrintStream prioritybattles) { + boolean errorsfound = false; + OutputStream out = null; + OutputStreamWriter outputStreamWriter = null; + PrintWriter wr = null; + InputStream in = null; + InputStreamReader inputStreamReader = null; + BufferedReader bufferedReader = null; + + try { + // Send data + URLConnection conn = FileTransfer.openOutputURLConnection(new URL(resultsurl)); + + out = FileTransfer.getOutputStream(conn); + outputStreamWriter = new OutputStreamWriter(out); + wr = new PrintWriter(outputStreamWriter); + + wr.println(data); + wr.flush(); + + // Get the response + in = FileTransfer.getInputStream(conn); + inputStreamReader = new InputStreamReader(in); + bufferedReader = new BufferedReader(inputStreamReader); + + String line; + boolean ok = false; + + while ((line = bufferedReader.readLine()) != null) { + if (line.indexOf("OK") != -1) { + ok = true; + System.out.println(line); + } else if (line.indexOf("<") != -1 && line.indexOf(">") != -1) { + // System.out.println(line); + // Save the number of battles for the bots into battlesnum !!!!!!!!!!!!! + String bot1 = results.get(i * 3 + 1); + + bot1 = bot1.substring(0, bot1.indexOf(",")); + String bot2 = results.get(i * 3 + 2); + + bot2 = bot2.substring(0, bot2.indexOf(",")); + line = line.replaceAll("<", ""); + line = line.replaceAll(">", ""); + String[] b = line.split(" "); + + if (b.length == 2) { + battlesnum.println(game + "," + bot1 + "," + b[0]); + battlesnum.println(game + "," + bot2 + "," + b[1]); + } + } else if (line.indexOf("[") != -1 && line.indexOf("]") != -1) { + line = line.substring(1); + line = line.substring(0, line.length() - 1); + String[] items = line.split(","); + String bot1 = items[0].substring(0, items[0].lastIndexOf("_")) + " " + + items[0].substring(items[0].lastIndexOf("_") + 1); + String bot2 = items[1].substring(0, items[1].lastIndexOf("_")) + " " + + items[1].substring(items[1].lastIndexOf("_") + 1); + String battle = bot1 + "," + bot2 + "," + "SERVER"; + + if (prioritybattles != null) { + prioritybattles.println(battle); + } + } else { + System.out.println(line); + } + } + if (!ok) { + saveError(outtxt, results.get(i * 3), results.get(i * 3 + 1), results.get(i * 3 + 2), saveonerror); + if (saveonerror) { + errorsfound = true; + } + } + } catch (IOException e) { + System.out.println(e); + if (saveonerror) { + errorsfound = true; + } + saveError(outtxt, results.get(i * 3), results.get(i * 3 + 1), results.get(i * 3 + 2), saveonerror); + } finally { + if (wr != null) { + wr.close(); + } + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException ignored) {} + } + } + return errorsfound; + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/UpdateRatingFiles.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/UpdateRatingFiles.java new file mode 100644 index 0000000..ea9c212 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/netengine/UpdateRatingFiles.java @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.roborumble.netengine; + + +import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; +import static net.sf.robocode.roborumble.util.PropertiesUtil.storeProperties; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.Properties; +import java.util.Vector; + + +/** + * Class used for updating the local rating files. + * Controlled by properties files. + * + * @author Albert Prez (original) + * @author Flemming N. Larsen (contributor) + */ +public class UpdateRatingFiles { + + private String game; + private final String minibots; + private final String microbots; + private final String nanobots; + private final String battlesnumfile; + private final String generalratings; + private final String miniratings; + private final String microratings; + private final String nanoratings; + + public UpdateRatingFiles(String propertiesfile) { + // Read parameters + Properties parameters = getProperties(propertiesfile); + + game = propertiesfile; + while (game.indexOf("/") != -1) { + game = game.substring(game.indexOf("/") + 1); + } + game = game.substring(0, game.indexOf(".")); + minibots = parameters.getProperty("MINIBOTS", ""); + microbots = parameters.getProperty("MICROBOTS", ""); + nanobots = parameters.getProperty("NANOBOTS", ""); + + battlesnumfile = parameters.getProperty("BATTLESNUMFILE", ""); + + generalratings = parameters.getProperty("RATINGS.GENERAL", ""); + miniratings = parameters.getProperty("RATINGS.MINIBOTS", ""); + microratings = parameters.getProperty("RATINGS.MICROBOTS", ""); + nanoratings = parameters.getProperty("RATINGS.NANOBOTS", ""); + } + + public boolean updateRatings() { + + // read all the records to be updated + Vector battles = new Vector(); + BufferedReader br = null; + + try { + FileReader fr = new FileReader(battlesnumfile); + + br = new BufferedReader(fr); + String record; + + while ((record = br.readLine()) != null) { + battles.add(record); + } + } catch (IOException e) { + System.out.println("Can't open # battles file ... Aborting # battles update"); + return false; + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException ignored) {} + } + } + + // read the ratings files + Properties all = getProperties(generalratings); + Properties mini = getProperties(miniratings); + Properties micro = getProperties(microratings); + Properties nano = getProperties(nanoratings); + + // update #battles + for (String battle : battles) { + String[] battleSpec = battle.split(","); + + battleSpec[1] = battleSpec[1].replaceAll(" ", "_"); + double num = Double.parseDouble(battleSpec[2]); + + if (battleSpec[0].equals(game)) { + updateRecord(battleSpec[1], num, all); + } else if (battleSpec[0].equals(minibots) && mini != null) { + updateRecord(battleSpec[1], num, mini); + } else if (battleSpec[0].equals(microbots) && micro != null) { + updateRecord(battleSpec[1], num, micro); + } else if (battleSpec[0].equals(nanobots) && nano != null) { + updateRecord(battleSpec[1], num, nano); + } + } + + // save ratings files + return storeProperties(all, generalratings, "General ratings updated with new battles number") + && storeProperties(all, miniratings, "Mini ratings updated with new battles number") + && storeProperties(all, microratings, "Micro ratings updated with new battles number") + && storeProperties(all, nanoratings, "Nano ratings updated with new battles number"); + } + + private void updateRecord(String bot, double battles, Properties ratings) { + String values = ratings.getProperty(bot); + + if (values == null) { + return; + } + + String[] value = values.split(","); + + values = value[0] + "," + Double.toString(battles) + "," + value[2]; + ratings.setProperty(bot, values); + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/util/ExcludesUtil.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/util/ExcludesUtil.java new file mode 100644 index 0000000..fd8bb56 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/util/ExcludesUtil.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.roborumble.util; + + +import java.util.Properties; + + +/** + * Utility class for working with the EXCLUDE property for excluding robots from download and battles. + * + * @author Flemming N. Larsen (original) + */ +public class ExcludesUtil { + + private static String[] excludes; + + /** + * Read and prepared exclude filters for robots that should not be downloaded or participate in battles. + * + * @param properties the properties to store. + * @return a string array containing the excluded robots or null if no excludes are defined. + */ + public static void setExcludes(Properties properties) { + if (excludes != null) { + return; + } + + // Read and prepare exclude filters + String exclude = properties.getProperty("EXCLUDE"); + + if (exclude != null) { + // Convert into regular expression + + // Dots must be dots, not "any character" in the regular expression + exclude = exclude.replaceAll("\\.", "\\\\."); + + // The wildcard character ? corresponds to the regular expression .? + exclude = exclude.replaceAll("\\?", ".?"); + + // The wildcard character * corresponds to the regular expression .* + exclude = exclude.replaceAll("\\*", ".*"); + + // Split the exclude line into independent exclude filters that are trimmed for white-spaces + excludes = exclude.split("[,;]+"); // white spaces are allowed in the filter due to robot version numbers + } + } + + /** + * Checks if a participant is excluded. + * + * @param botNameVersion the name and version of the participant. + * @return true if the participant is excluded; false otherwise. + */ + public static boolean isExcluded(String botNameVersion) { + if (excludes == null) { + return false; + } + + // Check the name against all exclude filters + for (int i = excludes.length - 1; i >= 0; i--) { + try { + if (botNameVersion.matches(excludes[i])) { + return true; + } + } catch (java.util.regex.PatternSyntaxException e) { + // Clear the current exclude if the syntax is illegal (for next time this method is called) + excludes[i] = ""; + } + } + + // Not excluded + return false; + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/util/PropertiesUtil.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/util/PropertiesUtil.java new file mode 100644 index 0000000..2527f1d --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/net/sf/robocode/roborumble/util/PropertiesUtil.java @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.roborumble.util; + + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + + +/** + * @author Flemming N. Larsen (original) + */ +public final class PropertiesUtil { + + /** + * Returns a new Properties instance that is initialized to the specified properties file. + * + * @param filename the filename of the properties file to load + * @return a new java.util.Properties instance + */ + public static Properties getProperties(String filename) { + Properties props = new Properties(); + + if (filename != null && filename.trim().length() > 0) { + FileInputStream fis = null; + + try { + fis = new FileInputStream(filename); + props.load(fis); + } catch (IOException e) { + System.err.println("Could not load properties file: " + filename); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + return props; + } + + /** + * Returns a new Properties instance that is initialized to the specified properties input stream. + * + * @param is the input stream of the properties to load + * @return a new java.util.Properties instance + */ + public static Properties getProperties(InputStream is) { + Properties props = new Properties(); + + try { + props.load(is); + } catch (Exception e) { + System.err.println("Could not load properties input stream: " + is); + } + return props; + } + + /** + * Stores a Properties instance to the specified properties file. + * + * @param properties the properties to store + * @param filename the filename of the file to store the properties into + * @param comments comments to include in the properties file + * @return true if the properties were stored; false otherwise + */ + public static boolean storeProperties(Properties properties, String filename, String comments) { + if (properties == null || filename == null || filename.trim().length() == 0) { + return false; + } + + FileOutputStream fos = null; + + try { + fos = new FileOutputStream(filename); + properties.store(fos, comments); + } catch (IOException e) { + System.err.println("Could not store properties to file: " + filename); + return false; + } finally { + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return true; + } +} diff --git a/代码/workspace_robo4/robocode.roborumble/src/main/java/roborumble/RoboRumbleAtHome.java b/代码/workspace_robo4/robocode.roborumble/src/main/java/roborumble/RoboRumbleAtHome.java new file mode 100644 index 0000000..ab15763 --- /dev/null +++ b/代码/workspace_robo4/robocode.roborumble/src/main/java/roborumble/RoboRumbleAtHome.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package roborumble; + + +import net.sf.robocode.roborumble.battlesengine.BattlesRunner; +import net.sf.robocode.roborumble.battlesengine.PrepareBattles; +import net.sf.robocode.roborumble.netengine.BotsDownload; +import net.sf.robocode.roborumble.netengine.ResultsUpload; +import net.sf.robocode.roborumble.netengine.UpdateRatingFiles; +import static net.sf.robocode.roborumble.util.PropertiesUtil.getProperties; + +import java.util.Properties; + + +/** + * Implements the client side of RoboRumble@Home. + * Controlled by properties files. + * + * @author Albert Prez (original) + * @author Flemming N. Larsen (contributor) + * @author Jerome Lavigne (contributor) + */ +public class RoboRumbleAtHome { + + public static void main(String args[]) { + + // Get the associated parameters file + String parameters = "./roborumble/roborumble.txt"; + + try { + parameters = args[0]; + } catch (Exception e) { + System.out.println("No argument found specifying properties file. \"roborumble.txt\" assumed."); + } + + // Read parameters for running the app + Properties param = getProperties(parameters); + + String downloads = param.getProperty("DOWNLOAD", "NOT"); + String executes = param.getProperty("EXECUTE", "NOT"); + String uploads = param.getProperty("UPLOAD", "NOT"); + String iterates = param.getProperty("ITERATE", "NOT"); + String runonly = param.getProperty("RUNONLY", "GENERAL"); + String melee = param.getProperty("MELEE", "NOT"); + + int iterations = 0; + long lastdownload = 0; + boolean ratingsdownloaded = false; + boolean participantsdownloaded; + String version = null; + + do { + final BattlesRunner engine = new BattlesRunner(parameters); + + if (version == null) { + version = engine.getVersion(); + } + + System.out.println("Iteration number " + iterations); + + // Download data from Internet if downloads is YES and it has not been download for two hours + if (downloads.equals("YES")) { + BotsDownload download = new BotsDownload(parameters); + + if (runonly.equals("SERVER")) { + // Download rating files and update ratings downloaded + System.out.println("Downloading rating files ..."); + ratingsdownloaded = download.downloadRatings(); + } + if ((System.currentTimeMillis() - lastdownload) > 2 * 3600 * 1000) { + System.out.println("Downloading participants list ..."); + participantsdownloaded = download.downloadParticipantsList(); + System.out.println("Downloading missing bots ..."); + download.downloadMissingBots(); + download.updateCodeSize(); + // Send the order to the server to remove old participants from the ratings file + if (ratingsdownloaded && participantsdownloaded) { + System.out.println("Removing old participants from server ..."); + // Send unwanted participants to the server + download.notifyServerForOldParticipants(); + } + + lastdownload = System.currentTimeMillis(); + } + } + + // Create battles file (and delete old ones), and execute battles + if (executes.equals("YES")) { + final boolean isMelee = melee.equals("YES"); + + boolean ready; + PrepareBattles battles = new PrepareBattles(parameters); + + if (isMelee) { + System.out.println("Preparing melee battles list ..."); + ready = battles.createMeleeBattlesList(); + } else { + final boolean isSmartBattles = ratingsdownloaded && runonly.equals("SERVER"); + + if (isSmartBattles) { + System.out.println("Preparing battles list using smart battles..."); + ready = battles.createSmartBattlesList(); + } else { + System.out.println("Preparing battles list..."); + ready = battles.createBattlesList(); + } + } + + // Disable the -DPRARALLEL and -DRANDOMSEED options + System.setProperty("PARALLEL", "false"); // TODO: Remove when robot thread CPU time can be measured + System.setProperty("RANDOMSEED", "none"); // In tournaments, robots should not be deterministic! + + // Execute battles + if (ready) { + if (isMelee) { + System.out.println("Executing melee battles ..."); + } else { + System.out.println("Executing battles ..."); + } + + engine.runBattlesImpl(isMelee); + } + } + + // Upload results + if (uploads.equals("YES") && version != null) { + System.out.println("Uploading results ..."); + ResultsUpload upload = new ResultsUpload(parameters, version); + + // Uploads the results to the server + upload.uploadResults(); + + // Updates the number of battles from the info received from the server + System.out.println("Updating number of battles fought ..."); + UpdateRatingFiles updater = new UpdateRatingFiles(parameters); + + ratingsdownloaded = updater.updateRatings(); + } + + iterations++; + } while (iterates.equals("YES")); + + // With Java 5 this causes a IllegalThreadStateException, but not in Java 6 + // System.exit(0); + } +} diff --git a/代码/workspace_robo4/robocode.samples/.classpath b/代码/workspace_robo4/robocode.samples/.classpath new file mode 100644 index 0000000..2dfe70b --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/.classpath @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.samples/.project b/代码/workspace_robo4/robocode.samples/.project new file mode 100644 index 0000000..d30f541 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/.project @@ -0,0 +1,16 @@ + + + robocode.samples + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.samples/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.samples/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.samples/pom.xml b/代码/workspace_robo4/robocode.samples/pom.xml new file mode 100644 index 0000000..6ee25a0 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + robocode.samples + Robocode Samples + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + + src/main/java + false + + **/*.java + + + + src/main/resources + false + + **/*.properties + **/*.team + **/*.html + + + + + diff --git a/代码/workspace_robo4/robocode.samples/robocode.samples.iml b/代码/workspace_robo4/robocode.samples/robocode.samples.iml new file mode 100644 index 0000000..bfdd4ee --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/robocode.samples.iml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/Corners.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Corners.java new file mode 100644 index 0000000..935467e --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Corners.java @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.DeathEvent; +import robocode.Robot; +import robocode.ScannedRobotEvent; +import static robocode.util.Utils.normalRelativeAngleDegrees; + +import java.awt.*; + + +/** + * Corners - a sample robot by Mathew Nelson. + *

+ * This robot moves to a corner, then swings the gun back and forth. + * If it dies, it tries a new corner in the next round. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class Corners extends Robot { + int others; // Number of other robots in the game + static int corner = 0; // Which corner we are currently using + // static so that it keeps it between rounds. + boolean stopWhenSeeRobot = false; // See goCorner() + + /** + * run: Corners' main run function. + */ + public void run() { + // Set colors + setBodyColor(Color.red); + setGunColor(Color.black); + setRadarColor(Color.yellow); + setBulletColor(Color.green); + setScanColor(Color.green); + + // Save # of other bots + others = getOthers(); + + // Move to a corner + goCorner(); + + // Initialize gun turn speed to 3 + int gunIncrement = 3; + + // Spin gun back and forth + while (true) { + for (int i = 0; i < 30; i++) { + turnGunLeft(gunIncrement); + } + gunIncrement *= -1; + } + } + + /** + * goCorner: A very inefficient way to get to a corner. Can you do better? + */ + public void goCorner() { + // We don't want to stop when we're just turning... + stopWhenSeeRobot = false; + // turn to face the wall to the "right" of our desired corner. + turnRight(normalRelativeAngleDegrees(corner - getHeading())); + // Ok, now we don't want to crash into any robot in our way... + stopWhenSeeRobot = true; + // Move to that wall + ahead(5000); + // Turn to face the corner + turnLeft(90); + // Move to the corner + ahead(5000); + // Turn gun to starting point + turnGunLeft(90); + } + + /** + * onScannedRobot: Stop and fire! + */ + public void onScannedRobot(ScannedRobotEvent e) { + // Should we stop, or just fire? + if (stopWhenSeeRobot) { + // Stop everything! You can safely call stop multiple times. + stop(); + // Call our custom firing method + smartFire(e.getDistance()); + // Look for another robot. + // NOTE: If you call scan() inside onScannedRobot, and it sees a robot, + // the game will interrupt the event handler and start it over + scan(); + // We won't get here if we saw another robot. + // Okay, we didn't see another robot... start moving or turning again. + resume(); + } else { + smartFire(e.getDistance()); + } + } + + /** + * smartFire: Custom fire method that determines firepower based on distance. + * + * @param robotDistance the distance to the robot to fire at + */ + public void smartFire(double robotDistance) { + if (robotDistance > 200 || getEnergy() < 15) { + fire(1); + } else if (robotDistance > 50) { + fire(2); + } else { + fire(3); + } + } + + /** + * onDeath: We died. Decide whether to try a different corner next game. + */ + public void onDeath(DeathEvent e) { + // Well, others should never be 0, but better safe than sorry. + if (others == 0) { + return; + } + + // If 75% of the robots are still alive when we die, we'll switch corners. + if ((others - getOthers()) / (double) others < .75) { + corner += 90; + if (corner == 270) { + corner = -90; + } + out.println("I died and did poorly... switching corner to " + corner); + } else { + out.println("I died but did well. I will still use corner " + corner); + } + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/Crazy.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Crazy.java new file mode 100644 index 0000000..4508d33 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Crazy.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.*; + +import java.awt.*; + + +/** + * Crazy - a sample robot by Mathew Nelson. + *

+ * This robot moves around in a crazy pattern. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class Crazy extends AdvancedRobot { + boolean movingForward; + + /** + * run: Crazy's main run function + */ + public void run() { + // Set colors + setBodyColor(new Color(0, 200, 0)); + setGunColor(new Color(0, 150, 50)); + setRadarColor(new Color(0, 100, 100)); + setBulletColor(new Color(255, 255, 100)); + setScanColor(new Color(255, 200, 200)); + + // Loop forever + while (true) { + // Tell the game we will want to move ahead 40000 -- some large number + setAhead(40000); + movingForward = true; + // Tell the game we will want to turn right 90 + setTurnRight(90); + // At this point, we have indicated to the game that *when we do something*, + // we will want to move ahead and turn right. That's what "set" means. + // It is important to realize we have not done anything yet! + // In order to actually move, we'll want to call a method that + // takes real time, such as waitFor. + // waitFor actually starts the action -- we start moving and turning. + // It will not return until we have finished turning. + waitFor(new TurnCompleteCondition(this)); + // Note: We are still moving ahead now, but the turn is complete. + // Now we'll turn the other way... + setTurnLeft(180); + // ... and wait for the turn to finish ... + waitFor(new TurnCompleteCondition(this)); + // ... then the other way ... + setTurnRight(180); + // .. and wait for that turn to finish. + waitFor(new TurnCompleteCondition(this)); + // then back to the top to do it all again + } + } + + /** + * onHitWall: Handle collision with wall. + */ + public void onHitWall(HitWallEvent e) { + // Bounce off! + reverseDirection(); + } + + /** + * reverseDirection: Switch from ahead to back & vice versa + */ + public void reverseDirection() { + if (movingForward) { + setBack(40000); + movingForward = false; + } else { + setAhead(40000); + movingForward = true; + } + } + + /** + * onScannedRobot: Fire! + */ + public void onScannedRobot(ScannedRobotEvent e) { + fire(1); + } + + /** + * onHitRobot: Back up! + */ + public void onHitRobot(HitRobotEvent e) { + // If we're moving the other robot, reverse! + if (e.isMyFault()) { + reverseDirection(); + } + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/Fire.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Fire.java new file mode 100644 index 0000000..f15b29f --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Fire.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.HitByBulletEvent; +import robocode.HitRobotEvent; +import robocode.Robot; +import robocode.ScannedRobotEvent; +import static robocode.util.Utils.normalRelativeAngleDegrees; + +import java.awt.*; + + +/** + * Fire - a sample robot by Mathew Nelson, and maintained. + *

+ * Sits still. Spins gun around. Moves when hit. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class Fire extends Robot { + int dist = 50; // distance to move when we're hit + + /** + * run: Fire's main run function + */ + public void run() { + // Set colors + setBodyColor(Color.orange); + setGunColor(Color.orange); + setRadarColor(Color.red); + setScanColor(Color.red); + setBulletColor(Color.red); + + // Spin the gun around slowly... forever + while (true) { + turnGunRight(5); + } + } + + /** + * onScannedRobot: Fire! + */ + public void onScannedRobot(ScannedRobotEvent e) { + // If the other robot is close by, and we have plenty of life, + // fire hard! + if (e.getDistance() < 50 && getEnergy() > 50) { + fire(3); + } // otherwise, fire 1. + else { + fire(1); + } + // Call scan again, before we turn the gun + scan(); + } + + /** + * onHitByBullet: Turn perpendicular to the bullet, and move a bit. + */ + public void onHitByBullet(HitByBulletEvent e) { + turnRight(normalRelativeAngleDegrees(90 - (getHeading() - e.getHeading()))); + + ahead(dist); + dist *= -1; + scan(); + } + + /** + * onHitRobot: Aim at it. Fire Hard! + */ + public void onHitRobot(HitRobotEvent e) { + double turnGunAmt = normalRelativeAngleDegrees(e.getBearing() + getHeading() - getGunHeading()); + + turnGunRight(turnGunAmt); + fire(3); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/Interactive.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Interactive.java new file mode 100644 index 0000000..51dcbc5 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Interactive.java @@ -0,0 +1,223 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.AdvancedRobot; +import static robocode.util.Utils.normalAbsoluteAngle; +import static robocode.util.Utils.normalRelativeAngle; + +import java.awt.*; +import java.awt.event.KeyEvent; +import static java.awt.event.KeyEvent.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; + + +/** + * Interactive - a sample robot by Flemming N. Larsen. + *

+ * This is a robot that is controlled using the arrow keys and mouse only. + *

+ * Keys: + * - W or arrow up: Move forward + * - S or arrow down: Move backward + * - A or arrow right: Turn right + * - D or arrow left: Turn left + * Mouse: + * - Moving: Moves the aim, which the gun will follow + * - Wheel up: Move forward + * - Wheel down: Move backward + * - Button 1: Fire a bullet with power = 1 + * - Button 2: Fire a bullet with power = 2 + * - Button 3: Fire a bullet with power = 3 + *

+ * The bullet color depends on the fire power: + * - Power = 1: Yellow + * - Power = 2: Orange + * - Power = 3: Red + *

+ * Note that the robot will continue firing as long as the mouse button is + * pressed down. + *

+ * By enabling the "Paint" button on the robot console window for this robot, + * a cross hair will be painted for the robots current aim (controlled by the + * mouse). + * + * @author Flemming N. Larsen (original) + * + * @version 1.2 + * + * @since 1.3.4 + */ +public class Interactive extends AdvancedRobot { + + // Move direction: 1 = move forward, 0 = stand still, -1 = move backward + int moveDirection; + + // Turn direction: 1 = turn right, 0 = no turning, -1 = turn left + int turnDirection; + + // Amount of pixels/units to move + double moveAmount; + + // The coordinate of the aim (x,y) + int aimX, aimY; + + // Fire power, where 0 = don't fire + int firePower; + + // Called when the robot must run + public void run() { + + // Sets the colors of the robot + // body = black, gun = white, radar = red + setColors(Color.BLACK, Color.WHITE, Color.RED); + + // Loop forever + for (;;) { + // Sets the robot to move forward, backward or stop moving depending + // on the move direction and amount of pixels to move + setAhead(moveAmount * moveDirection); + + // Decrement the amount of pixels to move until we reach 0 pixels + // This way the robot will automatically stop if the mouse wheel + // has stopped it's rotation + moveAmount = Math.max(0, moveAmount - 1); + + // Sets the robot to turn right or turn left (at maximum speed) or + // stop turning depending on the turn direction + setTurnRight(45 * turnDirection); // degrees + + // Turns the gun toward the current aim coordinate (x,y) controlled by + // the current mouse coordinate + double angle = normalAbsoluteAngle(Math.atan2(aimX - getX(), aimY - getY())); + + setTurnGunRightRadians(normalRelativeAngle(angle - getGunHeadingRadians())); + + // Fire the gun with the specified fire power, unless the fire power = 0 + if (firePower > 0) { + setFire(firePower); + } + + // Execute all pending set-statements + execute(); + + // Next turn is processed in this loop.. + } + } + + // Called when a key has been pressed + public void onKeyPressed(KeyEvent e) { + switch (e.getKeyCode()) { + case VK_UP: + case VK_W: + // Arrow up key: move direction = forward (infinitely) + moveDirection = 1; + moveAmount = Double.POSITIVE_INFINITY; + break; + + case VK_DOWN: + case VK_S: + // Arrow down key: move direction = backward (infinitely) + moveDirection = -1; + moveAmount = Double.POSITIVE_INFINITY; + break; + + case VK_RIGHT: + case VK_D: + // Arrow right key: turn direction = right + turnDirection = 1; + break; + + case VK_LEFT: + case VK_A: + // Arrow left key: turn direction = left + turnDirection = -1; + break; + } + } + + // Called when a key has been released (after being pressed) + public void onKeyReleased(KeyEvent e) { + switch (e.getKeyCode()) { + case VK_UP: + case VK_W: + case VK_DOWN: + case VK_S: + // Arrow up and down keys: move direction = stand still + moveDirection = 0; + moveAmount = 0; + break; + + case VK_RIGHT: + case VK_D: + case VK_LEFT: + case VK_A: + // Arrow right and left keys: turn direction = stop turning + turnDirection = 0; + break; + } + } + + // Called when the mouse wheel is rotated + public void onMouseWheelMoved(MouseWheelEvent e) { + // If the wheel rotation is negative it means that it is moved forward. + // Set move direction = forward, if wheel is moved forward. + // Otherwise, set move direction = backward + moveDirection = (e.getWheelRotation() < 0) ? 1 : -1; + + // Set the amount to move = absolute wheel rotation amount * 5 (speed) + // Here 5 means 5 pixels per wheel rotation step. The higher value, the + // more speed + moveAmount += Math.abs(e.getWheelRotation()) * 5; + } + + // Called when the mouse has been moved + public void onMouseMoved(MouseEvent e) { + // Set the aim coordinate = the mouse pointer coordinate + aimX = e.getX(); + aimY = e.getY(); + } + + // Called when a mouse button has been pressed + public void onMousePressed(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3) { + // Button 3: fire power = 3 energy points, bullet color = red + firePower = 3; + setBulletColor(Color.RED); + } else if (e.getButton() == MouseEvent.BUTTON2) { + // Button 2: fire power = 2 energy points, bullet color = orange + firePower = 2; + setBulletColor(Color.ORANGE); + } else { + // Button 1 or unknown button: + // fire power = 1 energy points, bullet color = yellow + firePower = 1; + setBulletColor(Color.YELLOW); + } + } + + // Called when a mouse button has been released (after being pressed) + public void onMouseReleased(MouseEvent e) { + // Fire power = 0, which means "don't fire" + firePower = 0; + } + + // Called in order to paint graphics for this robot. + // "Paint" button on the robot console window for this robot must be + // enabled in order to see the paintings. + public void onPaint(Graphics2D g) { + // Draw a red cross hair with the center at the current aim + // coordinate (x,y) + g.setColor(Color.RED); + g.drawOval(aimX - 15, aimY - 15, 30, 30); + g.drawLine(aimX, aimY - 4, aimX, aimY + 4); + g.drawLine(aimX - 4, aimY, aimX + 4, aimY); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/Interactive_v2.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Interactive_v2.java new file mode 100644 index 0000000..dcddb3b --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Interactive_v2.java @@ -0,0 +1,263 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.AdvancedRobot; +import robocode.util.Utils; +import static robocode.util.Utils.normalAbsoluteAngle; +import static robocode.util.Utils.normalRelativeAngle; + +import java.awt.*; +import java.awt.event.KeyEvent; +import static java.awt.event.KeyEvent.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import java.util.HashSet; +import java.util.Set; + + +/** + * Interactive_v2 - a modified version of the sample robot Interactive by Flemming N. Larsen + * to use absolute movements (up, right, down, left) by Tuan Anh Nguyen. + *

+ * This is a robot that is controlled using the arrow keys (or WASD) and mouse only. + *

+ * Keys: + * - W or arrow up: Move up + * - S or arrow down: Move down + * - A or arrow right: Move right + * - D or arrow left: Move left + * Mouse: + * - Moving: Moves the aim, which the gun will follow + * - Button 1: Fire a bullet with power = 1 + * - Button 2: Fire a bullet with power = 2 + * - Button 3: Fire a bullet with power = 3 + *

+ * The bullet color depends on the fire power: + * - Power = 1: Yellow + * - Power = 2: Orange + * - Power = 3: Red + *

+ * Note that the robot will continue firing as long as the mouse button is + * pressed down. + *

+ * By enabling the "Paint" button on the robot console window for this robot, + * a cross hair will be painted for the robots current aim (controlled by the + * mouse). + * + * @author Flemming N. Larsen (original) + * @author Tuan Anh Nguyen (contributor) + * + * @version 1.0 + * + * @since 1.7.2.2 + */ +public class Interactive_v2 extends AdvancedRobot { + + // The coordinate of the aim (x,y) + int aimX, aimY; + + // Fire power, where 0 = don't fire + int firePower; + + // Absolute directions on the screen + private enum Direction { + UP, + DOWN, + LEFT, + RIGHT + } + + // Current move directions + private final Set directions = new HashSet(); + + // Called when the robot must run + public void run() { + + // Sets the colors of the robot + // body = black, gun = white, radar = red + setColors(Color.BLACK, Color.WHITE, Color.RED); + + // Loop forever + for (;;) { + // Move the robot compared to the distance to move + setAhead(distanceToMove()); + + // Turn the body to it points in the correct direction + setTurnRight(angleToTurnInDegrees()); + + // Turns the gun toward the current aim coordinate (x,y) controlled by + // the current mouse coordinate + double angle = normalAbsoluteAngle(Math.atan2(aimX - getX(), aimY - getY())); + + setTurnGunRightRadians(normalRelativeAngle(angle - getGunHeadingRadians())); + + // Fire the gun with the specified fire power, unless the fire power = 0 + if (firePower > 0) { + setFire(firePower); + } + + // Execute all pending set-statements + execute(); + + // Next turn is processed in this loop.. + } + } + + // Called when a key has been pressed + public void onKeyPressed(KeyEvent e) { + switch (e.getKeyCode()) { + case VK_UP: + case VK_W: + directions.add(Direction.UP); + break; + + case VK_DOWN: + case VK_S: + directions.add(Direction.DOWN); + break; + + case VK_RIGHT: + case VK_D: + directions.add(Direction.RIGHT); + break; + + case VK_LEFT: + case VK_A: + directions.add(Direction.LEFT); + break; + } + } + + // Called when a key has been released (after being pressed) + public void onKeyReleased(KeyEvent e) { + switch (e.getKeyCode()) { + case VK_UP: + case VK_W: + directions.remove(Direction.UP); + break; + + case VK_DOWN: + case VK_S: + directions.remove(Direction.DOWN); + break; + + case VK_RIGHT: + case VK_D: + directions.remove(Direction.RIGHT); + break; + + case VK_LEFT: + case VK_A: + directions.remove(Direction.LEFT); + break; + } + } + + // Called when the mouse wheel is rotated + public void onMouseWheelMoved(MouseWheelEvent e) {// Do nothing + } + + // Called when the mouse has been moved + public void onMouseMoved(MouseEvent e) { + // Set the aim coordinate = the mouse pointer coordinate + aimX = e.getX(); + aimY = e.getY(); + } + + // Called when a mouse button has been pressed + public void onMousePressed(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON3) { + // Button 3: fire power = 3 energy points, bullet color = red + firePower = 3; + setBulletColor(Color.RED); + } else if (e.getButton() == MouseEvent.BUTTON2) { + // Button 2: fire power = 2 energy points, bullet color = orange + firePower = 2; + setBulletColor(Color.ORANGE); + } else { + // Button 1 or unknown button: + // fire power = 1 energy points, bullet color = yellow + firePower = 1; + setBulletColor(Color.YELLOW); + } + } + + // Called when a mouse button has been released (after being pressed) + public void onMouseReleased(MouseEvent e) { + // Fire power = 0, which means "don't fire" + firePower = 0; + } + + // Called in order to paint graphics for this robot. + // "Paint" button on the robot console window for this robot must be + // enabled in order to see the paintings. + public void onPaint(Graphics2D g) { + // Draw a red cross hair with the center at the current aim + // coordinate (x,y) + g.setColor(Color.RED); + g.drawOval(aimX - 15, aimY - 15, 30, 30); + g.drawLine(aimX, aimY - 4, aimX, aimY + 4); + g.drawLine(aimX - 4, aimY, aimX + 4, aimY); + } + + // Returns the angle to turn, which is the delta between the desired + // direction and the current heading of the robot + private double angleToTurnInDegrees() { + if (directions.isEmpty()) { + return 0; + } + return Utils.normalRelativeAngleDegrees(desiredDirection() - getHeading()); + } + + // Returns the distance to move + private double distanceToMove() { + // If no keys are pressed, we should not move at all + if (directions.isEmpty()) { + return 0; + } + // If the robot has more than 45 degrees to turn, move only 5 pixel + if (Math.abs(angleToTurnInDegrees()) > 45) { + return 5; + } + // Otherwise, move at full speed + return Double.POSITIVE_INFINITY; + } + + // Return the desired direction depending on the pending move directions. + // With one arrow key pressed, the move to N, E, S, W. + // With two keys pressed, the robot also move to NE, NW, SE, SW. + private double desiredDirection() { + if (directions.contains(Direction.UP)) { + if (directions.contains(Direction.RIGHT)) { + return 45; + } + if (directions.contains(Direction.LEFT)) { + return 315; + } + return 0; + } + if (directions.contains(Direction.DOWN)) { + if (directions.contains(Direction.RIGHT)) { + return 135; + } + if (directions.contains(Direction.LEFT)) { + return 225; + } + return 180; + } + if (directions.contains(Direction.RIGHT)) { + return 90; + } + if (directions.contains(Direction.LEFT)) { + return 270; + } + return 0; + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/MyFirstJuniorRobot.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/MyFirstJuniorRobot.java new file mode 100644 index 0000000..7931009 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/MyFirstJuniorRobot.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.JuniorRobot; + + +/** + * MyFirstJuniorRobot - a sample robot by Flemming N. Larsen + *

+ * Moves in a seesaw motion, and spins the gun around at each end + * when it cannot see any enemy robot. When the robot sees and enemy + * robot, it will immediately turn the gun and fire at it. + * + * @author Flemming N. Larsen (original) + */ +public class MyFirstJuniorRobot extends JuniorRobot { + + /** + * MyFirstJuniorRobot's run method - Seesaw as default + */ + public void run() { + // Set robot colors + setColors(green, black, blue); + + // Seesaw forever + while (true) { + ahead(100); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(100); // Move back 100 + turnGunRight(360); // Spin gun around + } + } + + /** + * When we see a robot, turn the gun towards it and fire + */ + public void onScannedRobot() { + // Turn gun to point at the scanned robot + turnGunTo(scannedAngle); + + // Fire! + fire(1); + } + + /** + * We were hit! Turn and move perpendicular to the bullet, + * so our seesaw might avoid a future shot. + */ + public void onHitByBullet() { + // Move ahead 100 and in the same time turn left papendicular to the bullet + turnAheadLeft(100, 90 - hitByBulletBearing); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/MyFirstRobot.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/MyFirstRobot.java new file mode 100644 index 0000000..d9013d0 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/MyFirstRobot.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.HitByBulletEvent; +import robocode.Robot; +import robocode.ScannedRobotEvent; + + +/** + * MyFirstRobot - a sample robot by Mathew Nelson. + *

+ * Moves in a seesaw motion, and spins the gun around at each end. + * + * @author Mathew A. Nelson (original) + */ +public class MyFirstRobot extends Robot { + + /** + * MyFirstRobot's run method - Seesaw + */ + public void run() { + + while (true) { + ahead(100); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(100); // Move back 100 + turnGunRight(360); // Spin gun around + } + } + + /** + * Fire when we see a robot + */ + public void onScannedRobot(ScannedRobotEvent e) { + fire(1); + } + + /** + * We were hit! Turn perpendicular to the bullet, + * so our seesaw might avoid a future shot. + */ + public void onHitByBullet(HitByBulletEvent e) { + turnLeft(90 - e.getBearing()); + } +} + diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/PaintingRobot.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/PaintingRobot.java new file mode 100644 index 0000000..638d04b --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/PaintingRobot.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.HitByBulletEvent; +import robocode.Robot; +import robocode.ScannedRobotEvent; + +import java.awt.*; + + +/** + * PaintingRobot - a sample robot that demonstrates the onPaint() and + * getGraphics() methods. + * Also demonstrate feature of debugging properties on RobotDialog + *

+ * Moves in a seesaw motion, and spins the gun around at each end. + * When painting is enabled for this robot, a red circle will be painted + * around this robot. + * + * @author Stefan Westen (original SGSample) + * @author Pavel Savara (contributor) + */ +public class PaintingRobot extends Robot { + + /** + * PaintingRobot's run method - Seesaw + */ + public void run() { + while (true) { + ahead(100); + turnGunRight(360); + back(100); + turnGunRight(360); + } + } + + /** + * Fire when we see a robot + */ + public void onScannedRobot(ScannedRobotEvent e) { + // demonstrate feature of debugging properties on RobotDialog + setDebugProperty("lastScannedRobot", e.getName() + " at " + e.getBearing() + " degrees at time " + getTime()); + + fire(1); + } + + /** + * We were hit! Turn perpendicular to the bullet, + * so our seesaw might avoid a future shot. + * In addition, draw orange circles where we were hit. + */ + public void onHitByBullet(HitByBulletEvent e) { + // demonstrate feature of debugging properties on RobotDialog + setDebugProperty("lastHitBy", e.getName() + " with power of bullet " + e.getPower() + " at time " + getTime()); + + // show how to remove debugging property + setDebugProperty("lastScannedRobot", null); + + // gebugging by painting to battle view + Graphics2D g = getGraphics(); + + g.setColor(Color.orange); + g.drawOval((int) (getX() - 55), (int) (getY() - 55), 110, 110); + g.drawOval((int) (getX() - 56), (int) (getY() - 56), 112, 112); + g.drawOval((int) (getX() - 59), (int) (getY() - 59), 118, 118); + g.drawOval((int) (getX() - 60), (int) (getY() - 60), 120, 120); + + turnLeft(90 - e.getBearing()); + } + + /** + * Paint a red circle around our PaintingRobot + */ + public void onPaint(Graphics2D g) { + g.setColor(Color.red); + g.drawOval((int) (getX() - 50), (int) (getY() - 50), 100, 100); + g.setColor(new Color(0, 0xFF, 0, 30)); + g.fillOval((int) (getX() - 60), (int) (getY() - 60), 120, 120); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/RamFire.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/RamFire.java new file mode 100644 index 0000000..d33c269 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/RamFire.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.HitRobotEvent; +import robocode.Robot; +import robocode.ScannedRobotEvent; + +import java.awt.*; + + +/** + * RamFire - a sample robot by Mathew Nelson. + *

+ * Drives at robots trying to ram them. + * Fires when it hits them. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RamFire extends Robot { + int turnDirection = 1; // Clockwise or counterclockwise + + /** + * run: Spin around looking for a target + */ + public void run() { + // Set colors + setBodyColor(Color.lightGray); + setGunColor(Color.gray); + setRadarColor(Color.darkGray); + + while (true) { + turnRight(5 * turnDirection); + } + } + + /** + * onScannedRobot: We have a target. Go get it. + */ + public void onScannedRobot(ScannedRobotEvent e) { + + if (e.getBearing() >= 0) { + turnDirection = 1; + } else { + turnDirection = -1; + } + + turnRight(e.getBearing()); + ahead(e.getDistance() + 5); + scan(); // Might want to move ahead again! + } + + /** + * onHitRobot: Turn to face robot, fire hard, and ram him again! + */ + public void onHitRobot(HitRobotEvent e) { + if (e.getBearing() >= 0) { + turnDirection = 1; + } else { + turnDirection = -1; + } + turnRight(e.getBearing()); + + // Determine a shot that won't kill the robot... + // We want to ram him instead for bonus points + if (e.getEnergy() > 16) { + fire(3); + } else if (e.getEnergy() > 10) { + fire(2); + } else if (e.getEnergy() > 4) { + fire(1); + } else if (e.getEnergy() > 2) { + fire(.5); + } else if (e.getEnergy() > .4) { + fire(.1); + } + ahead(40); // Ram him again! + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/SittingDuck.html b/代码/workspace_robo4/robocode.samples/src/main/java/sample/SittingDuck.html new file mode 100644 index 0000000..9f4d522 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/SittingDuck.html @@ -0,0 +1,24 @@ + + + + + + SittingDuck's Webpage + + + + + +

Hi! I'm a sitting duck.
+ + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/SittingDuck.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/SittingDuck.java new file mode 100644 index 0000000..78d7878 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/SittingDuck.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.AdvancedRobot; +import robocode.RobocodeFileOutputStream; + +import java.awt.*; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintStream; + + +/** + * SittingDuck - a sample robot by Mathew Nelson. + *

+ * Along with sitting still doing nothing, this robot demonstrates persistency. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Andrew Magargle (contributor) + */ +public class SittingDuck extends AdvancedRobot { + static boolean incrementedBattles = false; + + public void run() { + setBodyColor(Color.yellow); + setGunColor(Color.yellow); + + int roundCount, battleCount; + + try { + BufferedReader reader = null; + try { + // Read file "count.dat" which contains 2 lines, a round count, and a battle count + reader = new BufferedReader(new FileReader(getDataFile("count.dat"))); + + // Try to get the counts + roundCount = Integer.parseInt(reader.readLine()); + battleCount = Integer.parseInt(reader.readLine()); + + } finally { + if (reader != null) { + reader.close(); + } + } + } catch (IOException e) { + // Something went wrong reading the file, reset to 0. + roundCount = 0; + battleCount = 0; + } catch (NumberFormatException e) { + // Something went wrong converting to ints, reset to 0 + roundCount = 0; + battleCount = 0; + } + + // Increment the # of rounds + roundCount++; + + // If we haven't incremented # of battles already, + // Note: Because robots are only instantiated once per battle, member variables remain valid throughout it. + if (!incrementedBattles) { + // Increment # of battles + battleCount++; + incrementedBattles = true; + } + + PrintStream w = null; + try { + w = new PrintStream(new RobocodeFileOutputStream(getDataFile("count.dat"))); + + w.println(roundCount); + w.println(battleCount); + + // PrintStreams don't throw IOExceptions during prints, they simply set a flag.... so check it here. + if (w.checkError()) { + out.println("I could not write the count!"); + } + } catch (IOException e) { + out.println("IOException trying to write: "); + e.printStackTrace(out); + } finally { + if (w != null) { + w.close(); + } + } + out.println("I have been a sitting duck for " + roundCount + " rounds, in " + battleCount + " battles."); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/SpinBot.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/SpinBot.java new file mode 100644 index 0000000..4f4f3d0 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/SpinBot.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.AdvancedRobot; +import robocode.HitRobotEvent; +import robocode.ScannedRobotEvent; + +import java.awt.*; + + +/** + * SpinBot - a sample robot by Mathew Nelson. + *

+ * Moves in a circle, firing hard when an enemy is detected. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class SpinBot extends AdvancedRobot { + + /** + * SpinBot's run method - Circle + */ + public void run() { + // Set colors + setBodyColor(Color.blue); + setGunColor(Color.blue); + setRadarColor(Color.black); + setScanColor(Color.yellow); + + // Loop forever + while (true) { + // Tell the game that when we take move, + // we'll also want to turn right... a lot. + setTurnRight(10000); + // Limit our speed to 5 + setMaxVelocity(5); + // Start moving (and turning) + ahead(10000); + // Repeat. + } + } + + /** + * onScannedRobot: Fire hard! + */ + public void onScannedRobot(ScannedRobotEvent e) { + fire(3); + } + + /** + * onHitRobot: If it's our fault, we'll stop turning and moving, + * so we need to turn again to keep spinning. + */ + public void onHitRobot(HitRobotEvent e) { + if (e.getBearing() > -10 && e.getBearing() < 10) { + fire(3); + } + if (e.isMyFault()) { + turnRight(10); + } + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/Target.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Target.java new file mode 100644 index 0000000..0c34b2a --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Target.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.AdvancedRobot; +import robocode.Condition; +import robocode.CustomEvent; + +import java.awt.*; + + +/** + * Target - a sample robot by Mathew Nelson. + *

+ * Sits still. Moves every time energy drops by 20. + * This Robot demonstrates custom events. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class Target extends AdvancedRobot { + + int trigger; // Keeps track of when to move + + /** + * TrackFire's run method + */ + public void run() { + // Set colors + setBodyColor(Color.white); + setGunColor(Color.white); + setRadarColor(Color.white); + + // Initially, we'll move when life hits 80 + trigger = 80; + // Add a custom event named "trigger hit", + addCustomEvent(new Condition("triggerhit") { + public boolean test() { + return (getEnergy() <= trigger); + } + }); + } + + /** + * onCustomEvent handler + */ + public void onCustomEvent(CustomEvent e) { + // If our custom event "triggerhit" went off, + if (e.getCondition().getName().equals("triggerhit")) { + // Adjust the trigger value, or + // else the event will fire again and again and again... + trigger -= 20; + out.println("Ouch, down to " + (int) (getEnergy() + .5) + " energy."); + // move around a bit. + turnLeft(65); + ahead(100); + } + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/TrackFire.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/TrackFire.java new file mode 100644 index 0000000..70ca780 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/TrackFire.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.Robot; +import robocode.ScannedRobotEvent; +import robocode.WinEvent; +import static robocode.util.Utils.normalRelativeAngleDegrees; + +import java.awt.*; + + +/** + * TrackFire - a sample robot by Mathew Nelson. + *

+ * Sits still. Tracks and fires at the nearest robot it sees. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class TrackFire extends Robot { + + /** + * TrackFire's run method + */ + public void run() { + // Set colors + setBodyColor(Color.pink); + setGunColor(Color.pink); + setRadarColor(Color.pink); + setScanColor(Color.pink); + setBulletColor(Color.pink); + + // Loop forever + while (true) { + turnGunRight(10); // Scans automatically + } + } + + /** + * onScannedRobot: We have a target. Go get it. + */ + public void onScannedRobot(ScannedRobotEvent e) { + // Calculate exact location of the robot + double absoluteBearing = getHeading() + e.getBearing(); + double bearingFromGun = normalRelativeAngleDegrees(absoluteBearing - getGunHeading()); + + // If it's close enough, fire! + if (Math.abs(bearingFromGun) <= 3) { + turnGunRight(bearingFromGun); + // We check gun heat here, because calling fire() + // uses a turn, which could cause us to lose track + // of the other robot. + if (getGunHeat() == 0) { + fire(Math.min(3 - Math.abs(bearingFromGun), getEnergy() - .1)); + } + } // otherwise just set the gun to turn. + // Note: This will have no effect until we call scan() + else { + turnGunRight(bearingFromGun); + } + // Generates another scan event if we see a robot. + // We only need to call this if the gun (and therefore radar) + // are not turning. Otherwise, scan is called automatically. + if (bearingFromGun == 0) { + scan(); + } + } + + public void onWin(WinEvent e) { + // Victory dance + turnRight(36000); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/Tracker.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Tracker.java new file mode 100644 index 0000000..1cdc19c --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Tracker.java @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.HitRobotEvent; +import robocode.Robot; +import robocode.ScannedRobotEvent; +import robocode.WinEvent; +import static robocode.util.Utils.normalRelativeAngleDegrees; + +import java.awt.*; + + +/** + * Tracker - a sample robot by Mathew Nelson. + *

+ * Locks onto a robot, moves close, fires when close. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class Tracker extends Robot { + int count = 0; // Keeps track of how long we've + // been searching for our target + double gunTurnAmt; // How much to turn our gun when searching + String trackName; // Name of the robot we're currently tracking + + /** + * run: Tracker's main run function + */ + public void run() { + // Set colors + setBodyColor(new Color(128, 128, 50)); + setGunColor(new Color(50, 50, 20)); + setRadarColor(new Color(200, 200, 70)); + setScanColor(Color.white); + setBulletColor(Color.blue); + + // Prepare gun + trackName = null; // Initialize to not tracking anyone + setAdjustGunForRobotTurn(true); // Keep the gun still when we turn + gunTurnAmt = 10; // Initialize gunTurn to 10 + + // Loop forever + while (true) { + // turn the Gun (looks for enemy) + turnGunRight(gunTurnAmt); + // Keep track of how long we've been looking + count++; + // If we've haven't seen our target for 2 turns, look left + if (count > 2) { + gunTurnAmt = -10; + } + // If we still haven't seen our target for 5 turns, look right + if (count > 5) { + gunTurnAmt = 10; + } + // If we *still* haven't seen our target after 10 turns, find another target + if (count > 11) { + trackName = null; + } + } + } + + /** + * onScannedRobot: Here's the good stuff + */ + public void onScannedRobot(ScannedRobotEvent e) { + + // If we have a target, and this isn't it, return immediately + // so we can get more ScannedRobotEvents. + if (trackName != null && !e.getName().equals(trackName)) { + return; + } + + // If we don't have a target, well, now we do! + if (trackName == null) { + trackName = e.getName(); + out.println("Tracking " + trackName); + } + // This is our target. Reset count (see the run method) + count = 0; + // If our target is too far away, turn and move toward it. + if (e.getDistance() > 150) { + gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading())); + + turnGunRight(gunTurnAmt); // Try changing these to setTurnGunRight, + turnRight(e.getBearing()); // and see how much Tracker improves... + // (you'll have to make Tracker an AdvancedRobot) + ahead(e.getDistance() - 140); + return; + } + + // Our target is close. + gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading())); + turnGunRight(gunTurnAmt); + fire(3); + + // Our target is too close! Back up. + if (e.getDistance() < 100) { + if (e.getBearing() > -90 && e.getBearing() <= 90) { + back(40); + } else { + ahead(40); + } + } + scan(); + } + + /** + * onHitRobot: Set him as our new target + */ + public void onHitRobot(HitRobotEvent e) { + // Only print if he's not already our target. + if (trackName != null && !trackName.equals(e.getName())) { + out.println("Tracking " + e.getName() + " due to collision"); + } + // Set the target + trackName = e.getName(); + // Back up a bit. + // Note: We won't get scan events while we're doing this! + // An AdvancedRobot might use setBack(); execute(); + gunTurnAmt = normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading())); + turnGunRight(gunTurnAmt); + fire(3); + back(50); + } + + /** + * onWin: Do a victory dance + */ + public void onWin(WinEvent e) { + for (int i = 0; i < 50; i++) { + turnRight(30); + turnLeft(30); + } + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/VelociRobot.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/VelociRobot.java new file mode 100644 index 0000000..8eadf8b --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/VelociRobot.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.HitByBulletEvent; +import robocode.HitWallEvent; +import robocode.RateControlRobot; +import robocode.ScannedRobotEvent; + + +/** + * This is a sample of a robot using the RateControlRobot class + * + * @author Joshua Galecki (original) + */ +public class VelociRobot extends RateControlRobot { + + int turnCounter; + public void run() { + + turnCounter = 0; + setGunRotationRate(15); + + while (true) { + if (turnCounter % 64 == 0) { + // Straighten out, if we were hit by a bullet and are turning + setTurnRate(0); + // Go forward with a velocity of 4 + setVelocityRate(4); + } + if (turnCounter % 64 == 32) { + // Go backwards, faster + setVelocityRate(-6); + } + turnCounter++; + execute(); + } + } + + public void onScannedRobot(ScannedRobotEvent e) { + fire(1); + } + + public void onHitByBullet(HitByBulletEvent e) { + // Turn to confuse the other robot + setTurnRate(5); + } + + public void onHitWall(HitWallEvent e) { + // Move away from the wall + setVelocityRate(-1 * getVelocityRate()); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sample/Walls.java b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Walls.java new file mode 100644 index 0000000..f122c7b --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sample/Walls.java @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sample; + + +import robocode.HitRobotEvent; +import robocode.Robot; +import robocode.ScannedRobotEvent; + +import java.awt.*; + + +/** + * Walls - a sample robot by Mathew Nelson, and maintained by Flemming N. Larsen + *

+ * Moves around the outer edge with the gun facing in. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class Walls extends Robot { + + boolean peek; // Don't turn if there's a robot there + double moveAmount; // How much to move + + /** + * run: Move around the walls + */ + public void run() { + // Set colors + setBodyColor(Color.black); + setGunColor(Color.black); + setRadarColor(Color.orange); + setBulletColor(Color.cyan); + setScanColor(Color.cyan); + + // Initialize moveAmount to the maximum possible for this battlefield. + moveAmount = Math.max(getBattleFieldWidth(), getBattleFieldHeight()); + // Initialize peek to false + peek = false; + + // turnLeft to face a wall. + // getHeading() % 90 means the remainder of + // getHeading() divided by 90. + turnLeft(getHeading() % 90); + ahead(moveAmount); + // Turn the gun to turn right 90 degrees. + peek = true; + turnGunRight(90); + turnRight(90); + + while (true) { + // Look before we turn when ahead() completes. + peek = true; + // Move up the wall + ahead(moveAmount); + // Don't look now + peek = false; + // Turn to the next wall + turnRight(90); + } + } + + /** + * onHitRobot: Move away a bit. + */ + public void onHitRobot(HitRobotEvent e) { + // If he's in front of us, set back up a bit. + if (e.getBearing() > -90 && e.getBearing() < 90) { + back(100); + } // else he's in back of us, so set ahead a bit. + else { + ahead(100); + } + } + + /** + * onScannedRobot: Fire! + */ + public void onScannedRobot(ScannedRobotEvent e) { + fire(2); + // Note that scan is called automatically when the robot is moving. + // By calling it manually here, we make sure we generate another scan event if there's a robot on the next + // wall, so that we do not start moving up it until it's gone. + if (peek) { + scan(); + } + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/Alien.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/Alien.java new file mode 100644 index 0000000..b963ca6 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/Alien.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleex; + + +import robocode.*; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.peer.IBasicRobotPeer; +import robocode.robotinterfaces.peer.IStandardRobotPeer; + +import java.io.PrintStream; + + +/** + * A sample robot. + * Is not inherited from classic base robots, uses new experimental access to RobotPeer. + * Use -DEXPERIMENTAL=true to start robocode for this robot. + * + * @author Pavel Savara (original) + */ +public class Alien implements IBasicEvents, IBasicRobot, Runnable { + + PrintStream out; + IStandardRobotPeer peer; + + public Runnable getRobotRunnable() { + return this; + } + + public IBasicEvents getBasicEventListener() { + return this; + } + + public void setPeer(IBasicRobotPeer iRobotPeer) { + peer = (IStandardRobotPeer) iRobotPeer; + } + + public void setOut(PrintStream printStream) { + out = printStream; + } + + public void run() { + while (true) { + peer.move(100); // Move ahead 100 + peer.turnGun(Math.PI * 2); // Spin gun around + peer.move(-100); // Move back 100 + peer.turnGun(Math.PI * 2); // Spin gun around + } + } + + public void onScannedRobot(ScannedRobotEvent e) { + peer.setFire(1); + } + + public void onHitByBullet(HitByBulletEvent e) { + peer.turnBody(Math.PI / 2 + e.getBearingRadians()); + } + + public void onStatus(StatusEvent e) {} + + public void onBulletHit(BulletHitEvent e) {} + + public void onBulletHitBullet(BulletHitBulletEvent e) {} + + public void onBulletMissed(BulletMissedEvent e) {} + + public void onDeath(DeathEvent e) {} + + public void onHitRobot(HitRobotEvent e) {} + + public void onHitWall(HitWallEvent e) {} + + public void onRobotDeath(RobotDeathEvent e) {} + + public void onWin(WinEvent e) {} +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/AlienComposition.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/AlienComposition.java new file mode 100644 index 0000000..6e0f113 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/AlienComposition.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleex; + + +import robocode.*; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IBasicRobot; +import robocode.robotinterfaces.peer.IBasicRobotPeer; +import robocode.robotinterfaces.peer.IStandardRobotPeer; + +import java.io.PrintStream; + + +/** + * A sample robot. + * Is not inherited from classic base robots, uses new experimental access to RobotPeer. + * Use -DEXPERIMENTAL=true to start robocode for this robot. + * This composition version is showing possible decomposition of robot, main runnable and event handler to different classes. + * + * @author Pavel Savara (original) + */ +public class AlienComposition implements IBasicRobot { + PrintStream out; + IStandardRobotPeer peer; + final AlienMain main; + final AlienEventHandler handler; + + public AlienComposition() { + main = new AlienMain(); + handler = new AlienEventHandler(); + } + + public void setPeer(IBasicRobotPeer iRobotPeer) { + peer = (IStandardRobotPeer) iRobotPeer; + } + + public void setOut(PrintStream printStream) { + out = printStream; + } + + public Runnable getRobotRunnable() { + return main; + } + + public IBasicEvents getBasicEventListener() { + return handler; + } + + class AlienMain implements Runnable { + public void run() { + while (true) { + peer.move(100); // Move ahead 100 + peer.turnGun(Math.PI * 2); // Spin gun around + peer.move(-100); // Move back 100 + peer.turnGun(Math.PI * 2); // Spin gun around + } + } + } + + + class AlienEventHandler implements IBasicEvents { + public void onScannedRobot(ScannedRobotEvent e) { + peer.setFire(1); + } + + public void onHitByBullet(HitByBulletEvent e) { + peer.turnBody(Math.PI / 2 + e.getBearingRadians()); + } + + public void onStatus(StatusEvent e) {} + + public void onBulletHit(BulletHitEvent e) {} + + public void onBulletHitBullet(BulletHitBulletEvent e) {} + + public void onBulletMissed(BulletMissedEvent e) {} + + public void onDeath(DeathEvent e) {} + + public void onHitRobot(HitRobotEvent e) {} + + public void onHitWall(HitWallEvent e) {} + + public void onRobotDeath(RobotDeathEvent e) {} + + public void onWin(WinEvent e) {} + } +} + diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/MasterAndSlave.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/MasterAndSlave.java new file mode 100644 index 0000000..b862ff5 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/MasterAndSlave.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleex; + + +import robocode.AdvancedRobot; +import robocode.HitByBulletEvent; +import robocode.ScannedRobotEvent; +import robocode.robotinterfaces.IAdvancedEvents; +import robocode.robotinterfaces.IAdvancedRobot; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IInteractiveEvents; +import robocode.robotinterfaces.peer.IBasicRobotPeer; + +import java.io.PrintStream; + + +/** + * @author Pavel Savara (original) + */ +public class MasterAndSlave extends MasterBase implements IAdvancedRobot { + + /** + * This is not showing any aditional qualities over normal MyFirst robot. + * But it could, because architecture is no more tied by inheritance from Robot base class. + */ + public void run() { + while (true) { + ahead(100); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(100); // Move back 100 + turnGunRight(360); // Spin gun around + } + } + + public void onScannedRobot(ScannedRobotEvent e) { + fire(1); + } + + public void onHitByBullet(HitByBulletEvent e) { + turnLeft(90 - e.getBearing()); + } + + public IInteractiveEvents getInteractiveEventListener() { + return null; + } +} + + +/** + * Infrastructure base class, for helpers and boring implementation details + */ +abstract class MasterBase { + + public MasterBase() { + helperRobot = new Slave(this); + } + + private final AdvancedRobot helperRobot; + + public IAdvancedEvents getAdvancedEventListener() { + return helperRobot; + } + + public IInteractiveEvents getSystemEventListener() { + return helperRobot; + } + + public Runnable getRobotRunnable() { + return helperRobot; + } + + public IBasicEvents getBasicEventListener() { + return helperRobot; + } + + public void setPeer(IBasicRobotPeer robotPeer) { + helperRobot.setPeer(robotPeer); + } + + public void setOut(PrintStream printStream) { + helperRobot.setOut(printStream); + } + + public void turnGunRight(double degrees) { + helperRobot.turnGunRight(degrees); + } + + public void turnLeft(double degrees) { + helperRobot.turnLeft(degrees); + } + + public void ahead(double distance) { + helperRobot.ahead(distance); + } + + public void back(double distance) { + helperRobot.back(distance); + } + + public void fire(double power) { + helperRobot.fire(power); + } + + public void onScannedRobot(ScannedRobotEvent e) {} + + public void onHitByBullet(HitByBulletEvent e) {} + + public void run() {} +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/ProxyOfGreyEminence.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/ProxyOfGreyEminence.java new file mode 100644 index 0000000..9c2864b --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/ProxyOfGreyEminence.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleex; + + +import robocode.AdvancedRobot; +import robocode.HitByBulletEvent; +import robocode.ScannedRobotEvent; + + +/** + * This is just dummy proxy, it's hiding the Eminence and + * giving it more freedom to inherit from Monk rather than from Robot. + * + * @author Pavel Savara (original) + */ +public class ProxyOfGreyEminence extends AdvancedRobot { + private final GreyEminence monk; + + public ProxyOfGreyEminence() { + monk = new GreyEminence(this); + } + + public void onHitByBullet(HitByBulletEvent event) { + monk.onHitByBullet(event); + } + + public void onScannedRobot(ScannedRobotEvent event) { + monk.onScannedRobot(event); + } + + public void run() { + monk.run(); + } +} + + +/** + * The power behind the throne. + */ +class GreyEminence extends RegullarMonk { + private final ProxyOfGreyEminence proxy; + + public GreyEminence(ProxyOfGreyEminence proxy) { + this.proxy = proxy; + } + + /** + * This is not showing any aditional qualities over normal MyFirst robot. + * But it could, because architecture is no more tied by inheritance from Robot base class. + */ + public void run() { + while (true) { + proxy.ahead(100); // Move ahead 100 + proxy.turnGunRight(360); // Spin gun around + proxy.back(100); // Move back 100 + proxy.turnGunRight(360); // Spin gun around + } + } + + public void onScannedRobot(ScannedRobotEvent e) { + proxy.fire(1); + } + + public void onHitByBullet(HitByBulletEvent e) { + proxy.turnLeft(90 - e.getBearing()); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/RegullarMonk.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/RegullarMonk.java new file mode 100644 index 0000000..253f53c --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/RegullarMonk.java @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleex; + + +/** + * Monk of a order. Implements anything too boring for Eminence. + * The infractructure base class. + * + * @author Pavel Savara (original) + */ +abstract class RegullarMonk {} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/Slave.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/Slave.java new file mode 100644 index 0000000..d5e47ab --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleex/Slave.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleex; + + +import robocode.AdvancedRobot; +import robocode.HitByBulletEvent; +import robocode.ScannedRobotEvent; + + +/** + * This is robot derived from AdvancedRobot. + * Only reason to use this inheritance and this class is that external robots are unable to call RobotPeer directly. + * + * @author Pavel Savara (original) + */ +class Slave extends AdvancedRobot { + final MasterBase parent; + + public Slave(MasterBase parent) { + this.parent = parent; + } + + public void run() { + parent.run(); + } + + public void onScannedRobot(ScannedRobotEvent e) { + parent.onScannedRobot(e); + } + + public void onHitByBullet(HitByBulletEvent e) { + parent.onHitByBullet(e); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/samplesentry/BorderGuard.java b/代码/workspace_robo4/robocode.samples/src/main/java/samplesentry/BorderGuard.java new file mode 100644 index 0000000..8fc6ac7 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/samplesentry/BorderGuard.java @@ -0,0 +1,716 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package samplesentry; + + +import robocode.*; +import robocode.util.Utils; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Point2D; +import java.util.*; + + +/** + * BorderGuard - is a sample robot that demonstrates how the BorderSentry interface can be used for + * creating a robot that guards the border area of the battle field, and which is efficient against + * robots trying to hide at corners and robots sneaking around near the borders. + *

+ * This robot is somewhat advanced due to:
+ * 1) it uses linear targeting for predicting how to hit robots that moves in straight lines.
+ * 2) it will only fire at a robot, if it figures out that its bullets will do damage to that + * particular robot, e.g. when the robots predicted future position will be within the sentry border + * attack range.
+ * 3) it has an efficient scanner that keeps the scan angle as little as possible to get as new + * scanned data for enemy robots as possible.
+ * 4) it picks a target robot to fire at, which is the nearest robot our robot will be able to + * damage (by predicting its future position using linear targeting).
+ * 5) it only moves along the borders of the battle field and constantly changes its direction, so + * it is not an easy target, and it will try to get as close to its target robot as possible.
+ *

+ * Lots of improvements can be made to this robot by copying it - making it even stronger. The + * intention with of this sample robot is to serve as a more advanced example of how a AdvancedRobot + * can be made, and how it can be structured as most sample robots are far simpler. + *

+ * + * Credits goes to the hard working Robocoders at the RoboWiki. :-) + *

+ * + * This robot makes use of the Oldest Scanned melee scanner from the RoboWiki:
+ * http://robowiki.net/wiki/Melee_Radar + *

+ * + * In addition, it makes use of the Exact Non-iterative Solution for Linear Targeting from the + * RoboWiki:
+ * http://robowiki.net/wiki/Linear_Targeting + * + * @author Flemming N. Larsen + * + * @version 1.0 + * + * @since 1.9.0.0 + */ +public class BorderGuard extends AdvancedRobot implements BorderSentry { + + // Constants + final double FIREPOWER = 3; // Max. power => violent as this robot can afford it! + final double HALF_ROBOT_SIZE = 18; // Robot size is 36x36 units, so the half size is 18 units + + // Map containing data for all scanned robots. + // The key to the map is a robot name and the value is an object containing robot data. + final Map enemyMap; + + // Scanning direction, where the radar turns to the right with positive values, and turns + // to the left with negative values. + double scanDir = 1; + + // Oldest scanned robot. Can be null. + RobotData oldestScanned; + + // Target robot for the gun. Can be null meaning that there is currently no target robot. + RobotData target; + + // Last time when the robot shifted its direction + long lastDirectionShift; + + // Current direction, where 1 means ahead (forward) and -1 means back + int direction = 1; + + /** + * Constructs this robot. + */ + public BorderGuard() { + // We initialize a specialized HashMap that uses a linked list for the access order. + // This means that the last accessed robot entry is listed first, when we iterate over its + // values. This robot always sweep the radar towards the oldest scanned robot. + enemyMap = new LinkedHashMap(5, 2, true); + } + + /** + * Main method that is called by the game when the robot engage in the next round of a battle. + */ + @Override + public void run() { + // Do initialization stuff here before the loop + initialize(); + + // Loop forever. If the robot does not take action, the game will disable our robot! + while (true) { + // Handle a single turn... + + // Handle the radar that scans enemy robots + handleRadar(); + // Handle the gun by turning it and fire at our target + handleGun(); + // Move the robot around on the battlefield + moveRobot(); + + // Scan for other robots. Note that this method will execute all pending commands for + // the next turn. Hence, scan() ends the turn for our robot. + scan(); + } + } + + /** + * This method is called by the game when your robot sees another robot, i.e. when the robot's + * radar scan "hits" another robot. + * + * @param scannedRobotEvent + * is a ScannedRobotEvent event. + */ + @Override + public void onScannedRobot(ScannedRobotEvent scannedRobotEvent) { + // Check that the scanned robot is not a sentry robot + if (!scannedRobotEvent.isSentryRobot()) { + // The scanned robot is not a sentry robot... + + // Update the enemy map + updateEnemyMap(scannedRobotEvent); + + // Update the scan direction + updateScanDirection(scannedRobotEvent); + + // Update enemy target positions + updateEnemyTargetPositions(); + } + } + + /** + * This method is called by the game when another robot dies. + * + * @param robotDeathEvent + * is the RobotDeathEvent that occurs, when another robot dies, which contains data + * for the robot that died. + */ + @Override + public void onRobotDeath(RobotDeathEvent robotDeathEvent) { + // Gets the name of the robot that died + final String deadRobotName = robotDeathEvent.getName(); + + // Remove the robot data for the robot that died from the enemy map + enemyMap.remove(deadRobotName); + + // Remove the data entry for the oldest scanned robot, if we have such an entry + if (oldestScanned != null && oldestScanned.name.equals(deadRobotName)) { + oldestScanned = null; + } + if (target != null && target.name.equals(deadRobotName)) { + target = null; + } + } + + /** + * This method is called by the every time the robot is painted. In order to see the painting, + * make sure to enable the Paint button on the robot console for this robot. + * + * @param g + * is the {@link Graphics2D} object, which is the graphics context used for painting + * various shapes like rectangles, circles, lines etc. on top of the battlefield for + * debugging graphics. + */ + @Override + public void onPaint(Graphics2D g) { + // Set the line width to 2 pixels + g.setStroke(new BasicStroke(2f)); + + // Prepare colors for painting the scanned coordinate and target coordinate + Color color1 = new Color(0x00, 0xFF, 0x00, 0x40); // Green with 25% alpha blending + Color color2 = new Color(0xFF, 0xFF, 0x00, 0x40); // Yellow with 25% alhpa blending + + // Paint a two circles for each robot in the enemy map. One circle where the robot was + // scanned the last time, and another circle where our robot must point the gun in order to + // hit it (target coordinate). In addition, a line is drawn between these circles. + for (RobotData robot : enemyMap.values()) { + // Paint the two circles and a line + fillCircle(g, robot.scannedX, robot.scannedY, color1); // scanned coordinate + fillCircle(g, robot.targetX, robot.targetY, color2); // target coordinate + g.setColor(color1); + g.drawLine((int) robot.scannedX, (int) robot.scannedY, (int) robot.targetX, (int) robot.targetY); + } + + // Paint a two circles for the target robot. One circle where the robot was + // scanned the last time, and another circle where our robot must point the gun in order to + // hit it (target coordinate). In addition, a line is drawn between these circles. + if (target != null) { + // Prepare colors for painting the scanned coordinate and target coordinate + color1 = new Color(0xFF, 0x7F, 0x00, 0x40); // Orange with 25% alpha blending + color2 = new Color(0xFF, 0x00, 0x00, 0x80); // Red with 50% alpha blending + + // Paint the two circles and a line + fillCircle(g, target.scannedX, target.scannedY, color1); // scanned coordinate + fillCircle(g, target.targetX, target.targetY, color2); // target coordinate + g.setColor(color1); + g.drawLine((int) target.scannedX, (int) target.scannedY, (int) target.targetX, (int) target.targetY); + } + } + + /** + * Initializes this robot before a new round in a battle. + */ + private void initialize() { + // Let the robot body, gun, and radar turn independently of each other + setAdjustRadarForGunTurn(true); + setAdjustGunForRobotTurn(true); + + // Set robot colors + setBodyColor(new Color(0x5C, 0x33, 0x17)); // Chocolate Brown + setGunColor(new Color(0x45, 0x8B, 0x74)); // Aqua Marine + setRadarColor(new Color(0xD2, 0x69, 0x1E)); // Orange Chocolate + setBulletColor(new Color(0xFF, 0xD3, 0x9B)); // Burly wood + setScanColor(new Color(0xCA, 0xFF, 0x70)); // Olive Green + } + + /** + * This method handles the radar that scans for enemy robots. + */ + private void handleRadar() { + // Set the radar to turn infinitely to the right if the scan direction is positive; + // otherwise the radar is moved to the left, if the scan direction is negative. + // Notice that onScannedRobot(ScannedRobotEvent) is responsible for determining the scan + // direction. + setTurnRadarRightRadians(scanDir * Double.POSITIVE_INFINITY); + } + + /** + * Method that handles the gun be turning it and fire at a target. + */ + private void handleGun() { + // Update our target robot to fire at + updateTarget(); + // Update the gun direction + updateGunDirection(); + // Fires the gun, when it is ready + fireGunWhenReady(); + } + + /** + * Method that moves our robot around the battlefield. + */ + private void moveRobot() { + + // The movement strategy is to move as close to our target robot as possible. + // Our robot should move along the borders all the time, vertically or horizontally. + // When we get close to our target, or have no where to go, our robot should shift its + // direction from side to side so it does not stand still at any time. + // If the robot stands still, it will be an easy target for enemy robots. + + int newDirection = direction; + + // Get closer to our target if we have a target robot + if (target != null) { + // Calculate the range from the walls/borders, our robot should keep within + int borderRange = getSentryBorderSize() - 20; + + // The horizontal and vertical flags are used for determining, if our robot should + // move horizontal or vertical. + boolean horizontal = false; + boolean vertical = false; + + // Initialize the new heading of the robot to the current heading of the robot + double newHeading = getHeadingRadians(); + + // Check if our robot is at the upper or lower border and hence should move horizontally + if (getY() < borderRange || getY() > getBattleFieldHeight() - borderRange) { + horizontal = true; + } + // Check if our robot is at the left or right border and hence should move vertically + if (getX() < borderRange || getX() > getBattleFieldWidth() - borderRange) { + vertical = true; + } + + // If we are in one of the corners of the battlefield, we could move both horizontally + // or vertically. + // In this situation, we need to choose one of the two directions. + if (horizontal && vertical) { + // If the horizontal distance to our target is lesser than the vertical distance, + // then we choose to move vertically, and hence we clear the horizontal flag. + if (Math.abs(target.targetX - getX()) <= Math.abs(target.targetY - getY())) { + horizontal = false; // Do not move horizontally => move vertically + } + } + // Adjust the heading of our robot with 90 degrees, if it must move horizontally. + // Otherwise the calculated heading is towards moving vertically. + if (horizontal) { + newHeading -= Math.PI / 2; + } + // Set the robot to turn left the amount of radians we have just calculated + setTurnLeftRadians(Utils.normalRelativeAngle(newHeading)); + + // Check if our robot has finished turning, i.e. has less than 1 degrees left to turn + if (Math.abs(getTurnRemaining()) < 1 || Math.abs(getVelocity()) < 0.01) { + // If we should move horizontally, the set the robot to move ahead with the + // horizontal distance to the target robot. Otherwise, use the vertical distance. + double delta; // delta is the delta distance to move + if (horizontal) { + delta = target.targetX - getX(); + } else { + delta = target.targetY - getY(); + } + setAhead(delta); + + // Set the new direction of our robot to 1 (meaning move forward) if the delta + // distance is positive; otherwise it is set to -1 (meaning move backward). + newDirection = delta > 0 ? 1 : -1; + + // Check if more than 10 turns have past since we changed the direction the last + // time + if (getTime() - lastDirectionShift > 10) { + // If so, set the new direction to be the reverse direction if the velocity < 1 + if (Math.abs(getVelocity()) < 1) { + newDirection = direction * -1; + } + // Check if the direction really changed + if (newDirection != direction) { + // If the new direction != current direction, then set the current direction + // to be the new direction and save the current time so we know when we + // changed the direction the last time. + direction = newDirection; + lastDirectionShift = getTime(); + } + } + } + } + // Set ahead 100 units forward or backward depending on the direction + setAhead(100 * direction); + } + + /** + * Method the updates the enemy map based on new scan data for a scanned robot. + * + * @param scannedRobotEvent + * is a ScannedRobotEvent event containing data about a scanned robot. + */ + private void updateEnemyMap(ScannedRobotEvent scannedRobotEvent) { + // Gets the name of the scanned robot + final String scannedRobotName = scannedRobotEvent.getName(); + + // Get robot data for the scanned robot, if we have an entry in the enemy map + RobotData scannedRobot = enemyMap.get(scannedRobotName); + + // Check if data entry exists for the scanned robot + if (scannedRobot == null) { + // No data entry exists => Create a new data entry for the scanned robot + scannedRobot = new RobotData(scannedRobotEvent); + // Put the new data entry into the enemy map + enemyMap.put(scannedRobotName, scannedRobot); + } else { + // Data entry exists => Update the current entry with new scanned data + scannedRobot.update(scannedRobotEvent); + } + } + + /** + * Method that updates the direction of the radar based on new scan data for a scanned robot. + * + * @param scannedRobotEvent + * is a ScannedRobotEvent event containing data about a scanned robot. + */ + private void updateScanDirection(ScannedRobotEvent scannedRobotEvent) { + // Gets the name of the scanned robot + final String scannedRobotName = scannedRobotEvent.getName(); + + // Change the scanning direction if and only if we have no record for the oldest scanned + // robot or the scanned robot IS the oldest scanned robot (based on the name) AND the enemy + // map contains scanned data entries for ALL robots (the size of the enemy map is equal to + // the number of opponent robots found by calling the getOthers() method). + if ((oldestScanned == null || scannedRobotName.equals(oldestScanned.name)) && enemyMap.size() == getOthers()) { + + // Get the oldest scanned robot data from our LinkedHashMap, where the first value + // contains the oldest accessed entry, which is the robot we need to get. + RobotData oldestScannedRobot = enemyMap.values().iterator().next(); + + // Get the recent scanned position (x,y) of the oldest scanned robot + double x = oldestScannedRobot.scannedX; + double y = oldestScannedRobot.scannedY; + + // Get the heading of our robot + double ourHeading = getRadarHeadingRadians(); + + // Calculate the bearing to the oldest scanned robot. + // The bearing is the delta angle between the heading of our robot and the other robot, + // which can be a positive or negative angle. + double bearing = bearingTo(ourHeading, x, y); + + // Update the scan direction based on the bearing. + // If the bearing is positive, the radar will be moved to the right. + // If the bearing is negative, the radar will be moved to the left. + scanDir = bearing; + } + } + + /** + * Updates the target positions for all enemies. The target position is the position our robot + * must fire at in order to hit the target robot. This robot uses Linear Targeting (Exact + * Non-iterative Solution) as described on the RoboWiki here: + * http://robowiki.net/wiki/Linear_Targeting + */ + private void updateEnemyTargetPositions() { + // Go thru all robots in the enemy map + for (RobotData enemy : enemyMap.values()) { + + // Variables prefixed with e- refer to enemy and b- refer to bullet + double bV = Rules.getBulletSpeed(FIREPOWER); + double eX = enemy.scannedX; + double eY = enemy.scannedY; + double eV = enemy.scannedVelocity; + double eH = enemy.scannedHeading; + + // These constants make calculating the quadratic coefficients below easier + double A = (eX - getX()) / bV; + double B = (eY - getY()) / bV; + double C = eV / bV * Math.sin(eH); + double D = eV / bV * Math.cos(eH); + + // Quadratic coefficients: a*(1/t)^2 + b*(1/t) + c = 0 + double a = A * A + B * B; + double b = 2 * (A * C + B * D); + double c = (C * C + D * D - 1); + + // If the discriminant of the quadratic formula is >= 0, we have a solution meaning that + // at some time, t, the bullet will hit the enemy robot if we fire at it now. + double discrim = b * b - 4 * a * c; + if (discrim >= 0) { + // Reciprocal of quadratic formula. Calculate the two possible solution for the + // time, t + double t1 = 2 * a / (-b - Math.sqrt(discrim)); + double t2 = 2 * a / (-b + Math.sqrt(discrim)); + + // Choose the minimum positive time or select the one closest to 0, if the time is + // negative + double t = Math.min(t1, t2) >= 0 ? Math.min(t1, t2) : Math.max(t1, t2); + + // Calculate the target position (x,y) for the enemy. That is the point that our gun + // should point at in order to hit the enemy at the time, t. + double targetX = eX + eV * t * Math.sin(eH); + double targetY = eY + eV * t * Math.cos(eH); + + // Assume enemy stops at walls. Hence, we limit that target position at the walls. + double minX = HALF_ROBOT_SIZE; + double minY = HALF_ROBOT_SIZE; + double maxX = getBattleFieldWidth() - HALF_ROBOT_SIZE; + double maxY = getBattleFieldHeight() - HALF_ROBOT_SIZE; + + enemy.targetX = limit(targetX, minX, maxX); + enemy.targetY = limit(targetY, minY, maxY); + } + } + } + + /** + * Updates which enemy robot from the enemy map that should be our current target. + */ + private void updateTarget() { + // Set target to null, meaning that we have no target robot yet + target = null; + + // Create a list over possible target robots that is a copy of robot data from the enemy map + List targets = new ArrayList(enemyMap.values()); + + // Run thru all the possible target robots and remove those that are outside the attack + // range for this border sentry robot as our robot cannot do harm to robots outside its + // range. + Iterator it = targets.iterator(); + while (it.hasNext()) { + RobotData robot = it.next(); + if (isOutsideAttackRange(robot.targetX, robot.targetY)) { + it.remove(); + } + } + + // Set the target robot to be the one among all possible target robots that is closest to + // our robot. + double minDist = Double.POSITIVE_INFINITY; + for (RobotData robot : targets) { + double dist = distanceTo(robot.targetX, robot.targetY); + if (dist < minDist) { + minDist = dist; + target = robot; + } + } + + // If we still haven't got a target robot, then take the first one from our list of target + // robots if the list is not empty. + if (target == null && targets.size() > 0) { + target = targets.get(0); + } + } + + /** + * Method that updates the gun direction to point at the current target. + */ + private void updateGunDirection() { + // Only update the gun direction, if we have a current target + if (target != null) { + // Calculate the bearing between the gun and the target, which can be positive or + // negative + double targetBearing = bearingTo(getGunHeadingRadians(), target.targetX, target.targetY); + // Set the gun to turn right the amount of radians defined by the bearing to the target + setTurnGunRightRadians(targetBearing); // positive => turn right, negative => turn left + } + } + + /** + * Method that fires a bullet when the gun is ready to fire. + */ + private void fireGunWhenReady() { + // We only fire the fun, when we have a target robot + if (target != null) { + // Only fire when the angle of the gun is pointing at our (virtual) target robot + + // Calculate the distance between between our robot and the target robot + double dist = distanceTo(target.targetX, target.targetY); + // Angle that "covers" the the target robot from its center to its edge + double angle = Math.atan(HALF_ROBOT_SIZE / dist); + + // Check if the remaining angle (turn) to move the gun is less than our calculated cover + // angle + if (Math.abs(getGunTurnRemaining()) < angle) { + // If so, our gun should be pointing at our target so we can hit it => fire!! + setFire(FIREPOWER); + } + } + } + + /** + * Method that checks if a coordinate (x,y) is outside the Border Sentry's attack range. + * + * @param x + * is the x coordinate. + * @param y + * is the y coordinate. + * @return true if the coordinate is outside the attack range; false otherwise. + */ + private boolean isOutsideAttackRange(double x, double y) { + double minBorderX = getSentryBorderSize(); + double minBorderY = getSentryBorderSize(); + double maxBorderX = getBattleFieldWidth() - getSentryBorderSize(); + double maxBorderY = getBattleFieldHeight() - getSentryBorderSize(); + + return (x > minBorderX) && (y > minBorderY) && (x < maxBorderX) && (y < maxBorderY); + } + + /** + * Method that returns a value that is guaranteed to be within a value range defined by a + * minimum and maximum value based on an input value.
+ * If the input value is lesser than the minimum value, the returned value will be set to the + * minimum value.
+ * If the input value is greater than the maximum value, the returned value will be set to the + * maximum value.
+ * Otherwise the returned value will be equal to the input value. + * + * @param value + * is the input value to limit. + * @param min + * is the allowed minimum value. + * @param max + * is the allowed maximum value. + * @return the limited input value that is guaranteed to be within the specified minimum and + * maximum range. + */ + private double limit(double value, double min, double max) { + return Math.min(max, Math.max(min, value)); + } + + /** + * Methods that returns the distance to a coordinate (x,y) from our robot. + * + * @param x + * is the x coordinate. + * @param y + * is the y coordinate. + * @return the distance to the coordinate (x,y). + */ + private double distanceTo(double x, double y) { + return Math.hypot(x - getX(), y - getY()); + } + + /** + * Method that returns the angle to a coordinate (x,y) from our robot. + * + * @param x + * is the x coordinate. + * @param y + * is the y coordinate. + * @return the angle to the coordinate (x,y). + */ + private double angleTo(double x, double y) { + return Math.atan2(x - getX(), y - getY()); + } + + /** + * Method that returns the bearing to a coordinate (x,y) from the position and heading of our + * robot. The bearing is the delta angle between the heading of our robot and the angle of the + * specified coordinate. + * + * @param x + * is the x coordinate. + * @param y + * is the y coordinate. + * @return the angle to the coordinate (x,y). + */ + private double bearingTo(double heading, double x, double y) { + return Utils.normalRelativeAngle(angleTo(x, y) - heading); + } + + /** + * Method that paints a filled circle at the specified coordinate (x,y) and given color. The + * circle will have a radius of 20 pixels (meaning that the diameter will be 40 pixels). + * + * @param gfx + * is the graphics context to draw within. + * @param x + * is the x coordinate for the center of the circle. + * @param y + * is the y coordinate for the center of the circle. + * @param color + * is the color of the filled circle. + */ + private void fillCircle(Graphics2D gfx, double x, double y, Color color) { + // Set the pen color + gfx.setColor(color); + // Paint a filled circle (oval) that has a radius of 20 pixels with a center at the input + // coordinates. + gfx.fillOval((int) x - 20, (int) y - 20, 40, 40); + } + + /** + * This class is used for storing data about a robot that has been scanned.
+ * The data is mainly a snapshot of specific scanned data like the scanned position (x,y), + * velocity and heading, put also the calculated predicted target position of the robot when our + * robot needs to fire at the scanned robot.
+ * Note that this class calculates the position (x,y) of the scanned robot as our robot moves, + * and hence data like the angle and distance to the scanned robot will change over time. by + * using the position, it is easy to calculate a new angle and distance to the robot. + */ + class RobotData { + final String name; // name of the scanned robot + double scannedX; // x coordinate of the scanned robot based on the last update + double scannedY; // y coordinate of the scanned robot based on the last update + double scannedVelocity; // velocity of the scanned robot from the last update + double scannedHeading; // heading of the scanned robot from the last update + double targetX; // predicated x coordinate to aim our gun at, when firing at the robot + double targetY; // predicated y coordinate to aim our gun at, when firing at the robot + + /** + * Creates a new robot data entry based on new scan data for a scanned robot. + * + * @param event + * is a ScannedRobotEvent event containing data about a scanned robot. + */ + RobotData(ScannedRobotEvent event) { + // Store the name of the scanned robot + name = event.getName(); + // Updates all scanned facts like position, velocity, and heading + update(event); + // Initialize the coordinates (x,y) to fire at to the updated scanned position + targetX = scannedX; + targetY = scannedY; + } + + /** + * Updates the scanned data based on new scan data for a scanned robot. + * + * @param event + * is a ScannedRobotEvent event containing data about a scanned robot. + */ + void update(ScannedRobotEvent event) { + // Get the position of the scanned robot based on the ScannedRobotEvent + Point2D.Double pos = getPosition(event); + // Store the scanned position (x,y) + scannedX = pos.x; + scannedY = pos.y; + // Store the scanned velocity and heading + scannedVelocity = event.getVelocity(); + scannedHeading = event.getHeadingRadians(); + } + + /** + * Returns the position of the scanned robot based on new scan data for a scanned robot. + * + * @param event + * is a ScannedRobotEvent event containing data about a scanned robot. + * @return the position (x,y) of the scanned robot. + */ + Point2D.Double getPosition(ScannedRobotEvent event) { + // Gets the distance to the scanned robot + double distance = event.getDistance(); + // Calculate the angle to the scanned robot (our robot heading + bearing to scanned + // robot) + double angle = getHeadingRadians() + event.getBearingRadians(); + + // Calculate the coordinates (x,y) of the scanned robot + double x = getX() + Math.sin(angle) * distance; + double y = getY() + Math.cos(angle) * distance; + + // Return the position as a point (x,y) + return new Point2D.Double(x, y); + } + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/MyFirstDroid.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/MyFirstDroid.java new file mode 100644 index 0000000..c57d0d2 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/MyFirstDroid.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleteam; + + +import robocode.Droid; +import robocode.MessageEvent; +import robocode.TeamRobot; +import static robocode.util.Utils.normalRelativeAngleDegrees; + + +/** + * SimpleDroid - a sample robot by Mathew Nelson. + *

+ * Follows orders of team leader. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class MyFirstDroid extends TeamRobot implements Droid { + + /** + * run: Droid's default behavior + */ + public void run() { + out.println("MyFirstDroid ready."); + } + + /** + * onMessageReceived: What to do when our leader sends a message + */ + public void onMessageReceived(MessageEvent e) { + // Fire at a point + if (e.getMessage() instanceof Point) { + Point p = (Point) e.getMessage(); + // Calculate x and y to target + double dx = p.getX() - this.getX(); + double dy = p.getY() - this.getY(); + // Calculate angle to target + double theta = Math.toDegrees(Math.atan2(dx, dy)); + + // Turn gun to target + turnGunRight(normalRelativeAngleDegrees(theta - getGunHeading())); + // Fire hard! + fire(3); + } // Set our colors + else if (e.getMessage() instanceof RobotColors) { + RobotColors c = (RobotColors) e.getMessage(); + + setBodyColor(c.bodyColor); + setGunColor(c.gunColor); + setRadarColor(c.radarColor); + setScanColor(c.scanColor); + setBulletColor(c.bulletColor); + } + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/MyFirstLeader.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/MyFirstLeader.java new file mode 100644 index 0000000..140a94a --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/MyFirstLeader.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleteam; + + +import robocode.HitByBulletEvent; +import robocode.ScannedRobotEvent; +import robocode.TeamRobot; + +import java.awt.*; +import java.io.IOException; + + +/** + * MyFirstLeader - a sample team robot by Mathew Nelson. + *

+ * Looks around for enemies, and orders teammates to fire + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class MyFirstLeader extends TeamRobot { + + /** + * run: Leader's default behavior + */ + public void run() { + // Prepare RobotColors object + RobotColors c = new RobotColors(); + + c.bodyColor = Color.red; + c.gunColor = Color.red; + c.radarColor = Color.red; + c.scanColor = Color.yellow; + c.bulletColor = Color.yellow; + + // Set the color of this robot containing the RobotColors + setBodyColor(c.bodyColor); + setGunColor(c.gunColor); + setRadarColor(c.radarColor); + setScanColor(c.scanColor); + setBulletColor(c.bulletColor); + try { + // Send RobotColors object to our entire team + broadcastMessage(c); + } catch (IOException ignored) {} + // Normal behavior + while (true) { + setTurnRadarRight(10000); + ahead(100); + back(100); + } + } + + /** + * onScannedRobot: What to do when you see another robot + */ + public void onScannedRobot(ScannedRobotEvent e) { + // Don't fire on teammates + if (isTeammate(e.getName())) { + return; + } + // Calculate enemy bearing + double enemyBearing = this.getHeading() + e.getBearing(); + // Calculate enemy's position + double enemyX = getX() + e.getDistance() * Math.sin(Math.toRadians(enemyBearing)); + double enemyY = getY() + e.getDistance() * Math.cos(Math.toRadians(enemyBearing)); + + try { + // Send enemy position to teammates + broadcastMessage(new Point(enemyX, enemyY)); + } catch (IOException ex) { + out.println("Unable to send order: "); + ex.printStackTrace(out); + } + } + + /** + * onHitByBullet: Turn perpendicular to bullet path + */ + public void onHitByBullet(HitByBulletEvent e) { + turnLeft(90 - e.getBearing()); + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/Point.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/Point.java new file mode 100644 index 0000000..79f9c1b --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/Point.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleteam; + + +/** + * Point - a serializable point class + */ +public class Point implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + + private double x = 0.0; + private double y = 0.0; + + public Point(double x, double y) { + this.x = x; + this.y = y; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/RobotColors.java b/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/RobotColors.java new file mode 100644 index 0000000..079bc60 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/java/sampleteam/RobotColors.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package sampleteam; + + +import java.awt.*; + + +/** + * RobotColors - A serializable class to send Colors to teammates. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobotColors implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + + public Color bodyColor; + public Color gunColor; + public Color radarColor; + public Color scanColor; + public Color bulletColor; +} diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Corners.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Corners.properties new file mode 100644 index 0000000..86a295d --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Corners.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:14:27 EST 2006 +robot.description=\ A sample robot\n Moves to a corner, then swings the gun back and forth.\n If it dies, it tries a new corner in the next round. +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.Corners +robot.name=Corners diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Crazy.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Crazy.properties new file mode 100644 index 0000000..adc9001 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Crazy.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:16:04 EST 2006 +robot.description=\ A sample robot\n\n Moves around in a crazy pattern +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.Crazy +robot.name=Crazy diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Fire.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Fire.properties new file mode 100644 index 0000000..db0f3a7 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Fire.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:16:33 EST 2007 +robot.description=\ A sample robot\n\n Sits still. Spins gun around. Moves when hit. Ooh\! +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.Fire +robot.name=Fire diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Interactive.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Interactive.properties new file mode 100644 index 0000000..66603d1 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Interactive.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Wed Jun 27 23:08:48 EST 2007 +robot.description=\ A sample robot\n\n This is a robot that is controlled using the arrow keys and mouse only +robot.webpage= +robocode.version=1.3.4 +robot.java.source.included=true +robot.author.name=Flemming N. Larsen +robot.classname=sample.Interactive +robot.name=Interactive \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Interactive_v2.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Interactive_v2.properties new file mode 100644 index 0000000..aab1784 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Interactive_v2.properties @@ -0,0 +1,8 @@ +#Robot Properties +robot.description=\ A sample robot\n\n This is a robot that is controlled using the arrow keys and mouse only +robot.webpage= +robocode.version=1.3.4 +robot.java.source.included=true +robot.author.name=Tuan Anh Nguyen and Flemming N. Larsen +robot.classname=sample.Interactive_v2 +robot.name=Interactive_v2 \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/MyFirstJuniorRobot.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/MyFirstJuniorRobot.properties new file mode 100644 index 0000000..2cafbdc --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/MyFirstJuniorRobot.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Jul 29 00:07:28 EST 2007 +robot.description=\ A sample robot\n Moves in a seesaw motion, and spins the gun around at each end\n Moves perpendicular to the direction of a bullet that hits it +robot.webpage= +robocode.version=1.4 +robot.java.source.included=true +robot.author.name=Flemming N. Larsen +robot.classname=sample.MyFirstJuniorRobot +robot.name=MyFirstJuniorRobot \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/MyFirstRobot.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/MyFirstRobot.properties new file mode 100644 index 0000000..1d298da --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/MyFirstRobot.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Fri Nov 02 17:17:44 EST 2001 +robot.description=\ A sample robot\n Moves in a seesaw motion, and spins the gun around at each end\n Turns perpendicular to the direction of a bullet that hits it +robot.webpage=http\://robocode.sourceforge.net/myfirstrobot/MyFirstRobot.html +robocode.version=1.0 +robot.java.source.included=true +robot.author.name=Mathew Nelson +robot.classname=sample.MyFirstRobot +robot.name=MyFirstRobot diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/PaintingRobot.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/PaintingRobot.properties new file mode 100644 index 0000000..df0c29e --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/PaintingRobot.properties @@ -0,0 +1,10 @@ +#Robot Properties +#Sat Apr 12 14:47:44 EST 2008 +robot.description=\ A sample robot\n Demonstrates how to do custom painting and debugging properties. +robot.webpage= +robocode.version=1.6 +robot.java.source.included=true +robot.author.name=Stefan Westen +robot.classname=sample.PaintingRobot +robot.name=PaintingRobot + diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/RamFire.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/RamFire.properties new file mode 100644 index 0000000..e48d0d4 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/RamFire.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:17:21 EST 2007 +robot.description=\ A sample robot\n Drives at robots trying to ram them.\n Fires when it hits them. +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.RamFire +robot.name=RamFire diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/SittingDuck.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/SittingDuck.properties new file mode 100644 index 0000000..c3aab1e --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/SittingDuck.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:18:07 EST 2007 +robot.description=\ A sample robot\nThis robot sits still, and waits to be fired upon. Exciting stuff\!\nAlso counts how many times he has been a sitting duck. +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.SittingDuck +robot.name=SittingDuck diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/SpinBot.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/SpinBot.properties new file mode 100644 index 0000000..c80fa0b --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/SpinBot.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:18:07 EST 2006 +robot.description=\ A sample robot\n\n Moves in a circle, firing hard when an enemy is detected +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.SpinBot +robot.name=SpinBot diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Target.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Target.properties new file mode 100644 index 0000000..4537956 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Target.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:18:46 EST 2006 +robot.description=\ A sample robot\n Sits still. Moves every time energy drops by 20.\n This Robot demonstrates custom events. +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.Target +robot.name=Target diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/TrackFire.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/TrackFire.properties new file mode 100644 index 0000000..be9b3e8 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/TrackFire.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:21:08 EST 2006 +robot.description=\ A sample robot\n\n Tracks and fires at the nearest robot it sees +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.TrackFire +robot.name=TrackFire diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Tracker.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Tracker.properties new file mode 100644 index 0000000..1e510a5 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Tracker.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:20:26 EST 2006 +robot.description=\ A sample robot\n\n Locks onto a robot, moves close, fires when close. +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.Tracker +robot.name=Tracker diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/VelociRobot.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/VelociRobot.properties new file mode 100644 index 0000000..a48dbb8 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/VelociRobot.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Tue May 27 14:21:08 EST 2009 +robot.description=\ A sample robot\n\n Demonstrates the RateControlRobot +robot.webpage= +robocode.version=1.7.1.3 +robot.java.source.included=true +robot.author.name=Joshua Galecki +robot.classname=sample.VelociRobot +robot.name=VelociRobot diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Walls.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Walls.properties new file mode 100644 index 0000000..7549037 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sample/Walls.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Aug 20 21:21:53 EST 2006 +robot.description=\ A sample robot\n\n Moves around the outer edge with the gun facing in +robot.webpage= +robocode.version=1.1.2 +robot.java.source.included=true +robot.author.name=Mathew Nelson and Flemming N. Larsen +robot.classname=sample.Walls +robot.name=Walls diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/Alien.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/Alien.properties new file mode 100644 index 0000000..292c411 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/Alien.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Feb 20 21:16:33 EST 2008 +robot.description=\ A sample robot\n\n Is not inherited from classic base robots,\n uses new experimental access to RobotPeer. +robot.webpage=zamboch.blogspot.com +robocode.version=1.6 +robot.java.source.included=true +robot.author.name=Pavel Savara +robot.classname=sampleex.Alien +robot.name=Alien diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/MasterAndSlave.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/MasterAndSlave.properties new file mode 100644 index 0000000..539d240 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/MasterAndSlave.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Feb 20 21:16:33 EST 2008 +robot.description=\ A sample robot\n\n Is not inherited from classic base robots,\n uses new experimental access to RobotPeer. +robot.webpage=zamboch.blogspot.com +robocode.version=1.6 +robot.java.source.included=true +robot.author.name=Pavel Savara +robot.classname=sampleex.MasterAndSlave +robot.name=MasterAndSlave diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/ProxyOfGreyEminence.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/ProxyOfGreyEminence.properties new file mode 100644 index 0000000..e47c5a0 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sampleex/ProxyOfGreyEminence.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sun Feb 20 21:16:33 EST 2008 +robot.description=\ A sample robot\n\n Is not inherited from classic base robots,\n uses new experimental access to RobotPeer. +robot.webpage=zamboch.blogspot.com +robocode.version=1.6 +robot.java.source.included=true +robot.author.name=Pavel Savara +robot.classname=sampleex.ProxyOfGreyEminence +robot.name=ProxyOfGreyEminence diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/samplesentry/BorderGuard.properties b/代码/workspace_robo4/robocode.samples/src/main/resources/samplesentry/BorderGuard.properties new file mode 100644 index 0000000..4224bae --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/samplesentry/BorderGuard.properties @@ -0,0 +1,9 @@ +#Robot Properties +#Sat May 25 22:15:07 EST 2013 +robot.description=\ A sample robot\n\n This is a robot that guards the borders of the battlefield\n\nUse it against \"wall crawlers\" like e.g. sample.Walls and sample.Corners +robot.webpage= +robocode.version=1.9.0.0 +robot.java.source.included=true +robot.author.name=Flemming N. Larsen +robot.classname=samplesentry.BorderGuard +robot.name=BorderGuard \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.samples/src/main/resources/sampleteam/MyFirstTeam.team b/代码/workspace_robo4/robocode.samples/src/main/resources/sampleteam/MyFirstTeam.team new file mode 100644 index 0000000..f9878e8 --- /dev/null +++ b/代码/workspace_robo4/robocode.samples/src/main/resources/sampleteam/MyFirstTeam.team @@ -0,0 +1,7 @@ +#Robocode robot team +#Sun Aug 20 23:26:53 EST 2006 +team.members=sampleteam.MyFirstLeader,sampleteam.MyFirstDroid,sampleteam.MyFirstDroid,sampleteam.MyFirstDroid,sampleteam.MyFirstDroid +team.author.name=Mathew Nelson and Flemming N. Larsen +robocode.version=1.1.2 +team.webpage= +team.description=\ A sample team.\n MyFirstLeader scans for enemies,\n and orders the 4 droids to fire. diff --git a/代码/workspace_robo4/robocode.sound/.classpath b/代码/workspace_robo4/robocode.sound/.classpath new file mode 100644 index 0000000..f924dfd --- /dev/null +++ b/代码/workspace_robo4/robocode.sound/.classpath @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.sound/.project b/代码/workspace_robo4/robocode.sound/.project new file mode 100644 index 0000000..d9a53a7 --- /dev/null +++ b/代码/workspace_robo4/robocode.sound/.project @@ -0,0 +1,17 @@ + + + robocode.sound + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.core + robocode.api + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.sound/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.sound/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.sound/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.sound/pom.xml b/代码/workspace_robo4/robocode.sound/pom.xml new file mode 100644 index 0000000..b10ad26 --- /dev/null +++ b/代码/workspace_robo4/robocode.sound/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + robocode.sound + Robocode Sound + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.core + ${project.version} + + + diff --git a/代码/workspace_robo4/robocode.sound/robocode.sound.iml b/代码/workspace_robo4/robocode.sound/robocode.sound.iml new file mode 100644 index 0000000..be8c06b --- /dev/null +++ b/代码/workspace_robo4/robocode.sound/robocode.sound.iml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/Module.java b/代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/Module.java new file mode 100644 index 0000000..2cb58c0 --- /dev/null +++ b/代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/Module.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.sound; + + +import net.sf.robocode.core.BaseModule; +import net.sf.robocode.core.Container; + + +/** + * @author Pavel Savara (original) + */ +public class Module extends BaseModule { + static { + Container.cache.addComponent(ISoundManager.class, SoundManager.class); + } +} diff --git a/代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/SoundCache.java b/代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/SoundCache.java new file mode 100644 index 0000000..fae8191 --- /dev/null +++ b/代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/SoundCache.java @@ -0,0 +1,219 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.sound; + + +import net.sf.robocode.io.Logger; + +import javax.sound.sampled.*; +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + + +/** + * SoundCache maintains a table of sound clips. More than one instance of the same + * sample can be stored, so a given sound effect can be played more than once + * symultaneously. + * + * @author Luis Crespo (original) + * @author Flemming N. Larsen (contributor) + */ +class SoundCache { + + /** + * Table containing all sound clips + */ + private final Map soundTable; + + /** + * Mixer used for creating clip instances + */ + private final Mixer mixer; + + /** + * Holds data, length and format for a given sound effect, which can be used to create + * multiple instances of the same clip. + */ + private static class SoundData { + private final AudioFormat format; + private final int length; + private final byte[] byteData; + + private SoundData(AudioInputStream ais) throws IOException { + int bytesRead, pos; + + format = ais.getFormat(); + length = (int) (ais.getFrameLength() * format.getFrameSize()); + byteData = new byte[length]; + pos = 0; + + do { + bytesRead = ais.read(byteData, pos, length - pos); + if (bytesRead > 0) { + pos += bytesRead; + } + } while (bytesRead > 0 && pos < length); + + ais.close(); + } + } + + + /** + * Holds an array of clips from the same sample stream, and takes care of + * returning the next available clip. If all clips are active, the least + * recently used clip will be returned. + */ + private static class ClipClones { + private final Clip[] clips; + private int idx; + + private ClipClones(Mixer mixer, SoundData soundData, int size) throws LineUnavailableException { + idx = 0; + clips = new Clip[size]; + + DataLine.Info info = new DataLine.Info(Clip.class, soundData.format); + + if (!AudioSystem.isLineSupported(info)) { + throw new LineUnavailableException("Required data line is not supported by the audio system"); + } + + for (int i = 0; i < size; i++) { + clips[i] = (Clip) mixer.getLine(info); + clips[i].open(soundData.format, soundData.byteData, 0, soundData.length); + } + } + + private void dispose() { + for (Clip c : clips) { + c.close(); + } + } + + private Clip next() { + Clip c = clips[idx]; + + idx = (idx + 1) % clips.length; + c.stop(); + c.setFramePosition(0); + return c; + } + } + + /** + * Constructs a sound cache to hold sound clips that is created based on the + * specified mixer. + * + * @param mixer the mixer to be used for creating the clip instances + */ + public SoundCache(Mixer mixer) { + this.mixer = mixer; + soundTable = new HashMap(); + } + + /** + * Adds a number of clip clones for a given resource holding the audio data. + * If there is any error, the method returns silently, and clip instances will + * not be found later for the provided key. + * + * @param key the key to be used for later retrieval of the sound + * @param resourceName the resource holding the audio data + * @param numClones the number of copies of the clip to be created + */ + public void addSound(Object key, String resourceName, int numClones) { + if (mixer == null || resourceName == null || (resourceName.trim().length() == 0)) { + return; + } + + SoundData data = createSoundData(resourceName); + + if (data == null) { + return; + } + + ClipClones clones; + + try { + clones = new ClipClones(mixer, data, numClones); + soundTable.put(key, clones); + } catch (LineUnavailableException e) { + Logger.logError( + "The audio mixer " + mixer.getMixerInfo().getName() + + " does not support the audio format of the sound clip: " + resourceName); + } + } + + /** + * Creates an instance of SoundData, to be used later for creating the clip clones. + * + * @param resourceName the name of the resource holding the audio data + * @return the newly created sound data + */ + private SoundData createSoundData(String resourceName) { + SoundData data; + URL url = SoundCache.class.getResource(resourceName); + + if (url == null) { + Logger.logError("Could not load sound because of invalid resource name: " + resourceName); + return null; + } + try { + AudioInputStream ais = AudioSystem.getAudioInputStream(url); + + data = new SoundData(ais); + } catch (Exception e) { + Logger.logError("Error while reading sound from resource: " + resourceName, e); + data = null; + } + return data; + } + + /** + * Gets the next available clip instance of a given sound. If all clips for that + * sound are active (playing), the least recently used will be returned. + * + * @param key the key that was used when adding the sound + * @return a clip instance ready to be played through Clip.start() + */ + public Clip getSound(Object key) { + ClipClones clones = soundTable.get(key); + + if (clones == null) { + return null; + } + return clones.next(); + } + + /** + * Removes all clip copies of a given sound, closing all its dependent resources + * + * @param key the key that was used when adding the sound + */ + public void removeSound(Object key) { + ClipClones clones = soundTable.get(key); + + if (clones == null) { + return; + } + clones.dispose(); + + soundTable.remove(key); + } + + /** + * Empties all clips from the sound cache + */ + public void clear() { + for (ClipClones clones : soundTable.values()) { + clones.dispose(); + } + soundTable.clear(); + } +} diff --git a/代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/SoundManager.java b/代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/SoundManager.java new file mode 100644 index 0000000..9886d13 --- /dev/null +++ b/代码/workspace_robo4/robocode.sound/src/main/java/net/sf/robocode/sound/SoundManager.java @@ -0,0 +1,376 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.sound; + + +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.settings.ISettingsListener; +import net.sf.robocode.settings.ISettingsManager; +import robocode.control.events.BattleAdaptor; +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.BattleStartedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IBulletSnapshot; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.snapshot.RobotState; + +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.FloatControl; +import javax.sound.sampled.Mixer; + + +/** + * The sound manager is responsible of keeping a table of sound effects and + * play the appropriate sound for each bullet or robot event that is supposed + * to make any noise. + * + * @author Luis Crespo (original) + * @author Flemming N. Larsen (contributor) + * @author Titus Chen (contributor) + */ +public class SoundManager implements ISoundManager { + + // Cache containing sound clips + private SoundCache sounds; + + // Access to properties + private final ISettingsManager properties; + private final IBattleManager battleManager; + private boolean isSoundEnabled = true; + BattleObserver observer; + + public SoundManager(final ISettingsManager properties, IBattleManager battleManager) { + this.battleManager = battleManager; + this.properties = properties; + if (isSoundEnabled()) { + observer = new BattleObserver(); + battleManager.addListener(observer); + } + + properties.addPropertyListener(new ISettingsListener() { + public void settingChanged(String property) { + if (property.equals(ISettingsManager.OPTIONS_SOUND_ENABLESOUND)) { + updateListener(); + } + } + }); + + } + + /** + * Returns the current mixer selected from the Robocode properties. + * + * @return the current Mixer instance + */ + public Mixer getMixer() { + return findMixer(properties.getOptionsSoundMixer()); + } + + private boolean isSoundEnabled() { + return isSoundEnabled && properties.getOptionsSoundEnableSound(); + } + + public void setEnableSound(boolean enable) { + isSoundEnabled = enable; + updateListener(); + } + + private void updateListener() { + if (observer == null && isSoundEnabled()) { + observer = new BattleObserver(); + battleManager.addListener(observer); + } else if (observer != null && !isSoundEnabled()) { + battleManager.removeListener(observer); + observer = null; + } + } + + /** + * Returns the cache containing sound clips. + * + * @return a SoundCache instance + */ + private SoundCache getSounds() { + if (sounds == null) { + sounds = new SoundCache(getMixer()); + + // Sound effects + sounds.addSound("gunshot", properties.getFileGunshotSfx(), 5); + sounds.addSound("robot death", properties.getRobotDeathSfx(), 3); + sounds.addSound("bullet hits robot", properties.getBulletHitsRobotSfx(), 3); + sounds.addSound("bullet hits bullet", properties.getBulletHitsBulletSfx(), 2); + sounds.addSound("robot collision", properties.getRobotCollisionSfx(), 2); + sounds.addSound("wall collision", properties.getWallCollisionSfx(), 2); + + // Music + sounds.addSound("theme", properties.getFileThemeMusic(), 1); + sounds.addSound("background", properties.getFileBackgroundMusic(), 1); + sounds.addSound("endOfBattle", properties.getFileEndOfBattleMusic(), 1); + } + return sounds; + } + + /** + * Iterates over the available mixers, looking for the one that matches a given + * class name. + * + * @param mixerClassName the class name of the mixer to be used. + * @return the requested mixer, if found. Otherwise, it returns null. + */ + private Mixer findMixer(String mixerClassName) { + if (mixerClassName == null) { + return null; + } + for (Mixer.Info mi : AudioSystem.getMixerInfo()) { + Mixer m = AudioSystem.getMixer(mi); + + if (m.getClass().getSimpleName().equals(mixerClassName)) { + return m; + } + } + return null; + } + + /** + * Performs shutdown, by liberating the sound table + */ + public void dispose() { + if (sounds != null) { // Do not call getSounds()! + sounds.clear(); + } + } + + /** + * Plays a specific sound at a given volume, panning and loop count + * + * @param key the sound name, as stored in the sound table + * @param pan panning to be used (-1=left, 0=middle, +1=right) + * @param volume volume to be used, from 0 to 1 + * @param loop the number of times to loop the sound + */ + private void playSound(Object key, float pan, float volume, int loop) { + Clip c = getSounds().getSound(key); + + if (c == null) { + return; + } + + if (properties.getOptionsSoundEnableMixerPan() && c.isControlSupported(FloatControl.Type.PAN)) { + FloatControl panCtrl = (FloatControl) c.getControl(FloatControl.Type.PAN); + + panCtrl.setValue(pan); + } + if (properties.getOptionsSoundEnableMixerVolume() && c.isControlSupported(FloatControl.Type.MASTER_GAIN)) { + FloatControl volCtrl = (FloatControl) c.getControl(FloatControl.Type.MASTER_GAIN); + + float min = volCtrl.getMinimum() / 4; + + if (volume != 1) { + volCtrl.setValue(min * (1 - volume)); + } + } + c.loop(loop); + } + + /** + * Plays a specific sound at a given panning with max. volume and without looping. + * + * @param key the sound name, as stored in the sound table + * @param pan panning to be used (-1=left, 0=middle, +1=right) + */ + private void playSound(Object key, float pan) { + playSound(key, pan, 1, 0); + } + + /** + * Plays a specific piece of music with a given loop count with no panning and + * max. volume. + * + * @param key the sound name, as stored in the sound table + * @param loop the number of times to loop the music + */ + private void playMusic(Object key, int loop) { + playSound(key, 0, 1, loop); + } + + /** + * Plays a bullet sound depending on the bullet's state + * + * @param bp the bullet peer + * @param battleFieldWidth the width of the battle field used for panning. + */ + public void playBulletSound(IBulletSnapshot bp, int battleFieldWidth) { + float pan = 0; + + if (properties.getOptionsSoundEnableMixerPan()) { + pan = calcPan((float) bp.getPaintX(), battleFieldWidth); + } + switch (bp.getState()) { + case FIRED: + if (properties.getOptionsSoundEnableGunshot()) { + playSound("gunshot", pan, calcBulletVolume(bp), 0); + } + break; + + case HIT_VICTIM: + if (properties.getOptionsSoundEnableBulletHit()) { + playSound("bullet hits robot", pan); + } + break; + + case HIT_BULLET: + if (properties.getOptionsSoundEnableBulletHit()) { + playSound("bullet hits bullet", pan); + } + break; + + case HIT_WALL: + // Currently, no sound + break; + + case EXPLODED: + if (properties.getOptionsSoundEnableRobotDeath()) { + playSound("robot death", pan); + } + break; + + default: + } + } + + /** + * Plays a robot sound depending on the robot's state + * + * @param robotPeer the robot peer + * @param battleFieldWidth the battle field width used for panning + */ + public void playRobotSound(IRobotSnapshot robotPeer, int battleFieldWidth) { + float pan = 0; + + if (properties.getOptionsSoundEnableMixerPan()) { + pan = calcPan((float) robotPeer.getX(), battleFieldWidth); + } + switch (robotPeer.getState()) { + case HIT_ROBOT: + if (properties.getOptionsSoundEnableRobotCollision()) { + playSound("robot collision", pan); + } + break; + + case HIT_WALL: + if (properties.getOptionsSoundEnableWallCollision()) { + playSound("wall collision", pan); + } + break; + + default: + } + } + + /** + * Plays the theme music once. + */ + public void playThemeMusic() { + if (isSoundEnabled()) { + playMusic("theme", 0); + } + } + + /** + * Plays the background music, which is looping forever until stopped. + */ + public void playBackgroundMusic() { + playMusic("background", -1); + } + + /** + * Stops the background music. + */ + public void stopBackgroundMusic() { + Clip c = getSounds().getSound("background"); + + if (c != null) { + c.stop(); + } + } + + /** + * Plays the end of battle music once. + */ + public void playEndOfBattleMusic() { + playMusic("endOfBattle", 0); + } + + /** + * Determines pan based on the relative position to the battlefield's width + * + * @param x the bullet or robot position + * @param width the battlefield's width + * @return the panning value, ranging from -1 to +1 + */ + private float calcPan(float x, float width) { + float semiWidth = width / 2; + + return (x - semiWidth) / semiWidth; + } + + /** + * Determines volume based on the bullets's energy + * + * @param bp the bullet peer + * @return the volume value, ranging from 0 to 1 + */ + private float calcBulletVolume(IBulletSnapshot bp) { + return (float) (bp.getPower() / robocode.Rules.MAX_BULLET_POWER); + } + + private class BattleObserver extends BattleAdaptor { + @Override + public void onBattleStarted(BattleStartedEvent event) { + if (isSoundEnabled()) { + playBackgroundMusic(); + } + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + stopBackgroundMusic(); + if (isSoundEnabled()) { + playEndOfBattleMusic(); + } + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + if (isSoundEnabled()) { + int battleFieldWidth = battleManager.getBattleProperties().getBattlefieldWidth(); + + for (IBulletSnapshot bp : event.getTurnSnapshot().getBullets()) { + if (bp.getFrame() == 0) { + playBulletSound(bp, battleFieldWidth); + } + } + + boolean playedRobotHitRobot = false; + + for (IRobotSnapshot rp : event.getTurnSnapshot().getRobots()) { + // Make sure that robot-hit-robot events do not play twice (one per colliding robot) + if (rp.getState() == RobotState.HIT_ROBOT) { + if (playedRobotHitRobot) { + continue; + } + playedRobotHitRobot = true; + } + + playRobotSound(rp, battleFieldWidth); + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.sound/src/main/resources/net/sf/robocode/sound/sounds/13831_adcbicycle_22.wav b/代码/workspace_robo4/robocode.sound/src/main/resources/net/sf/robocode/sound/sounds/13831_adcbicycle_22.wav new file mode 100644 index 0000000000000000000000000000000000000000..a721580df68c3da6f4d4df54ffc5b9d00d1a4ac6 GIT binary patch literal 74240 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.sound/src/main/resources/net/sf/robocode/sound/sounds/shellhit.wav b/代码/workspace_robo4/robocode.sound/src/main/resources/net/sf/robocode/sound/sounds/shellhit.wav new file mode 100644 index 0000000000000000000000000000000000000000..c077a22f520d2c76de28e4790bea05f1b8755b17 GIT binary patch literal 46496 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.tests.robots/.classpath b/代码/workspace_robo4/robocode.tests.robots/.classpath new file mode 100644 index 0000000..fa51e61 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.tests.robots/.project b/代码/workspace_robo4/robocode.tests.robots/.project new file mode 100644 index 0000000..e9d65ce --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/.project @@ -0,0 +1,17 @@ + + + robocode.tests.robots + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + robocode.samples + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.tests.robots/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.tests.robots/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.tests.robots/pom.xml b/代码/workspace_robo4/robocode.tests.robots/pom.xml new file mode 100644 index 0000000..4c61b0f --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + robocode.tests.robots + Robocode Tested Robots + + robocode + net.sf.robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + net.sf.robocode + robocode.samples + ${project.version} + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack-dependencies + test + + unpack-dependencies + + + sample*/** + ${project.build.directory}/classes + + + + + + + diff --git a/代码/workspace_robo4/robocode.tests.robots/robocode.tests.robots.iml b/代码/workspace_robo4/robocode.tests.robots/robocode.tests.robots.iml new file mode 100644 index 0000000..d39c655 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/robocode.tests.robots.iml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLonger.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLonger.java new file mode 100644 index 0000000..002d5f8 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLonger.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +import robocode.Robot; + + +/** + * @author Pavel Savara (original) + */ +public class NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLonger extends Robot { + @Override + public void run() { + while (true) { + ahead(1); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(1); // Move back 100 + turnGunRight(360); // Spin gun around + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/NoPackageShortName.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/NoPackageShortName.java new file mode 100644 index 0000000..ccc98f9 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/NoPackageShortName.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +import robocode.Robot; + + +/** + * @author Pavel Savara (original) + */ +public class NoPackageShortName extends Robot { + @Override + public void run() { + while (true) { + ahead(1); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(1); // Move back 100 + turnGunRight(360); // Spin gun around + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/robocode/BadNamespace.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/robocode/BadNamespace.java new file mode 100644 index 0000000..d18c589 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/robocode/BadNamespace.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package robocode; + + +/** + * @author Pavel Savara (original) + */ +public class BadNamespace extends Robot { + @Override + public void run() { + while (true) { + ahead(1); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(1); // Move back 100 + turnGunRight(360); // Spin gun around + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/Ahead.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/Ahead.java new file mode 100644 index 0000000..67d4bd8 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/Ahead.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; + + +/** + * @author Pavel Savara (original) + */ +public class Ahead extends AdvancedRobot { + + @Override + public void run() { + ahead(100); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BadFirePower.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BadFirePower.java new file mode 100644 index 0000000..7bdd393 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BadFirePower.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import robocode.Bullet; + + +/** + * From Bug 2410856 + * @author Pavel Savara (original) + */ +public class BadFirePower extends AdvancedRobot { + + public void run() { + while (true) { + Bullet bullet = setFireBullet(getTime() - 12.0); + + if (bullet != null) { + out.println(getTime() + " Bullet power: " + bullet.getPower()); + } else { + out.println(getTime() + " No bullet"); + } + execute(); + } + } + +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BattleLost.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BattleLost.java new file mode 100644 index 0000000..35226d9 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BattleLost.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.BattleEndedEvent; +import robocode.DeathEvent; +import robocode.Robot; +import robocode.WinEvent; + + +/** + * @author Pavel Savara (original) + */ +public class BattleLost extends Robot { + @Override + public void run() { + while (true) { + ahead(1); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(1); // Move back 100 + turnGunRight(360); // Spin gun around + } + } + + @Override + public void onWin(WinEvent e) { + out.println("Win!"); + } + + @Override + public void onDeath(DeathEvent e) { + out.println("Death!"); + } + + @Override + public void onBattleEnded(BattleEndedEvent event) { + out.println("BattleEnded!"); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BattleWin.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BattleWin.java new file mode 100644 index 0000000..b37d4c1 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BattleWin.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.*; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class BattleWin extends Robot { + + @Override + public void run() { + while (true) { + ahead(100); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(100); // Move back 100 + turnGunRight(360); // Spin gun around + } + } + + @Override + public void onScannedRobot(ScannedRobotEvent e) { + fire(1); + } + + @Override + public void onHitByBullet(HitByBulletEvent e) { + turnLeft(90 - e.getBearing()); + } + + @Override + public void onWin(WinEvent e) { + out.println("Win!"); + } + + @Override + public void onDeath(DeathEvent e) { + out.println("Death!"); + } + + @Override + public void onRoundEnded(RoundEndedEvent event) { + out.println("RoundEnded!"); + } + + @Override + public void onBattleEnded(BattleEndedEvent event) { + out.println("BattleEnded!"); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BodyTurnRate.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BodyTurnRate.java new file mode 100644 index 0000000..7bed86e --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/BodyTurnRate.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +/** + * @author Flemming N. Larsen (original) + */ +public class BodyTurnRate extends robocode.AdvancedRobot { + + public void run() { + // Test turn rate at all speed moving ahead and turning left + + setAhead(1000); + setTurnLeft(360); + executeAndDumpTurnRate9turns(); + + stopMoving(); + + // Test turn rate at all speed moving ahead and turning right + + setAhead(1000); + setTurnRight(360); + executeAndDumpTurnRate9turns(); + + stopMoving(); + + // Test turn rate at all speed moving back and turning right + + setBack(1000); + setTurnRight(360); + executeAndDumpTurnRate9turns(); + + stopMoving(); + + // Test turn rate at all speed moving back and turning left + + setBack(1000); + setTurnLeft(360); + executeAndDumpTurnRate9turns(); + + stopMoving(); + } + + private void executeAndDumpTurnRate9turns() { + for (int i = 0; i < 9; i++) { + executeAndDumpTurnRate(); + } + } + + private void executeAndDumpTurnRate() { + double lastHeading = getHeading(); + double lastVelocity = getVelocity(); + + execute(); + + double turnRate = robocode.util.Utils.normalRelativeAngleDegrees(getHeading() - lastHeading); + + out.println(getTime() + ": " + lastVelocity + ", " + turnRate); + } + + private void stopMoving() { + setAhead(0); + setTurnLeft(0); + + for (int i = 0; i < 6; i++) { + executeAndDumpTurnRate(); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorHttpAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorHttpAttack.java new file mode 100644 index 0000000..c124fea --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorHttpAttack.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; + + +/** + * @author Flemming N. Larsen (original) + */ +public class ConstructorHttpAttack extends AdvancedRobot { + + static final String HTTP_ADDR = "http://robocode.sourceforge.net/"; + + public ConstructorHttpAttack() { + try { + URL url = new URL(HTTP_ADDR); + + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + InputStream is = conn.getInputStream(); + + is.read(); + } + } catch (IOException e) { + e.printStackTrace(out); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorReflectionAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorReflectionAttack.java new file mode 100644 index 0000000..c884f07 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorReflectionAttack.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.*; + + +/** + * @author Flemming N. Larsen (original) + */ +public class ConstructorReflectionAttack extends robocode.AdvancedRobot { + + static ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + static { + try { + Field field = System.class.getField("out"); + + field.setAccessible(true); + Object obj = field.get(null); + Method method = obj.getClass().getMethod("print", new Class[] { String.class }); + + method.setAccessible(true); + method.invoke(obj, new Object[] { "Hello World" }); + + } catch (Exception e) { + // The stack trace from the exception is redirected to a temporary buffer, + // which is read and written out to the robot's output in the run() method. + + PrintStream ps = new PrintStream(baos); + + e.printStackTrace(ps); + ps.flush(); + } + } + + public void run() { + // Write out the buffered output + out.append(baos.toString()); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorSocketAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorSocketAttack.java new file mode 100644 index 0000000..a509dae --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ConstructorSocketAttack.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import java.io.*; +import java.net.*; + + +/** + * @author Flemming N. Larsen (original) + */ +public class ConstructorSocketAttack extends AdvancedRobot { + + static ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + static { + ServerSocket server = null; + Socket client = null; + + try { + server = new ServerSocket(9999); + client = server.accept(); + + InputStream is = new DataInputStream(client.getInputStream()); + OutputStream os = new PrintStream(client.getOutputStream()); + + os.write(1); + is.read(); + } catch (IOException e) { + // The stack trace from the exception is redirected to a temporary buffer, + // which is read and written out to the robot's output in the run() method. + + PrintStream ps = new PrintStream(baos); + + e.printStackTrace(ps); + ps.flush(); + } finally { + if (server != null) { + try { + server.close(); + } catch (IOException e) {} + } + if (client != null) { + try { + client.close(); + } catch (IOException e) {} + } + } + } + + public void run() { + // Write out the buffered output + out.append(baos.toString()); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/CustomEvents.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/CustomEvents.java new file mode 100644 index 0000000..7cc0415 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/CustomEvents.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import robocode.Condition; +import robocode.CustomEvent; +import robocode.ScannedRobotEvent; + + +/** + * @author Pavel Savara (original) + */ +public class CustomEvents extends AdvancedRobot { + @Override + public void run() { + + addCustomEvent(new Condition("onTick99", 99) { + public boolean test() { + return true; + } + }); + + addCustomEvent(new Condition("onTick30", 30) { + public boolean test() { + return true; + } + }); + + addCustomEvent(new Condition("onLowEnergy98", 98) { + public boolean test() { + return getEnergy() < 20; + } + }); + while (true) { + ahead(100); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(100); // Move back 100 + turnGunRight(360); // Spin gun around + } + } + + public void onCustomEvent(CustomEvent e) { + out.println(getTime() + " " + e.getCondition().getName()); + } + + public void onScannedRobot(ScannedRobotEvent e) { + out.println(getTime() + " onScannedRobot10"); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat1.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat1.java new file mode 100644 index 0000000..77ef9cc --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat1.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; + + +/** + * This test robot is based on Eric Simonton's 3 caveats on the RoboWiki + * where Robocode did not work as expected when updating the robot movements + * with deceleration. + * + * @author Flemming N. Larsen (original) + */ +public class DecelerationCaveat1 extends AdvancedRobot { + + @Override + public void run() { + setAhead(100); + for (int i = 1; i <= 8; i++) { + execute(); + } + + setAhead(22.8); + for (int i = 1; i <= 5; i++) { + execute(); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat2.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat2.java new file mode 100644 index 0000000..72beece --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat2.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; + + +/** + * This test robot is based on Eric Simonton's 3 caveats on the RoboWiki + * where Robocode did not work as expected when updating the robot movements + * with deceleration. + * + * @author Flemming N. Larsen (original) + */ +public class DecelerationCaveat2 extends AdvancedRobot { + + @Override + public void run() { + setAhead(100); + for (int i = 1; i <= 8; i++) { + execute(); + } + + setAhead(22.5); + for (int i = 1; i <= 6; i++) { + execute(); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat3.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat3.java new file mode 100644 index 0000000..3fa6a50 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DecelerationCaveat3.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; + + +/** + * This test robot is based on Eric Simonton's 3 caveats on the RoboWiki + * where Robocode did not work as expected when updating the robot movements + * with deceleration. + * + * @author Flemming N. Larsen (original) + */ +public class DecelerationCaveat3 extends AdvancedRobot { + + @Override + public void run() { + setAhead(100); + for (int i = 1; i <= 8; i++) { + execute(); + } + + setAhead(-200); + setMaxVelocity(7); + execute(); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DieFast.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DieFast.java new file mode 100644 index 0000000..580309c --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/DieFast.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.Robot; +import robocode.exception.RobotException; + + +/** + * @author Pavel Savara (original) + */ +public class DieFast extends Robot { + public void run() { + throw new RobotException(); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/EnvAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/EnvAttack.java new file mode 100644 index 0000000..d662243 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/EnvAttack.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; + + +/** + * @author Pavel Savara (original) + */ +public class EnvAttack extends AdvancedRobot { + @Override + public void run() { + + // attack + System.setProperty("NOSECURITY", "true"); + + // noinspection InfiniteLoopStatement + for (;;) { + turnLeft(100); + ahead(10); + turnLeft(100); + back(10); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/EventPriorityFilter.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/EventPriorityFilter.java new file mode 100644 index 0000000..5e7ab7a --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/EventPriorityFilter.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import robocode.HitWallEvent; +import robocode.ScannedRobotEvent; + + +/** + * @author Pavel Savara (original) + */ +public class EventPriorityFilter extends AdvancedRobot { + + @Override + public void run() { + // noinspection InfiniteLoopStatement + for (;;) { + ahead(10); // make sure we eventually hits a wall to receive onHitWall + } + } + + @Override + public void onScannedRobot(ScannedRobotEvent event) { + out.println("Scanned!!!"); // a robot was scanned -> problem! + } + + @Override + public void onHitWall(HitWallEvent e) { + // when the radar is turned here, at least another robot should be scanned + // but event should not be dispatched because we are in handler with higher priority + turnRadarRight(360); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FairPlay.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FairPlay.java new file mode 100644 index 0000000..1de6b99 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FairPlay.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.*; + + +/** + * @author Nat Pavasant (original) + */ +public class FairPlay extends AdvancedRobot { + public void run() { + setTurnRadarRightRadians(1d / 0d); + } + + public void onScannedRobot(ScannedRobotEvent e) { + setTurnRadarLeft(getRadarTurnRemaining()); + setTurnGunRightRadians( + robocode.util.Utils.normalRelativeAngle(e.getBearingRadians() + getHeadingRadians() - getGunHeadingRadians())); + setFire(3); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileOutputStreamAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileOutputStreamAttack.java new file mode 100644 index 0000000..689f1ae --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileOutputStreamAttack.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + + +/** + * @author Flemming N. Larsen (original) + */ +public class FileOutputStreamAttack extends AdvancedRobot { + + public void run() { + File file = null; + FileOutputStream fis = null; + try { + file = getDataFile("test"); + fis = new FileOutputStream(file); + fis.write(1); + } catch (IOException e) { + e.printStackTrace(out); + } finally { + if (fis != null) { + try { + fis.close(); + } catch (IOException ignore) {} + } + if (file != null) { + file.delete(); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileWriteSize.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileWriteSize.java new file mode 100644 index 0000000..ed89564 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/FileWriteSize.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import robocode.RobocodeFileOutputStream; +import java.io.File; +import java.io.IOException; + + +/** + * @author Flemming N. Larsen (original) + */ +public class FileWriteSize extends AdvancedRobot { + + public void run() { + out.println("Data directory: " + getDataDirectory()); + out.println("Data quota: " + getDataQuotaAvailable()); + + byte[] buf = new byte[100000]; + + File file = null; + RobocodeFileOutputStream rfos = null; + + try { + file = getDataFile("test"); + out.println("Data file: " + file.getCanonicalPath()); + file.delete(); + + rfos = new RobocodeFileOutputStream(file); + + for (int i = 0; i < 3; i++) { + rfos.write(buf); + } + } catch (IOException e) { + e.printStackTrace(out); + } finally { + if (rfos != null) { + try { + rfos.close(); + } catch (IOException e) { + e.printStackTrace(out); + } + } + if (file != null) { + if (!file.delete()) { + out.println("Could not delete the file: " + file); + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/GunHeat.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/GunHeat.java new file mode 100644 index 0000000..06ce045 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/GunHeat.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; + + +/** + * @author Pavel Savara (original) + * From bug 2405844 + */ +public class GunHeat extends AdvancedRobot { + + public void run() { + while (true) { + setFireBullet(3.0); + out.println(getTime() + " gunHeat after fire: " + getGunHeat()); + execute(); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/GunTurnRate.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/GunTurnRate.java new file mode 100644 index 0000000..3b265aa --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/GunTurnRate.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +/** + * @author Flemming N. Larsen (original) + */ +public class GunTurnRate extends robocode.AdvancedRobot { + public void run() { + setMaxTurnRate(5); + + setTurnGunLeft(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + setTurnGunRight(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + setTurnLeft(Double.POSITIVE_INFINITY); + setTurnGunLeft(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + setTurnRight(Double.POSITIVE_INFINITY); + setTurnGunRight(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + setMaxTurnRate(20); + + setTurnLeft(Double.POSITIVE_INFINITY); + setTurnGunLeft(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + setTurnRight(Double.POSITIVE_INFINITY); + setTurnGunRight(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + setAdjustGunForRobotTurn(false); + + setTurnRight(Double.POSITIVE_INFINITY); + setTurnGunLeft(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + + setTurnLeft(Double.POSITIVE_INFINITY); + setTurnGunRight(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + executeAndDumpTurnRate(); + } + + private void executeAndDumpTurnRate() { + double lastHeading = getGunHeading(); + + execute(); + + double turnRate = robocode.util.Utils.normalRelativeAngleDegrees(getGunHeading() - lastHeading); + + out.println(getTime() + ": " + turnRate); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/HttpAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/HttpAttack.java new file mode 100644 index 0000000..ea0c97c --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/HttpAttack.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; + + +/** + * @author Flemming N. Larsen (original) + */ +public class HttpAttack extends AdvancedRobot { + + static final String HTTP_ADDR = "http://robocode.sourceforge.net/"; + + public void run() { + try { + URL url = new URL(HTTP_ADDR); + + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + InputStream is = conn.getInputStream(); + + is.read(); + } + } catch (IOException e) { + e.printStackTrace(out); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/InteruptibleEvent.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/InteruptibleEvent.java new file mode 100644 index 0000000..d3a306f --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/InteruptibleEvent.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import robocode.HitWallEvent; +import robocode.ScannedRobotEvent; + + +/** + * Based on bug 2212289. + * + * Robot provided for the test named TestScanForRobotsWhenHitWall, which tests if onScannedRobot() + * is called when the radar is turned from within a onHitWall() event. + * + * @author Flemming N. Larsen (original) + */ +public class InteruptibleEvent extends AdvancedRobot { + + @Override + public void run() { + setEventPriority("HitWallEvent", getEventPriority("ScannedRobotEvent")); // make same as scan + + // noinspection InfiniteLoopStatement + for (;;) { + ahead(10); // make sure we eventually hits a wall to receive onHitWall + } + } + + @Override + public void onScannedRobot(ScannedRobotEvent event) { + out.println("Scanned!!!"); // a robot was scanned -> success! + } + + @Override + public void onHitWall(HitWallEvent e) { + setInterruptible(true); // make sure that the event handler can be interrupted and restarted + turnRadarRight(360); // when the radar is turned here, at least another robot should be scanned + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/JuniorEvents.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/JuniorEvents.java new file mode 100644 index 0000000..cd126f8 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/JuniorEvents.java @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.*; +import robocode.Event; +import robocode.robotinterfaces.IBasicEvents; +import robocode.robotinterfaces.IJuniorRobot; +import robocode.robotinterfaces.peer.IBasicRobotPeer; +import robocode.util.Utils; + +import java.awt.*; +import java.io.PrintStream; +import java.util.HashMap; +import java.util.Map; + + +/** + * @author Pavel Savara (original) + */ +public class JuniorEvents implements IJuniorRobot, IBasicEvents, Runnable { + + IBasicRobotPeer peer; + PrintStream out; + final Map counts = new HashMap(); + Bullet bullet; + + public void run() { + // noinspection InfiniteLoopStatement + while (true) { + peer.move(100); // Move ahead 100 + peer.turnGun(Math.PI * 2); // Spin gun around + peer.move(-100); // Move back 100 + peer.turnGun(Math.PI * 2); // Spin gun around + } + } + + public Runnable getRobotRunnable() { + return this; + } + + public IBasicEvents getBasicEventListener() { + return this; + } + + public void setPeer(IBasicRobotPeer peer) { + this.peer = peer; + } + + public void setOut(PrintStream out) { + this.out = out; + } + + public void onStatus(StatusEvent event) { + count(event); + final Graphics2D g = peer.getGraphics(); + + g.setColor(Color.orange); + g.drawOval((int) (peer.getX() - 55), (int) (peer.getY() - 55), 110, 110); + } + + public void onBulletHit(BulletHitEvent event) { + count(event); + } + + public void onBulletHitBullet(BulletHitBulletEvent event) { + count(event); + } + + public void onBulletMissed(BulletMissedEvent event) { + count(event); + } + + public void onDeath(DeathEvent event) { + count(event); + } + + public void onHitByBullet(HitByBulletEvent event) { + count(event); + } + + public void onHitRobot(HitRobotEvent event) { + count(event); + } + + public void onHitWall(HitWallEvent event) { + count(event); + } + + public void onRobotDeath(RobotDeathEvent event) { + count(event); + } + + public void onWin(WinEvent event) { + count(event); + + // this is tested output + for (Map.Entry s : counts.entrySet()) { + out.println(s.getKey() + " " + s.getValue()); + } + out.println("last bullet heading " + bullet.getHeadingRadians()); + } + + public void onScannedRobot(ScannedRobotEvent event) { + count(event); + + // Turn gun to point at the scanned robot + peer.turnGun(Utils.normalAbsoluteAngle(peer.getBodyHeading() + event.getBearingRadians() - peer.getGunHeading())); // + + // Fire! + double power = 1; + + Bullet firedBullet = peer.fire(power); + + if (firedBullet != null) { + this.bullet = firedBullet; + } + } + + private void count(Event event) { + final String name = event.getClass().getName(); + Integer curr = counts.get(name); + + if (curr == null) { + curr = 0; + } + counts.put(name, curr + 1); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/MaxTurnRate.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/MaxTurnRate.java new file mode 100644 index 0000000..858e625 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/MaxTurnRate.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +/** + * @author Flemming N. Larsen (original) + */ +public class MaxTurnRate extends robocode.AdvancedRobot { + public void run() { + + setTurnLeft(Double.POSITIVE_INFINITY); + + for (int i = 0; i < 13; i++) { + setMaxTurnRate(i); + executeAndDumpTurnRate(); + } + + setTurnRight(Double.POSITIVE_INFINITY); + + for (int i = 0; i < 13; i++) { + setMaxTurnRate(i); + executeAndDumpTurnRate(); + } + } + + private void executeAndDumpTurnRate() { + double lastHeading = getHeading(); + + execute(); + + double turnRate = robocode.util.Utils.normalRelativeAngleDegrees(getHeading() - lastHeading); + + out.println(getTime() + ": " + getVelocity() + ", " + turnRate); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/MaxVelocity.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/MaxVelocity.java new file mode 100644 index 0000000..fec7a11 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/MaxVelocity.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +/** + * @author Flemming N. Larsen (original) + */ +public class MaxVelocity extends robocode.AdvancedRobot { + + public void run() { + for (;;) { + int time = (int) getTime(); + + if (time < 200) { + out.println(time + ": " + getVelocity()); + } + + switch (time) { + case 1: + setAhead(1000); + break; + + case 20: + setBack(1000); + break; + + case 40: + setMaxVelocity(4.2); + setAhead(1000); + break; + + case 60: + setBack(1000); + break; + + case 80: + setMaxVelocity(100); + setAhead(1000); + break; + + case 100: + setBack(1000); + break; + + case 120: + setMaxVelocity(-2); + setAhead(1000); + break; + + case 140: + setBack(1000); + break; + + case 160: + setMaxVelocity(0); + setAhead(1000); + break; + + case 180: + setBack(1000); + break; + } + execute(); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/PrivateConstructor.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/PrivateConstructor.java new file mode 100644 index 0000000..505eb51 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/PrivateConstructor.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.Robot; + + +/** + * @author Pavel Savara (original) + */ +public class PrivateConstructor extends Robot { + private PrivateConstructor() {// private + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RadarTurnRateAndSetAdjust.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RadarTurnRateAndSetAdjust.java new file mode 100644 index 0000000..6e9ddf1 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RadarTurnRateAndSetAdjust.java @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +/** + * @author Flemming N. Larsen (original) + */ +public class RadarTurnRateAndSetAdjust extends robocode.AdvancedRobot { + public void run() { + // -- Turn 1 -- + setTurnRadarRight(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. radar turn rate = 45 + + // -- Turn 2 -- + setTurnGunRight(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. gun + radar turn rate = 20 + 45 = 65 + + // -- Turn 3 -- + setTurnRight(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. robot + gun + radar turn rate = 10 + 20 + 45 = 75 + + // -- Turn 4 -- + setTurnRadarLeft(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. robot + gun - radar turn rate = 10 + 20 - 45 = -15 + + // -- Turn 5 -- + setTurnGunLeft(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. robot + gun - radar turn rate = 10 - 20 - 45 = -55 + + // -- Turn 6 -- + setTurnLeft(1000); + executeAndDumpTurnRate(); + // Expected turn rate: max. robot + gun - radar turn rate = -10 - 20 - 45 = -75 + + // -- Turn 7 -- + setAdjustRadarForGunTurn(false); + setTurnRight(14); + setTurnGunRight(15); + setTurnRadarRight(7); + executeAndDumpTurnRate(); + // Expected turn rate: robot + gun + radar turn rate = 14 + 15 + 7 = 32 + + // -- Turn 8 -- + setAdjustGunForRobotTurn(false); + setAdjustRadarForRobotTurn(false); + setAdjustRadarForGunTurn(true); + setTurnRight(14); + setTurnGunLeft(15); + setTurnRadarRight(7); + executeAndDumpTurnRate(); + // Expected turn rate: robot (max) + radar turn rate (ignoring gun turn rate, but not robot turn rate) = 10 + 7 = 17 + + // -- Turn 9 -- + setAdjustGunForRobotTurn(false); + setAdjustRadarForRobotTurn(true); + setAdjustRadarForGunTurn(true); + setTurnRight(14); + setTurnGunLeft(15); + setTurnRadarRight(35); + executeAndDumpTurnRate(); + // Expected turn rate: robot turn rate (ignoring both gun and body turn rate) = 35 + + // -- Turn 10 -- + setAdjustGunForRobotTurn(false); + setAdjustRadarForRobotTurn(false); + setAdjustRadarForGunTurn(true); + setTurnRight(14); + setTurnGunLeft(15); + setTurnRadarLeft(7); + executeAndDumpTurnRate(); + // Expected turn rate: robot (max) + radar turn rate (ignoring gun turn rate, but not robot turn rate) = 10 - 7 = 3 + + // -- Turn 11 -- + setAdjustGunForRobotTurn(false); + setAdjustRadarForRobotTurn(true); + setAdjustRadarForGunTurn(true); + setTurnRight(4); + setTurnGunRight(60); + setTurnRadarLeft(100); + executeAndDumpTurnRate(); + // Expected turn rate: robot (max) turn rate (ignoring both gun and body turn rate) = -20 + + // -- Turn 12 -- + setAdjustGunForRobotTurn(false); + setAdjustRadarForRobotTurn(false); + setAdjustRadarForGunTurn(true); + setTurnRight(Double.POSITIVE_INFINITY); + setTurnGunRight(Double.POSITIVE_INFINITY); + setTurnRadarRight(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + // Expected turn rate: setAdjusts are all ignored, max. robot + gun + radar turn rate = 10 + 20 + 45 = 75 + + // -- Turn 13 -- + setAdjustGunForRobotTurn(true); + setAdjustRadarForRobotTurn(false); + setAdjustRadarForGunTurn(true); + setTurnRight(Double.NEGATIVE_INFINITY); + setTurnGunRight(Double.NEGATIVE_INFINITY); + setTurnRadarRight(Double.NEGATIVE_INFINITY); + executeAndDumpTurnRate(); + // Expected turn rate: setAdjusts are all ignored, max. robot + gun + radar turn rate = -10 - 20 - 45 = -75 + + // -- Turn 14 -- + setAdjustGunForRobotTurn(true); + setAdjustRadarForRobotTurn(true); + setAdjustRadarForGunTurn(true); + setTurnLeft(Double.NEGATIVE_INFINITY); + setTurnGunLeft(Double.NEGATIVE_INFINITY); + setTurnRadarLeft(Double.POSITIVE_INFINITY); + executeAndDumpTurnRate(); + // Expected turn rate: setAdjusts are all ignored, max. robot + gun + radar turn rate = -(-10) - (-20) - 45 = -15 + } + + private void executeAndDumpTurnRate() { + double lastHeading = getRadarHeading(); + + execute(); + + double turnRate = robocode.util.Utils.normalRelativeAngleDegrees(getRadarHeading() - lastHeading); + + out.println(getTime() + ": " + turnRate); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/Random.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/Random.java new file mode 100644 index 0000000..c9415b5 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/Random.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.Robot; + + +/** + * @author Pavel Savara (original) + */ +public class Random extends Robot { + + @Override + public void run() { + + while (true) { + ahead(100 * Math.random()); + turnRight(180 * Math.random()); + back(100 * Math.random()); + turnLeft(360 * Math.random()); + } + } +} + diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RateControl.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RateControl.java new file mode 100644 index 0000000..bf97c6f --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RateControl.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.RateControlRobot; + + +/** + * @author Joshua Galecki (original) + */ +public class RateControl extends RateControlRobot { + @Override + public void run() { + for (int turnNumber = 0; turnNumber < 80; turnNumber++) { + if (turnNumber == 0) { + setTurnRate(4.5); + } else if (turnNumber == 10) { + setTurnRate(-9); + } else if (turnNumber == 20) { + setTurnRate(0); + setVelocityRate(2); + } else if (turnNumber == 25) { + setVelocityRate(-8); + } else if (turnNumber == 35) { + setVelocityRate(0); + setGunRotationRate(9); + } else if (turnNumber == 45) { + setGunRotationRate(-4.5); + } else if (turnNumber == 55) { + setGunRotationRate(0); + setRadarRotationRate(9); + } else if (turnNumber == 65) { + setRadarRotationRate(-4.5); + } else if (turnNumber == 75) { + setRadarRotationRate(0); + } + execute(); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ReflectionAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ReflectionAttack.java new file mode 100644 index 0000000..37355c0 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ReflectionAttack.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import java.lang.reflect.*; + + +/** + * @author Flemming N. Larsen (original) + */ +public class ReflectionAttack extends robocode.AdvancedRobot { + + public void run() { + try { + Field field = System.class.getField("out"); + + field.setAccessible(true); + Object obj = field.get(null); + Method method = obj.getClass().getMethod("print", new Class[] { String.class }); + + method.setAccessible(true); + method.invoke(obj, new Object[] { "Hello World" }); + + } catch (Exception e) { + e.printStackTrace(out); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ReverseDirection.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ReverseDirection.java new file mode 100644 index 0000000..de7cc0b --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/ReverseDirection.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +/** + * @author Flemming N. Larsen (original) + */ +public class ReverseDirection extends robocode.AdvancedRobot { + public void run() { + setAhead(Double.POSITIVE_INFINITY); + setMaxVelocity(1.0); + execute(); + // robot has a positive velocity of 1.0 + + out.println(getVelocity()); + + setMaxVelocity(0.5); + setAhead(Double.NEGATIVE_INFINITY); + execute(); + // robot should have a negative velocity of -0.5 + + out.println(getVelocity()); + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RobotDeathEvents.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RobotDeathEvents.java new file mode 100644 index 0000000..d057416 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/RobotDeathEvents.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.DeathEvent; +import robocode.RobotDeathEvent; +import robocode.AdvancedRobot; + + +/** + * @author Flemming N. Larsen (original) + */ +public class RobotDeathEvents extends AdvancedRobot { + private boolean dead; + private long enemyCount; + + public void run() { + enemyCount = getOthers(); + while (!dead) { + if (enemyCount != getOthers()) { + throw new RuntimeException("enemyCount != getOthers()"); + } + execute(); + } + } + + public void onRobotDeath(RobotDeathEvent e) { + enemyCount--; + } + + public void onDeath(DeathEvent e) { + dead = true; + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/SkipTurns.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/SkipTurns.java new file mode 100644 index 0000000..09b562e --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/SkipTurns.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import robocode.SkippedTurnEvent; +import robocode.StatusEvent; + + +/** + * @author Pavel Savara (original) + */ +public class SkipTurns extends AdvancedRobot { + private volatile int skipped = 0; + + static final int LIMIT = 5; + + @Override + public void run() { + // noinspection InfiniteLoopStatement + for (;;) { + if (skipped > LIMIT) { + throw new Error("satisfied, end battle please"); + } + turnLeft(10); + if (skipped > LIMIT) { + // satisfied, end battle please + throw new Error(); + } + ahead(1); + if (skipped > LIMIT) { + // satisfied, end battle please + throw new Error(); + } + turnLeft(10); + if (skipped > LIMIT) { + // satisfied, end battle please + throw new Error(); + } + back(1); + } + } + + @Override + public void onStatus(StatusEvent e) { + out.println("live"); + slowResponse(); + } + + @Override + public void onSkippedTurn(SkippedTurnEvent event) { + out.println("Skipped!!!"); + + skipped++; + } + + private final Object w = new Object(); + + private void slowResponse() { + + synchronized (w) { + try { + if (skipped > 3) { + w.wait(3000); + } else { + w.wait(130); + } + } catch (InterruptedException e) { + // eat interrupt + e.printStackTrace(out); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/SocketAttack.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/SocketAttack.java new file mode 100644 index 0000000..5109c10 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/SocketAttack.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.AdvancedRobot; +import java.io.*; +import java.net.*; + + +/** + * @author Flemming N. Larsen (original) + */ +public class SocketAttack extends AdvancedRobot { + + public void run() { + ServerSocket server = null; + Socket client = null; + + try { + server = new ServerSocket(9999); + client = server.accept(); + + InputStream is = new DataInputStream(client.getInputStream()); + OutputStream os = new PrintStream(client.getOutputStream()); + + os.write(1); + is.read(); + } catch (IOException e) { + e.printStackTrace(out); + } finally { + if (server != null) { + try { + server.close(); + } catch (IOException e) {} + } + if (client != null) { + try { + client.close(); + } catch (IOException e) {} + } + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/TooLongNameThisIsReallyTooLongName.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/TooLongNameThisIsReallyTooLongName.java new file mode 100644 index 0000000..77cb808 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/TooLongNameThisIsReallyTooLongName.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.Robot; + + +/** + * @author Pavel Savara (original) + */ +public class TooLongNameThisIsReallyTooLongName extends Robot { + @Override + public void run() { + while (true) { + ahead(1); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(1); // Move back 100 + turnGunRight(360); // Spin gun around + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/WatchBullets.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/WatchBullets.java new file mode 100644 index 0000000..16bcee8 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tested/robots/WatchBullets.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tested.robots; + + +import robocode.*; +import static robocode.util.Utils.normalRelativeAngle; + + +/** + * @author Pavel Savara (original) + */ +public class WatchBullets extends AdvancedRobot { + public void run() { + while (true) { + ahead(100); + turnGunRight(360); + back(100); + turnGunRight(360); + } + } + + Bullet bullet; + + public void onStatus(StatusEvent event) { + dump(); + } + + @Override + public void onScannedRobot(ScannedRobotEvent e) { + // Calculate exact location of the robot + double absoluteBearing = getHeading() + e.getBearing(); + double bearingFromGun = normalRelativeAngle(absoluteBearing - getGunHeading()); + + // If it's close enough, fire! + if (Math.abs(bearingFromGun) <= 3) { + turnGunRight(bearingFromGun); + // We check gun heat here, because calling fire() + // uses a turn, which could cause us to lose track + // of the other robot. + if (getGunHeat() == 0 && bullet == null) { + final Bullet lbullet = fireBullet(Math.min(3 - Math.abs(bearingFromGun), getEnergy() - .1)); + + bullet = lbullet; + } + } // otherwise just set the gun to turn. + // Note: This will have no effect until we call scan() + else { + turnGunRight(bearingFromGun); + } + // Generates another scan event if we see a robot. + // We only need to call this if the gun (and therefore radar) + // are not turning. Otherwise, scan is called automatically. + if (bearingFromGun == 0) { + scan(); + } + } + + private void dump() { + if (bullet != null) { + out.println( + getTime() + " " + bullet.getX() + " " + bullet.getY() + " " + bullet.getHeading() + " " + + bullet.isActive()); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/java/tooLongNamespaceThisIsReallyTooLongNamespace/TooLongNamespace.java b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tooLongNamespaceThisIsReallyTooLongNamespace/TooLongNamespace.java new file mode 100644 index 0000000..0fc2fb2 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/java/tooLongNamespaceThisIsReallyTooLongNamespace/TooLongNamespace.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package tooLongNamespaceThisIsReallyTooLongNamespace; + + +import robocode.Robot; + + +/** + * @author Pavel Savara (original) + */ +public class TooLongNamespace extends Robot { + @Override + public void run() { + while (true) { + ahead(1); // Move ahead 100 + turnGunRight(360); // Spin gun around + back(1); // Move back 100 + turnGunRight(360); // Spin gun around + } + } +} diff --git a/代码/workspace_robo4/robocode.tests.robots/src/main/resources/tested/robots/TestTeam.team b/代码/workspace_robo4/robocode.tests.robots/src/main/resources/tested/robots/TestTeam.team new file mode 100644 index 0000000..fd3a223 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests.robots/src/main/resources/tested/robots/TestTeam.team @@ -0,0 +1,7 @@ +#Robocode robot team +#Sat Oct 25 22:23:58 CEST 2008 +team.members=sampleteam.MyFirstLeader,sampleteam.MyFirstDroid,sample.Fire +team.author.name= +robocode.version=unknown +uuid=8abd63e8-1156-4fb4-a81f-eb10fca9596d +team.description=testteam diff --git a/代码/workspace_robo4/robocode.tests/.classpath b/代码/workspace_robo4/robocode.tests/.classpath new file mode 100644 index 0000000..54fd109 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/.classpath @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.tests/.project b/代码/workspace_robo4/robocode.tests/.project new file mode 100644 index 0000000..96f238f --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/.project @@ -0,0 +1,22 @@ + + + robocode.tests + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + robocode.tests.robots + robocode.samples + robocode.core + robocode.host + robocode.battle + robocode.repository + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.tests/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.tests/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.tests/config/robocode.properties b/代码/workspace_robo4/robocode.tests/config/robocode.properties new file mode 100644 index 0000000..ad5840f --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/config/robocode.properties @@ -0,0 +1,3 @@ +#Robocode Properties +#Thu Mar 12 00:15:08 CET 2009 +robocode.cpu.constant=9994115 diff --git a/代码/workspace_robo4/robocode.tests/pom.xml b/代码/workspace_robo4/robocode.tests/pom.xml new file mode 100644 index 0000000..d84174f --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + robocode.tests + Robocode Tests + + net.sf.robocode + robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + net.sf.robocode + robocode.tests.robots + ${project.version} + + + junit + junit + 4.11 + + + net.sf.robocode + robocode.core + ${project.version} + test + + + net.sf.robocode + robocode.samples + ${project.version} + test + + + net.sf.robocode + robocode.host + ${project.version} + test + + + net.sf.robocode + robocode.battle + ${project.version} + test + + + net.sf.robocode + robocode.repository + ${project.version} + test + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.tests/robocode.tests.iml b/代码/workspace_robo4/robocode.tests/robocode.tests.iml new file mode 100644 index 0000000..7cffb25 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/robocode.tests.iml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/RobocodeTestBed.java b/代码/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/RobocodeTestBed.java new file mode 100644 index 0000000..ad034fb --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/main/java/net/sf/robocode/test/helpers/RobocodeTestBed.java @@ -0,0 +1,209 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.helpers; + + +import net.sf.robocode.io.Logger; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import robocode.control.*; +import robocode.control.events.*; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.util.Utils; + +import java.io.File; +import java.io.IOException; +import java.util.Random; + + +/** + * @author Pavel Savara (original) + */ +public abstract class RobocodeTestBed extends BattleAdaptor { + protected static final IRobocodeEngine engine; + protected final BattlefieldSpecification battleFieldSpec = new BattlefieldSpecification(); + protected static int errors = 0; + protected static StringBuilder errorText = new StringBuilder(); + protected static int messages = 0; + protected static String robotsPath; + + public static boolean isDumpingPositions = false; + public static boolean isDumpingTurns = false; + public static boolean isDumpingOutput = true; + public static boolean isDumpingErrors = true; + public static boolean isDumpingMessages = true; + public static boolean hasJavaNetURLPermission = isClassAvailable("java.net.URLPermission"); + + private static boolean isClassAvailable(String name) { + try { + return Class.forName(name) != null; + } catch (ClassNotFoundException e) { + return false; + } + } + + static { + System.setProperty("EXPERIMENTAL", "true"); + System.setProperty("TESTING", "true"); + System.setProperty("WORKINGDIRECTORY", "target/test-classes"); + try { + String currentDirAbsolutePath = new File("").getAbsolutePath(); + if (currentDirAbsolutePath.endsWith("robocode.tests")) { + robotsPath = new File("../robocode.tests.robots").getCanonicalPath(); + } else if (currentDirAbsolutePath.endsWith("robocode.dotnet.tests")) { + robotsPath = new File("../../../robocode.tests.robots").getCanonicalPath(); + } else if (new File("robocode.tests.robots").isDirectory()) { + robotsPath = new File("robocode.tests.robots").getCanonicalPath(); + } else { + throw new Error("Unknown directory: " + currentDirAbsolutePath); + } + } catch (IOException e) { + e.printStackTrace(Logger.realErr); + } + System.setProperty("ROBOTPATH", robotsPath + "/target/classes"); + + engine = new RobocodeEngine(new BattleAdaptor() { + public void onBattleMessage(BattleMessageEvent event) { + if (isDumpingMessages) { + Logger.realOut.println(event.getMessage()); + } + messages++; + } + + public void onBattleError(BattleErrorEvent event) { + if (isDumpingErrors) { + Logger.realErr.println(event.getError()); + } + errorText.append("----------err #"); + errorText.append(errors); + errorText.append("--------------------------------------------------\n"); + errorText.append(event.getError()); + errorText.append("\n"); + errors++; + } + }); + } + + public RobocodeTestBed() { + // silent when running in maven + if (System.getProperty("surefire.test.class.path", null) != null) { + isDumpingOutput = false; + isDumpingErrors = false; + isDumpingMessages = false; + } + errors = 0; + messages = 0; + } + + public void onTurnEnded(TurnEndedEvent event) { + if (isDumpingTurns) { + Logger.realOut.println("turn " + event.getTurnSnapshot().getTurn()); + } + for (IRobotSnapshot robot : event.getTurnSnapshot().getRobots()) { + if (isDumpingPositions) { + Logger.realOut.print(robot.getVeryShortName()); + Logger.realOut.print(" X:"); + Logger.realOut.print(robot.getX()); + Logger.realOut.print(" Y:"); + Logger.realOut.print(robot.getY()); + Logger.realOut.print(" V:"); + Logger.realOut.print(robot.getVelocity()); + Logger.realOut.println(); + } + if (isDumpingOutput) { + Logger.realOut.print(robot.getOutputStreamSnapshot()); + } + } + } + + public void onBattleStarted(BattleStartedEvent event) { + if (isDeterministic() && isCheckOnBattleStart()) { + final Random random = Utils.getRandom(); + + if (event.getRobotsCount() == 2) { + Assert.assertNear(0.98484154, random.nextDouble()); + } + } + } + + public abstract String getRobotNames(); + + public int getNumRounds() { + return 1; + } + + public String getInitialPositions() { + return null; + } + + public int getExpectedRobotCount(String robotList) { + return robotList.split("[\\s,;]+").length; + } + + public boolean isDeterministic() { + return true; + } + + public boolean isCheckOnBattleStart() { + return false; + } + + @Before + public void setup() { + engine.addBattleListener(this); + if (isDeterministic()) { + RandomFactory.resetDeterministic(0); + if (isCheckOnBattleStart()) { + Assert.assertNear(0.730967, RandomFactory.getRandom().nextDouble()); + } + } + errors = 0; + errorText = new StringBuilder(); + messages = 0; + } + + @After + public void tearDown() { + engine.removeBattleListener(this); + } + + @Test + public void run() { + runSetup(); + runBattle(getRobotNames(), getNumRounds(), getInitialPositions()); + runTeardown(); + final int expectedErrors = getExpectedErrors(); + + if (errors != expectedErrors) { + throw new AssertionError( + "Number of errors " + errors + " is different than expected " + expectedErrors + "\n" + errorText + + "======================================================================"); + } + } + + protected int getExpectedErrors() { + return 0; + } + + protected void runSetup() {} + + protected void runTeardown() {} + + protected void runBattle(String robotList, int numRounds, String initialPositions) { + final RobotSpecification[] robotSpecifications = engine.getLocalRepository(robotList); + + if (getExpectedRobotCount(robotList) > 0) { + Assert.assertNotNull("Robot were not loaded", robotSpecifications); + Assert.assertEquals("Robot were not loaded", getExpectedRobotCount(robotList), robotSpecifications.length); + engine.runBattle(new BattleSpecification(numRounds, battleFieldSpec, robotSpecifications), initialPositions, + true); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/core/util/AlphanumericComparatorTest.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/core/util/AlphanumericComparatorTest.java new file mode 100644 index 0000000..255fbd2 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/core/util/AlphanumericComparatorTest.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.core.util; + + +import java.util.Arrays; + +import net.sf.robocode.util.AlphanumericComparator; + +import org.junit.Assert; +import org.junit.Test; + + +/** + * @author Flemming N. Larsen (original) + */ +public class AlphanumericComparatorTest { + @Test + public void correctSorting() { + + // Our unsorted strings that must be sorted + final String[] unsortedStrings = { + null, "", " ", "alpha2", "alpha1", "bEtA", "BeTa", "alpha", "Alpha2", "Alpha1", "Alpha", "1.2", "1.22", + "1.22A", "1.3", "2.10a.1", "2.1.1", "2.10", "2.1a", "2.10.2", "1c", "1h", "1p", "alpha", "beta", "alPHA", + "beTA", "ALpha", "BEta", "ALPHA", "BETA" + }; + + // The expected result, when the unsorted strings have been sorted correctly + final String[] correctlySortedStrings = { + "1.2", "1.3", "1.22A", "1.22", "1c", "1h", "1p", "2.1.1", "2.1a", "2.10.2", "2.10a.1", "2.10", " ", "ALPHA", + "ALpha", "Alpha1", "Alpha2", "Alpha", "alPHA", "alpha1", "alpha2", "alpha", "alpha", "BETA", "BEta", "BeTa", + "bEtA", "beTA", "beta", "", null + }; + + // Make sure the input and expected output string arrays have the same length + Assert.assertEquals(unsortedStrings.length, correctlySortedStrings.length); + + // Sort the unsorted strings + Arrays.sort(unsortedStrings, new AlphanumericComparator()); + + // Check the result against our expected result + boolean sortedCorrectly = true; + + for (int i = 0; i < unsortedStrings.length; i++) { + String str1 = unsortedStrings[i]; + String str2 = correctlySortedStrings[i]; + + if (!(str1 == null && str2 == null) && !str1.equals(str2)) { + sortedCorrectly = false; + break; + } + } + Assert.assertTrue(sortedCorrectly); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/host/security/RobotClassLoaderTest.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/host/security/RobotClassLoaderTest.java new file mode 100644 index 0000000..13cd254 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/host/security/RobotClassLoaderTest.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.host.security; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.core.EngineClassLoader; +import net.sf.robocode.host.security.RobotClassLoader; +import net.sf.robocode.security.HiddenAccess; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + + +/** + * @author Pavel Savara (original) + */ +public class RobotClassLoaderTest { + static URL classPath; + final String badRobot = "tested.robots.IncludeNamespaceAttack"; + final String goodRobot = "tested.robots.Ahead"; + + @BeforeClass + public static void init() throws IOException { + HiddenAccess.initContainer(); + classPath = new File("../robocode.tests.robots/target/classes").getCanonicalFile().toURI().toURL(); + } + + @Test + public void engineAllowed() throws ClassNotFoundException { + final ClassLoader engineLoader = new EngineClassLoader(ClassLoader.getSystemClassLoader()); + + engineLoader.loadClass("net.sf.robocode.host.proxies.BasicRobotProxy"); + final Class c = engineLoader.loadClass("net.sf.robocode.host.proxies.BasicRobotProxy"); + + Assert.assertEquals(engineLoader, c.getClassLoader()); + } + + @Test + public void robotAllowed() throws ClassNotFoundException { + RobotClassLoader cl = new RobotClassLoader(classPath, goodRobot); + final Class c = cl.loadClass("robocode.Robot", true); + + Assert.assertEquals(Container.systemLoader, c.getClassLoader()); + } + + @Test + public void robotAllowedMain() throws ClassNotFoundException { + RobotClassLoader cl = new RobotClassLoader(classPath, goodRobot); + final Class c = cl.loadRobotMainClass(true); + + Assert.assertEquals(cl, c.getClassLoader()); + } + + @Test(expected = ClassNotFoundException.class) + public void robotBlockedBad() throws ClassNotFoundException { + RobotClassLoader cl = new RobotClassLoader(classPath, badRobot); + + cl.loadRobotMainClass(true); + } + + @Test(expected = ClassNotFoundException.class) + public void robotBlockedRobocode() throws ClassNotFoundException { + RobotClassLoader cl = new RobotClassLoader(classPath, goodRobot); + + cl.loadClass("net.sf.robocode.host.proxies.BasicRobotProxy"); + } + + @Test(expected = ClassNotFoundException.class) + public void robotBlockedControl() throws ClassNotFoundException { + RobotClassLoader cl = new RobotClassLoader(classPath, goodRobot); + + cl.loadClass("robocode.control.RobocodeEngine"); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestAcceleration.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestAcceleration.java new file mode 100644 index 0000000..4afd20c --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestAcceleration.java @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; + +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class TestAcceleration extends RobocodeTestBed { + + private double[] startX = new double[3]; + private double[] startY = new double[3]; + + @Test + public void run() { + super.run(); + } + + @Override + public String getRobotNames() { + return "tested.robots.DecelerationCaveat1,tested.robots.DecelerationCaveat2,tested.robots.DecelerationCaveat3"; + } + + @Override + public String getInitialPositions() { + return "(50,50,0), (100,50,0), (150,50,0)"; // Make sure the robots do not collide! + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + IRobotSnapshot caveat1 = event.getTurnSnapshot().getRobots()[0]; + IRobotSnapshot caveat2 = event.getTurnSnapshot().getRobots()[1]; + IRobotSnapshot caveat3 = event.getTurnSnapshot().getRobots()[2]; + + switch (event.getTurnSnapshot().getTurn()) { + case 1: + resetStartPositions(event.getTurnSnapshot()); + + Assert.assertNear(1, caveat1.getVelocity()); + Assert.assertNear(1, caveat2.getVelocity()); + Assert.assertNear(1, caveat3.getVelocity()); + + Assert.assertNear(1 - 1, distance(0, caveat1)); + Assert.assertNear(1 - 1, distance(1, caveat2)); + Assert.assertNear(1 - 1, distance(2, caveat3)); + break; + + case 2: + Assert.assertNear(2, caveat1.getVelocity()); + Assert.assertNear(2, caveat2.getVelocity()); + Assert.assertNear(2, caveat3.getVelocity()); + + Assert.assertNear(3 - 1, distance(0, caveat1)); + Assert.assertNear(3 - 1, distance(1, caveat2)); + Assert.assertNear(3 - 1, distance(2, caveat3)); + break; + + case 3: + Assert.assertNear(3, caveat1.getVelocity()); + Assert.assertNear(3, caveat2.getVelocity()); + Assert.assertNear(3, caveat3.getVelocity()); + + Assert.assertNear(6 - 1, distance(0, caveat1)); + Assert.assertNear(6 - 1, distance(1, caveat2)); + Assert.assertNear(6 - 1, distance(2, caveat3)); + break; + + case 4: + Assert.assertNear(4, caveat1.getVelocity()); + Assert.assertNear(4, caveat2.getVelocity()); + Assert.assertNear(4, caveat3.getVelocity()); + + Assert.assertNear(10 - 1, distance(0, caveat1)); + Assert.assertNear(10 - 1, distance(1, caveat2)); + Assert.assertNear(10 - 1, distance(2, caveat3)); + break; + + case 5: + Assert.assertNear(5, caveat1.getVelocity()); + Assert.assertNear(5, caveat2.getVelocity()); + Assert.assertNear(5, caveat3.getVelocity()); + + Assert.assertNear(15 - 1, distance(0, caveat1)); + Assert.assertNear(15 - 1, distance(1, caveat2)); + Assert.assertNear(15 - 1, distance(2, caveat3)); + break; + + case 6: + Assert.assertNear(6, caveat1.getVelocity()); + Assert.assertNear(6, caveat2.getVelocity()); + Assert.assertNear(6, caveat3.getVelocity()); + + Assert.assertNear(21 - 1, distance(0, caveat1)); + Assert.assertNear(21 - 1, distance(1, caveat2)); + Assert.assertNear(21 - 1, distance(2, caveat3)); + break; + + case 7: + Assert.assertNear(7, caveat1.getVelocity()); + Assert.assertNear(7, caveat2.getVelocity()); + Assert.assertNear(7, caveat3.getVelocity()); + + Assert.assertNear(28 - 1, distance(0, caveat1)); + Assert.assertNear(28 - 1, distance(1, caveat2)); + Assert.assertNear(28 - 1, distance(2, caveat3)); + break; + + case 8: + Assert.assertNear(8, caveat1.getVelocity()); + Assert.assertNear(8, caveat2.getVelocity()); + Assert.assertNear(8, caveat3.getVelocity()); + + Assert.assertNear(36 - 1, distance(0, caveat1)); + Assert.assertNear(36 - 1, distance(1, caveat2)); + Assert.assertNear(36 - 1, distance(2, caveat3)); + + resetStartPositions(event.getTurnSnapshot()); + break; + + case 9: + Assert.assertNear(8, caveat1.getVelocity()); + Assert.assertNear(8, caveat2.getVelocity()); + + Assert.assertNear(6, caveat3.getVelocity()); // Caveat 3 (max. speed is set to 6) + + Assert.assertNear(8, distance(0, caveat1)); + Assert.assertNear(8, distance(1, caveat2)); + + resetStartPositions(event.getTurnSnapshot()); + break; + + case 10: + Assert.assertNear(caveat1.getVelocity(), distance(0, caveat1)); + Assert.assertNear(caveat2.getVelocity(), distance(1, caveat2)); + + resetStartPositions(event.getTurnSnapshot()); + break; + + case 11: + Assert.assertNear(caveat1.getVelocity(), distance(0, caveat1)); + Assert.assertNear(caveat2.getVelocity(), distance(1, caveat2)); + + resetStartPositions(event.getTurnSnapshot()); + break; + + case 12: + Assert.assertNear(caveat1.getVelocity(), distance(0, caveat1)); + Assert.assertNear(caveat2.getVelocity(), distance(1, caveat2)); + + resetStartPositions(event.getTurnSnapshot()); + break; + + case 13: + Assert.assertNear(caveat1.getVelocity(), distance(0, caveat1)); // Caveat 1 (distance should be = velocity) + Assert.assertNear(caveat2.getVelocity(), distance(1, caveat2)); + + resetStartPositions(event.getTurnSnapshot()); + break; + + case 14: + Assert.assertNear(0, caveat1.getVelocity()); + Assert.assertNear(0, caveat2.getVelocity()); + + Assert.assertNear(0, distance(1, caveat2)); // Caveat 2 (distance should be 0) + break; + } + } + + private void resetStartPositions(ITurnSnapshot turnSnapshot) { + for (int i = 0; i < 3; i++) { + IRobotSnapshot robot = turnSnapshot.getRobots()[i]; + + startX[i] = robot.getX(); + startY[i] = robot.getY(); + } + } + + private double distance(int index, IRobotSnapshot robotSnapshot) { + return Math.hypot(robotSnapshot.getX() - startX[index], robotSnapshot.getY() - startY[index]); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestAwtAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestAwtAttack.java new file mode 100644 index 0000000..a53be8b --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestAwtAttack.java @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; + +import javax.swing.*; + + +/** + * @author Pavel Savara (original) + */ +public class TestAwtAttack extends RobocodeTestBed { + // in case: boolean messagedAttack; + boolean messagedBreakthru; + + @Test + public void run() { + super.run(); + } + + /* in case that we don't block JFrame by classloader + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("Hacked!!!")) { + messagedBreakthru = true; + } + if (out.contains("Robots are not allowed to reference javax.swing package")) { + messagedAttack = true; + } + } */ + + @Override + public String getRobotNames() { + return "tested.robots.BattleLost,tested.robots.AwtAttack"; + } + + JFrame frame; + + @Override + protected void runSetup() { + frame = new JFrame(); + frame.setVisible(true); + } + + @Override + protected int getExpectedErrors() { + return 2; + } + + @Override + public int getExpectedRobotCount(String list) { + return 1; + } + + @Override + protected void runTeardown() { + + Runnable doCheck = new Runnable() { + public void run() { + Logger.logMessage("works still!!!"); + } + }; + + javax.swing.SwingUtilities.invokeLater(doCheck); + + frame.setVisible(false); + Assert.assertFalse(messagedBreakthru); + // in case: Assert.assertTrue(messagedAttack); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestBodyTurnRate.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestBodyTurnRate.java new file mode 100644 index 0000000..5ec9dc7 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestBodyTurnRate.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestBodyTurnRate extends RobocodeTestBed { + + StringBuffer buf = new StringBuffer(); + + @Override + public String getRobotNames() { + return "tested.robots.BodyTurnRate,sample.Target"; + } + + @Override + public String getInitialPositions() { + return "(600,200,0), (50,50,0)"; // Make sure the robots do not collide! + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + buf.append(event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot()); + + if (event.getTurnSnapshot().getTurn() == 60) { + final String out = buf.toString(); + + Assert.assertTrue(out.contains("1: 0.0, -10.0") | out.contains("1: 0.0, -9.9999999999")); + Assert.assertTrue(out.contains("2: 1.0, -9.25") | out.contains("2: 1.0, -9.2499999999")); + Assert.assertTrue(out.contains("3: 2.0, -8.5") | out.contains("3: 2.0, -8.4999999999")); + Assert.assertTrue(out.contains("4: 3.0, -7.75") | out.contains("4: 3.0, -7.7499999999")); + Assert.assertTrue(out.contains("5: 4.0, -7.0") | out.contains("5: 4.0, -6.9999999999")); + Assert.assertTrue(out.contains("6: 5.0, -6.25") | out.contains("6: 5.0, -6.2499999999")); + Assert.assertTrue(out.contains("7: 6.0, -5.5") | out.contains("7: 6.0, -5.4999999999")); + Assert.assertTrue(out.contains("8: 7.0, -4.75") | out.contains("8: 7.0, -4.7499999999")); + Assert.assertTrue(out.contains("9: 8.0, -4.0") | out.contains("9: 8.0, -3.9999999999")); + + Assert.assertTrue(out.contains("10: 8.0, 0.0") | out.contains("10: 8.0, -0.0")); + Assert.assertTrue(out.contains("11: 6.0, 0.0") | out.contains("11: 6.0, -0.0")); + Assert.assertTrue(out.contains("12: 4.0, 0.0") | out.contains("12: 4.0, -0.0")); + Assert.assertTrue(out.contains("13: 2.0, 0.0") | out.contains("13: 2.0, -0.0")); + Assert.assertTrue( + out.contains("14: 0.0, 0.0") | out.contains("14: 0.0, -0.0") | out.contains("14: -0.0, 0.0") + | out.contains("14: -0.0, -0.0")); + Assert.assertTrue( + out.contains("15: 0.0, 0.0") | out.contains("15: 0.0, -0.0") | out.contains("15: -0.0, 0.0") + | out.contains("15: -0.0, -0.0")); + + Assert.assertTrue(out.contains("16: 0.0, 10.0") | out.contains("16: 0.0, 9.9999999999")); + Assert.assertTrue(out.contains("17: 1.0, 9.25") | out.contains("17: 1.0, 9.2499999999")); + Assert.assertTrue(out.contains("18: 2.0, 8.5") | out.contains("18: 2.0, 8.4999999999")); + Assert.assertTrue(out.contains("19: 3.0, 7.75") | out.contains("19: 3.0, 7.7499999999")); + Assert.assertTrue(out.contains("20: 4.0, 7.0") | out.contains("20: 4.0, 6.9999999999")); + Assert.assertTrue(out.contains("21: 5.0, 6.25") | out.contains("21: 5.0, 6.2499999999")); + Assert.assertTrue(out.contains("22: 6.0, 5.5") | out.contains("22: 6.0, 5.4999999999")); + Assert.assertTrue(out.contains("23: 7.0, 4.75") | out.contains("23: 7.0, 4.7499999999")); + Assert.assertTrue(out.contains("24: 8.0, 4.0") | out.contains("24: 8.0, 3.9999999999")); + + Assert.assertTrue(out.contains("25: 8.0, 0.0") | out.contains("25: 8.0, -0.0")); + Assert.assertTrue(out.contains("26: 6.0, 0.0") | out.contains("26: 6.0, -0.0")); + Assert.assertTrue(out.contains("27: 4.0, 0.0") | out.contains("27: 4.0, -0.0")); + Assert.assertTrue(out.contains("28: 2.0, 0.0") | out.contains("28: 2.0, -0.0")); + Assert.assertTrue( + out.contains("29: 0.0, 0.0") | out.contains("29: 0.0, -0.0") | out.contains("29: -0.0, 0.0") + | out.contains("29: -0.0, -0.0")); + Assert.assertTrue( + out.contains("30: 0.0, 0.0") | out.contains("30: 0.0, -0.0") | out.contains("30: -0.0, 0.0") + | out.contains("30: -0.0, -0.0")); + + Assert.assertTrue(out.contains("31: 0.0, 10.0") | out.contains("31: 0.0, 9.9999999999")); + Assert.assertTrue(out.contains("32: -1.0, 9.25") | out.contains("32: -1.0, 9.2499999999")); + Assert.assertTrue(out.contains("33: -2.0, 8.5") | out.contains("33: -2.0, 8.4999999999")); + Assert.assertTrue(out.contains("34: -3.0, 7.75") | out.contains("34: -3.0, 7.7499999999")); + Assert.assertTrue(out.contains("35: -4.0, 7.0") | out.contains("35: -4.0, 6.9999999999")); + Assert.assertTrue(out.contains("36: -5.0, 6.25") | out.contains("36: -5.0, 6.2499999999")); + Assert.assertTrue(out.contains("37: -6.0, 5.5") | out.contains("37: -6.0, 5.4999999999")); + Assert.assertTrue(out.contains("38: -7.0, 4.75") | out.contains("38: -7.0, 4.7499999999")); + Assert.assertTrue(out.contains("39: -8.0, 4.0") | out.contains("39: -8.0, 3.9999999999")); + + Assert.assertTrue(out.contains("40: -8.0, 0.0") | out.contains("40: -8.0, -0.0")); + Assert.assertTrue(out.contains("41: -6.0, 0.0") | out.contains("41: -6.0, -0.0")); + Assert.assertTrue(out.contains("42: -4.0, 0.0") | out.contains("42: -4.0, -0.0")); + Assert.assertTrue(out.contains("43: -2.0, 0.0") | out.contains("43: -2.0, -0.0")); + Assert.assertTrue( + out.contains("44: -0.0, 0.0") | out.contains("44: -0.0, -0.0") | out.contains("44: 0.0, 0.0") + | out.contains("44: 0.0, -0.0")); + Assert.assertTrue( + out.contains("45: -0.0, 0.0") | out.contains("45: -0.0, -0.0") | out.contains("45: 0.0, 0.0") + | out.contains("45: 0.0, -0.0")); + + Assert.assertTrue(out.contains("46: 0.0, -10.0") | out.contains("46: 0.0, -9.9999999999")); + Assert.assertTrue(out.contains("47: -1.0, -9.25") | out.contains("47: -1.0, -9.2499999999")); + Assert.assertTrue(out.contains("48: -2.0, -8.5") | out.contains("48: -2.0, -8.4999999999")); + Assert.assertTrue(out.contains("49: -3.0, -7.75") | out.contains("49: -3.0, -7.7499999999")); + Assert.assertTrue(out.contains("50: -4.0, -7.0") | out.contains("50: -4.0, -6.9999999999")); + Assert.assertTrue(out.contains("51: -5.0, -6.25") | out.contains("51: -5.0, -6.2499999999")); + Assert.assertTrue(out.contains("52: -6.0, -5.5") | out.contains("52: -6.0, -5.4999999999")); + Assert.assertTrue(out.contains("53: -7.0, -4.75") | out.contains("53: -7.0, -4.7499999999")); + Assert.assertTrue(out.contains("54: -8.0, -4.0") | out.contains("54: -8.0, -3.9999999999")); + + Assert.assertTrue(out.contains("55: -8.0, 0.0") | out.contains("55: -8.0, -0.0")); + Assert.assertTrue(out.contains("56: -6.0, 0.0") | out.contains("56: -6.0, -0.0")); + Assert.assertTrue(out.contains("57: -4.0, 0.0") | out.contains("57: -4.0, -0.0")); + Assert.assertTrue(out.contains("58: -2.0, 0.0") | out.contains("58: -2.0, -0.0")); + Assert.assertTrue( + out.contains("59: -0.0, 0.0") | out.contains("59: -0.0, -0.0") | out.contains("59: 0.0, 0.0") + | out.contains("59: 0.0, -0.0")); + Assert.assertTrue( + out.contains("60: -0.0, 0.0") | out.contains("60: -0.0, -0.0") | out.contains("60: 0.0, 0.0") + | out.contains("60: 0.0, -0.0")); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestBulletPower.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestBulletPower.java new file mode 100644 index 0000000..b37b24f --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestBulletPower.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestBulletPower extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "sample.Target,tested.robots.BadFirePower"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + IRobotSnapshot bp = event.getTurnSnapshot().getRobots()[1]; + + final int time = event.getTurnSnapshot().getTurn(); + + switch (time) { + case 30: + case 46: + case 62: + case 78: + case 94: + case 110: + test(bp, "Bullet power: 3.0"); + break; + + default: + if (time > 1 && time < 115) { + test(bp, "No bullet"); + } + break; + } + } + + private void test(IRobotSnapshot gh, String s) { + Assert.assertTrue(gh.getOutputStreamSnapshot() + " expected " + s, gh.getOutputStreamSnapshot().contains(s)); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorAwtAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorAwtAttack.java new file mode 100644 index 0000000..be70e57 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorAwtAttack.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import javax.swing.*; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestConstructorAwtAttack extends RobocodeTestBed { + // in case: boolean messagedAttack; + boolean messagedBreakthru; + + JFrame frame; + + @Override + public String getRobotNames() { + return "tested.robots.ConstructorAwtAttack,tested.robots.BattleLost"; + } + + /* in case that we don't block JFrame by classloader + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("Hacked!!!")) { + messagedBreakthru = true; + } + if (out.contains("Robots are not allowed to reference javax.swing package")) { + messagedAttack = true; + } + } */ + + @Override + protected void runSetup() { + frame = new JFrame(); + frame.setVisible(true); + } + + @Override + protected int getExpectedErrors() { + return 2; + } + + @Override + public int getExpectedRobotCount(String list) { + return 1; + } + + @Override + protected void runTeardown() { + Runnable doCheck = new Runnable() { + public void run() { + Logger.logMessage("works still!!!"); + } + }; + + javax.swing.SwingUtilities.invokeLater(doCheck); + + frame.setVisible(false); + Assert.assertFalse(messagedBreakthru); + // in case: Assert.assertTrue(messagedAttack); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorHttpAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorHttpAttack.java new file mode 100644 index 0000000..8a613fa --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorHttpAttack.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestConstructorHttpAttack extends RobocodeTestBed { + + private boolean messagedInitialization; + private boolean messagedAccessDenied; + + @Override + public String getRobotNames() { + return "tested.robots.ConstructorHttpAttack,sample.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("An error occurred during initialization")) { + messagedInitialization = true; + } + + if (out.contains("access denied (java.net.SocketPermission") + || out.contains("access denied (\"java.net.SocketPermission\"")) { + messagedAccessDenied = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Error during initialization", messagedInitialization); + Assert.assertTrue("HTTP connection is not allowed", messagedAccessDenied); + } + + @Override + protected int getExpectedErrors() { + return hasJavaNetURLPermission ? 3 : 2; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorReflectionAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorReflectionAttack.java new file mode 100644 index 0000000..9dd6718 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorReflectionAttack.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestConstructorReflectionAttack extends RobocodeTestBed { + + private boolean messagedAccessDenied; + + @Override + public String getRobotNames() { + return "tested.robots.ConstructorReflectionAttack,sample.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("access denied (java.lang.reflect.ReflectPermission") + || out.contains("access denied (\"java.lang.reflect.ReflectPermission\"")) { + messagedAccessDenied = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Reflection is not allowed", messagedAccessDenied); + } + + @Override + protected int getExpectedErrors() { + return 1; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorSocketAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorSocketAttack.java new file mode 100644 index 0000000..74ced61 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorSocketAttack.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestConstructorSocketAttack extends RobocodeTestBed { + + private boolean messagedInitialization; + private boolean messagedAccessDenied; + + @Override + public String getRobotNames() { + return "tested.robots.ConstructorSocketAttack,sample.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("An error occurred during initialization")) { + messagedInitialization = true; + } + + if (out.contains("access denied (java.net.SocketPermission") + || out.contains("access denied (\"java.net.SocketPermission\"")) { + messagedAccessDenied = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Error during initialization", messagedInitialization); + Assert.assertTrue("Socket connection is not allowed", messagedAccessDenied); + } + + @Override + protected int getExpectedErrors() { + return 2; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorThreadAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorThreadAttack.java new file mode 100644 index 0000000..48bae71 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestConstructorThreadAttack.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestConstructorThreadAttack extends RobocodeTestBed { + boolean messagedUnknown; + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("Preventing Thread-") && out.contains("from access to MyAttack")) { + messagedUnknown = true; + } + } + + @Override + public String getRobotNames() { + return "tested.robots.ConstructorThreadAttack,sample.Target"; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedUnknown); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestCustomEvents.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestCustomEvents.java new file mode 100644 index 0000000..8446b86 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestCustomEvents.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import org.junit.Test; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import net.sf.robocode.test.helpers.Assert; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestCustomEvents extends RobocodeTestBed { + + @Test + public void run() { + super.run(); + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + IRobotSnapshot gh = event.getTurnSnapshot().getRobots()[1]; + + switch (event.getTurnSnapshot().getTurn()) { + case 130: + test(gh, "130 onTick99\n130 onTick30"); + break; + + case 1451: + test(gh, "1451 onTick99\n1451 onLowEnergy98\n1451 onTick30\n1451 onScannedRobot10"); + break; + + default: + break; + } + } + + private void test(IRobotSnapshot gh, String s) { + Assert.assertTrue("got: " + gh.getOutputStreamSnapshot() + ", expected: " + s, + gh.getOutputStreamSnapshot().contains(s)); + } + + @Override + public String getRobotNames() { + return "sample.Target,tested.robots.CustomEvents"; + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestDuplicatesAndScore.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestDuplicatesAndScore.java new file mode 100644 index 0000000..0ce124d --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestDuplicatesAndScore.java @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import org.junit.Test; +import robocode.BattleResults; +import robocode.control.events.BattleCompletedEvent; +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.RoundStartedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestDuplicatesAndScore extends RobocodeTestBed { + private IRobotSnapshot[] robots; + private BattleResults[] results; + private int lastTurn; + + @Test + public void run() { + super.run(); + } + + @Override + public int getExpectedRobotCount(String list) { + return 8; + } + + @Override + public String getRobotNames() { + return "sample.Fire,tested.robots.TestTeam,tested.robots.TestTeam,sample.Crazy"; + } + + @Override + public void onRoundStarted(final RoundStartedEvent event) { + super.onRoundStarted(event); + if (event.getRound() == 0) { + robots = event.getStartSnapshot().getRobots(); + Assert.assertEquals(8, robots.length); + + net.sf.robocode.test.helpers.Assert.assertNear(568.1445492, robots[0].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(436.7181397, robots[1].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(316.4177265, robots[2].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(721.2294027, robots[3].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(142.7260067, robots[4].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(738.1464346, robots[5].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(335.0596303, robots[6].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(390.7055126, robots[7].getX()); + + net.sf.robocode.test.helpers.Assert.assertNear(100.000, robots[0].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(200.000, robots[1].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(120.000, robots[2].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(100.000, robots[3].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(200.000, robots[4].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(120.000, robots[5].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(100.000, robots[6].getEnergy()); + net.sf.robocode.test.helpers.Assert.assertNear(100.000, robots[7].getEnergy()); + } + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + lastTurn = event.getTurnSnapshot().getTurn(); + robots = event.getTurnSnapshot().getRobots(); + + if (lastTurn == 1) { + net.sf.robocode.test.helpers.Assert.assertNear(568.1445492, robots[0].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(437.5845260, robots[1].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(316.4177265, robots[2].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(721.2294027, robots[3].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(142.4365354, robots[4].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(738.1464346, robots[5].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(335.0596303, robots[6].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(389.7078698, robots[7].getX()); + } + + if (lastTurn == 1365) { + net.sf.robocode.test.helpers.Assert.assertNear(468.5942997, robots[0].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(415.4262123, robots[1].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(317.3362130, robots[2].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(671.1937618, robots[3].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(365.6640401, robots[4].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(734.4305396, robots[5].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(368.6778268, robots[6].getX()); + net.sf.robocode.test.helpers.Assert.assertNear(112.8133694, robots[7].getX()); + } + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + if (event.isAborted()) { + results = null; + } + } + + @Override + public void onBattleCompleted(BattleCompletedEvent event) { + results = event.getSortedResults(); + } + + @Override + protected void runTeardown() { + Assert.assertNotNull(results); + Assert.assertNotNull(robots); + Assert.assertThat(robots[0].getName(), is("sample.Fire (1)")); + Assert.assertThat(robots[1].getName(), is("sampleteam.MyFirstLeader (1)")); + Assert.assertThat(robots[2].getName(), is("sampleteam.MyFirstDroid (1)")); + Assert.assertThat(robots[3].getName(), is("sample.Fire (2)")); + Assert.assertThat(robots[4].getName(), is("sampleteam.MyFirstLeader (2)")); + Assert.assertThat(robots[5].getName(), is("sampleteam.MyFirstDroid (2)")); + Assert.assertThat(robots[6].getName(), is("sample.Fire (3)")); + Assert.assertThat(robots[7].getName(), is("sample.Crazy")); + + Assert.assertThat(results[0].getTeamLeaderName(), is("tested.robots.TestTeam (2)")); + Assert.assertThat(results[1].getTeamLeaderName(), is("tested.robots.TestTeam (1)")); + Assert.assertThat(results[2].getTeamLeaderName(), is("sample.Fire (1)")); + Assert.assertThat(results[3].getTeamLeaderName(), is("sample.Crazy")); + + Assert.assertThat(results[0].getLastSurvivorBonus(), is(100)); + Assert.assertThat(results[1].getLastSurvivorBonus(), is(0)); + Assert.assertThat(results[2].getLastSurvivorBonus(), is(0)); + Assert.assertThat(results[3].getLastSurvivorBonus(), is(0)); + + Assert.assertThat(results[0].getRamDamage(), is(0)); + Assert.assertThat(results[1].getRamDamage(), is(2)); + Assert.assertThat(results[2].getRamDamage(), is(2)); + Assert.assertThat(results[3].getRamDamage(), is(10)); + + Assert.assertThat(results[0].getBulletDamageBonus(), is(93)); + Assert.assertThat(results[1].getBulletDamageBonus(), is(18)); + Assert.assertThat(results[2].getBulletDamageBonus(), is(0)); + Assert.assertThat(results[3].getBulletDamageBonus(), is(0)); + + Assert.assertThat(results[0].getBulletDamage(), is(513)); + Assert.assertThat(results[1].getBulletDamage(), is(280)); + Assert.assertThat(results[2].getBulletDamage(), is(89)); + Assert.assertThat(results[3].getBulletDamage(), is(48)); + + Assert.assertThat(results[0].getScore(), is(1206)); + Assert.assertThat(results[1].getScore(), is(650)); + Assert.assertThat(results[2].getScore(), is(242)); + Assert.assertThat(results[3].getScore(), is(158)); + + Assert.assertThat(lastTurn, is(893)); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestEnvAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestEnvAttack.java new file mode 100644 index 0000000..f1c05ed --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestEnvAttack.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Pavel Savara (original) + */ +public class TestEnvAttack extends RobocodeTestBed { + boolean messagedAttack; + + @Test + public void run() { + super.run(); + } + + @Override + public String getRobotNames() { + return "tested.robots.BattleLost,tested.robots.EnvAttack"; + } + + @Override + protected int getExpectedErrors() { + return 1; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("AccessControlException: access denied")) { + messagedAttack = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedAttack); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestEventPriorityFilter.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestEventPriorityFilter.java new file mode 100644 index 0000000..4800756 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestEventPriorityFilter.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Pavel Savara (original) + */ +public class TestEventPriorityFilter extends RobocodeTestBed { + boolean messagedScanned; + + @Test + public void run() { + super.run(); + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("Scanned!!!")) { + messagedScanned = true; + } + } + + @Override + public String getRobotNames() { + return "tested.robots.EventPriorityFilter,tested.robots.EventPriorityFilter"; + } + + @Override + protected void runTeardown() { + Assert.assertFalse(messagedScanned); + } +} + diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFairPlay.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFairPlay.java new file mode 100644 index 0000000..39769a6 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFairPlay.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import org.junit.Assert; +import org.junit.Test; + +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IScoreSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestFairPlay extends RobocodeTestBed { + + ITurnSnapshot lastTurnSnapshot; + + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "tested.robots.FairPlay,tested.robots.FairPlay"; + } + + @Override + public int getNumRounds() { + return 200; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + lastTurnSnapshot = event.getTurnSnapshot(); + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + final IScoreSnapshot[] scores = lastTurnSnapshot.getSortedTeamScores(); + final IScoreSnapshot score1 = scores[0]; + final IScoreSnapshot score2 = scores[1]; + + double minTotal = Math.min(score1.getTotalScore(), score2.getTotalScore()); + double maxTotal = Math.max(score1.getTotalScore(), score2.getTotalScore()); + + Assert.assertTrue("The total scores should be almost the same", maxTotal / minTotal <= 1.05); + + double minFirsts = Math.min(score1.getTotalFirsts(), score2.getTotalFirsts()); + double maxFirsts = Math.max(score1.getTotalFirsts(), score2.getTotalFirsts()); + + Assert.assertTrue("The total firsts should be almost the same", maxFirsts / minFirsts <= 1.05); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileAttack.java new file mode 100644 index 0000000..a7085d0 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileAttack.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + +import java.io.File; + + +/** + * @author Pavel Savara (original) + */ +public class TestFileAttack extends RobocodeTestBed { + boolean messagedWrite; + boolean messagedRead; + + @Test + public void run() { + super.run(); + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("Preventing tested.robots.FileAttack from access: (java.io.FilePermission C:\\MSDOS.SYS read)") + || out.contains( + "Preventing tested.robots.FileAttack from access: (\"java.io.FilePermission\" \"C:\\MSDOS.SYS\" \"read\")")) { + messagedRead = true; + } + if (out.contains( + "Preventing tested.robots.FileAttack from access: (java.io.FilePermission C:\\Robocode.attack write)") + || out.contains( + "Preventing tested.robots.FileAttack from access: (\"java.io.FilePermission\" \"C:\\Robocode.attack\" \"write\")")) { + messagedWrite = true; + } + } + + @Override + public String getRobotNames() { + return "sample.Fire,tested.robots.FileAttack"; + } + + @Override + protected void runSetup() { + File attack = new File("C:\\Robocode.attack"); + + if (attack.exists()) { + Assert.assertTrue(attack.delete()); + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Didn't seen preventing read", messagedRead); + Assert.assertTrue("Didn't seen preventing write", messagedWrite); + Assert.assertFalse("Found attack file", new File("C:\\Robocode.attack").exists()); + } + + @Override + protected int getExpectedErrors() { + return 2; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileOutputStreamAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileOutputStreamAttack.java new file mode 100644 index 0000000..cc64e98 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileOutputStreamAttack.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestFileOutputStreamAttack extends RobocodeTestBed { + + private boolean messagedAccessDenied; + + @Override + public String getRobotNames() { + return "tested.robots.FileOutputStreamAttack,sample.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("access denied (java.io.FilePermission") + || out.contains("access denied (\"java.io.FilePermission\"")) { + messagedAccessDenied = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("FileOutputStream is not allowed", messagedAccessDenied); + } + + @Override + protected int getExpectedErrors() { + return 1; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileWrite.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileWrite.java new file mode 100644 index 0000000..d59c722 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileWrite.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; + + +/** + * @author Pavel Savara (original) + */ +public class TestFileWrite extends RobocodeTestBed { + + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "sample.Walls,sample.SittingDuck"; + } + + File file = new File(robotsPath, "/target/classes/sample/SittingDuck.data/count.dat"); + + @Override + protected void runSetup() { + if (file.exists()) { + if (!file.delete()) { + Logger.logError("Can't delete" + file); + } + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue(file.exists()); + if (!file.delete()) { + Logger.logError("Can't delete" + file); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileWriteSize.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileWriteSize.java new file mode 100644 index 0000000..12dac22 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestFileWriteSize.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import java.io.File; + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestFileWriteSize extends RobocodeTestBed { + + boolean messagedDataQuota; + boolean messagedDataDirectory; + boolean messagedDataFile; + boolean messageQuotaReached; + boolean robotTerminated; + + @Override + public String getRobotNames() { + return "tested.robots.FileWriteSize,sample.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + String path = robotsPath; + + if (File.separatorChar == '\\') { + out = out.replaceAll("[\\\\]", "/"); + path = path.replaceAll("[\\\\]", "/"); + } + if (out.contains("Data quota: 200000\n")) { + messagedDataQuota = true; + } + if (out.contains("Data directory: " + path + "/target/classes/tested/robots/FileWriteSize.data")) { + messagedDataDirectory = true; + } + if (out.contains("Data file: " + path + "/target/classes/tested/robots/FileWriteSize.data/test")) { + messagedDataFile = true; + } + if (out.contains("You have reached your filesystem quota of: 200000 bytes")) { + messageQuotaReached = true; + } + if (event.getTurnSnapshot().getRobots()[0].getEnergy() == 0) { + robotTerminated = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Data quota must be 200000", messagedDataQuota); + Assert.assertTrue("Data directory path is wrong", messagedDataDirectory); + Assert.assertTrue("Data file path is wrong", messagedDataFile); + Assert.assertTrue("Error must be output that file quota has been exceeded", messageQuotaReached); + Assert.assertTrue("Game must terminate the robot", robotTerminated); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestGunHeat.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestGunHeat.java new file mode 100644 index 0000000..f19ea6d --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestGunHeat.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestGunHeat extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "sample.Target,tested.robots.GunHeat"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + IRobotSnapshot gh = event.getTurnSnapshot().getRobots()[1]; + + switch (event.getTurnSnapshot().getTurn()) { + case 1: + test(gh, "3.0"); + break; + + case 2: + test(gh, "2.8"); + break; + + case 3: + test(gh, "2.699999"); + break; + + case 4: + test(gh, "2.599999"); + break; + + case 9: + test(gh, "2.09999999"); + break; + + case 20: + test(gh, "0.9999999"); + break; + + case 28: + test(gh, "0.19999999"); + break; + + case 29: + test(gh, "0.09999999"); + break; + + case 30: + test(gh, "1.6"); + break; + + case 570: + test(gh, "2.77555"); + break; + + case 571: + test(gh, "0.0"); + break; + + default: + break; + } + } + + private void test(IRobotSnapshot gh, String s) { + Assert.assertTrue(gh.getOutputStreamSnapshot() + " expected " + s, + gh.getOutputStreamSnapshot().contains("after fire: " + s)); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestGunTurnRate.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestGunTurnRate.java new file mode 100644 index 0000000..c19543e --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestGunTurnRate.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestGunTurnRate extends RobocodeTestBed { + + StringBuffer buf = new StringBuffer(); + + @Override + public String getRobotNames() { + return "tested.robots.GunTurnRate,sample.Target"; + } + + @Override + public String getInitialPositions() { + return "(50,50,0), (150,50,0)"; // Make sure the robots do not collide! + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + buf.append(event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot()); + + if (event.getTurnSnapshot().getTurn() == 16) { + final String out = buf.toString(); + + Assert.assertTrue(out.contains("1: -20.0") | out.contains("1: -19.9999999999")); + Assert.assertTrue(out.contains("2: -20.0") | out.contains("2: -19.9999999999")); + Assert.assertTrue(out.contains("3: 20.0") | out.contains("3: 19.9999999999")); + Assert.assertTrue(out.contains("4: 20.0") | out.contains("4: 19.9999999999")); + Assert.assertTrue(out.contains("5: -25.0") | out.contains("5: -24.9999999999")); + Assert.assertTrue(out.contains("6: -25.0") | out.contains("6: -24.9999999999")); + Assert.assertTrue(out.contains("7: 25.0") | out.contains("7: 24.9999999999")); + Assert.assertTrue(out.contains("8: 25.0") | out.contains("8: 24.9999999999")); + Assert.assertTrue(out.contains("9: -30.0") | out.contains("9: -29.9999999999")); + Assert.assertTrue(out.contains("10: -30.0") | out.contains("10: -29.9999999999")); + Assert.assertTrue(out.contains("11: 30.0") | out.contains("11: 29.9999999999")); + Assert.assertTrue(out.contains("12: 30.0") | out.contains("12: 29.9999999999")); + Assert.assertTrue(out.contains("13: -10.0") | out.contains("13: -9.9999999999")); + Assert.assertTrue(out.contains("14: -10.0") | out.contains("14: -9.9999999999")); + Assert.assertTrue(out.contains("15: 10.0") | out.contains("15: 9.9999999999")); + Assert.assertTrue(out.contains("16: 10.0") | out.contains("16: 9.9999999999")); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestHttpAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestHttpAttack.java new file mode 100644 index 0000000..bd097be --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestHttpAttack.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestHttpAttack extends RobocodeTestBed { + + private boolean messagedAccessDenied; + + @Override + public String getRobotNames() { + return "tested.robots.HttpAttack,sample.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("access denied (java.net.SocketPermission") + || out.contains("access denied (\"java.net.SocketPermission\"")) { + messagedAccessDenied = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("HTTP connection is not allowed", messagedAccessDenied); + } + + @Override + protected int getExpectedErrors() { + return hasJavaNetURLPermission ? 2 : 1; // Security error must be reported as an error. Java 8 reports two errors. + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestIncludeNamespaceAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestIncludeNamespaceAttack.java new file mode 100644 index 0000000..200d715 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestIncludeNamespaceAttack.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; + + +/** + * @author Pavel Savara (original) + */ +public class TestIncludeNamespaceAttack extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + @Override + protected int getExpectedErrors() { + return 2; + } + + @Override + public int getExpectedRobotCount(String list) { + return 1; + } + + @Override + public String getRobotNames() { + return "tested.robots.DieFast,tested.robots.IncludeNamespaceAttack"; + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestInteruptibleEvent.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestInteruptibleEvent.java new file mode 100644 index 0000000..8faacad --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestInteruptibleEvent.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; + + +/** + * Test if onScannedRobot() is called when the radar is turned from within a onHitWall() event. + * + * @author Flemming N. Larsen (original) + */ +public class TestInteruptibleEvent extends RobocodeTestBed { + boolean messagedScanned; + + @Test + public void run() { + super.run(); + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("Scanned!!!")) { + messagedScanned = true; + } + } + + @Override + public String getRobotNames() { + return "tested.robots.InteruptibleEvent,tested.robots.InteruptibleEvent"; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedScanned); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestJunior.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestJunior.java new file mode 100644 index 0000000..3d8d21c --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestJunior.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import org.junit.Assert; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestJunior extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "tested.robots.JuniorEvents,sample.SittingDuck"; + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[0]; + + if (event.getTurnSnapshot().getTurn() == 590) { + String out = robot.getOutputStreamSnapshot(); + + test(out, "robocode.BulletMissedEvent 5"); + test(out, "robocode.ScannedRobotEvent 100"); + test(out, "robocode.BulletHitEvent 24"); + test(out, "robocode.StatusEvent 590"); + test(out, "robocode.WinEvent 1"); + test(out, "last bullet heading 6.06794172"); + } + } + + private void test(String out, String in) { + Assert.assertTrue(in, out.contains(in)); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestLost.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestLost.java new file mode 100644 index 0000000..cb49cbb --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestLost.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestLost extends RobocodeTestBed { + private int lost = 0; + private int end = 0; + + @Test + public void run() { + super.run(); + } + + @Override + public int getNumRounds() { + return 5; + } + + @Override + public String getRobotNames() { + return "sample.Fire,tested.robots.BattleLost"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[1]; + final String streamSnapshot = robot.getOutputStreamSnapshot(); + + if (streamSnapshot.contains("Death!")) { + lost++; + } + if (streamSnapshot.contains("BattleEnded!")) { + end++; + } + } + + @Override + protected void runTeardown() { + Assert.assertThat("always should loose", lost, is(getNumRounds())); + Assert.assertThat("should get BattleEnded event", end, is(1)); + } + +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestMaxTurnRate.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestMaxTurnRate.java new file mode 100644 index 0000000..b139c08 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestMaxTurnRate.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestMaxTurnRate extends RobocodeTestBed { + + StringBuffer buf = new StringBuffer(); + + @Override + public String getRobotNames() { + return "tested.robots.MaxTurnRate,sample.Target"; + } + + @Override + public String getInitialPositions() { + return "(50,50,0), (150,50,0)"; // Make sure the robots do not collide! + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + buf.append(event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot()); + + if (event.getTurnSnapshot().getTurn() == 26) { + final String out = buf.toString(); + + Assert.assertTrue(out.contains("1: 0.0, 0.0") | out.contains("1: 0.0, -0.0")); + Assert.assertTrue(out.contains("2: 0.0, -1.0") | out.contains("2: 0.0, -0.999999999")); + Assert.assertTrue(out.contains("3: 0.0, -2.0") | out.contains("3: 0.0, -1.999999999")); + Assert.assertTrue(out.contains("4: 0.0, -3.0") | out.contains("4: 0.0, -2.999999999")); + Assert.assertTrue(out.contains("5: 0.0, -4.0") | out.contains("5: 0.0, -3.999999999")); + Assert.assertTrue(out.contains("6: 0.0, -5.0") | out.contains("6: 0.0, -4.999999999")); + Assert.assertTrue(out.contains("7: 0.0, -6.0") | out.contains("7: 0.0, -5.999999999")); + Assert.assertTrue(out.contains("8: 0.0, -7.0") | out.contains("8: 0.0, -6.999999999")); + Assert.assertTrue(out.contains("9: 0.0, -8.0") | out.contains("9: 0.0, -7.999999999")); + Assert.assertTrue(out.contains("10: 0.0, -9.0") | out.contains("10: 0.0, -8.999999999")); + Assert.assertTrue(out.contains("11: 0.0, -10.0") | out.contains("11: 0.0, -9.999999999")); + Assert.assertTrue(out.contains("12: 0.0, -10.0") | out.contains("12: 0.0, -9.999999999")); + Assert.assertTrue(out.contains("13: 0.0, -10.0") | out.contains("13: 0.0, -9.999999999")); + + Assert.assertTrue(out.contains("14: 0.0, 0.0") | out.contains("14: 0.0, -0.0")); + Assert.assertTrue(out.contains("15: 0.0, 1.0") | out.contains("15: 0.0, 0.999999999")); + Assert.assertTrue(out.contains("16: 0.0, 2.0") | out.contains("16: 0.0, 1.999999999")); + Assert.assertTrue(out.contains("17: 0.0, 3.0") | out.contains("17: 0.0, 2.999999999")); + Assert.assertTrue(out.contains("18: 0.0, 4.0") | out.contains("18: 0.0, 3.999999999")); + Assert.assertTrue(out.contains("19: 0.0, 5.0") | out.contains("19: 0.0, 4.999999999")); + Assert.assertTrue(out.contains("20: 0.0, 6.0") | out.contains("20: 0.0, 5.999999999")); + Assert.assertTrue(out.contains("21: 0.0, 7.0") | out.contains("21: 0.0, 6.999999999")); + Assert.assertTrue(out.contains("22: 0.0, 8.0") | out.contains("22: 0.0, 7.999999999")); + Assert.assertTrue(out.contains("23: 0.0, 9.0") | out.contains("23: 0.0, 8.999999999")); + Assert.assertTrue(out.contains("24: 0.0, 10.0") | out.contains("24: 0.0, 9.999999999")); + Assert.assertTrue(out.contains("25: 0.0, 10.0") | out.contains("25: 0.0, 9.999999999")); + Assert.assertTrue(out.contains("26: 0.0, 10.0") | out.contains("26: 0.0, 9.999999999")); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestMaxVelocity.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestMaxVelocity.java new file mode 100644 index 0000000..ac28d8b --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestMaxVelocity.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; +import robocode.util.Utils; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestMaxVelocity extends RobocodeTestBed { + + @Override + public String getRobotNames() { + return "tested.robots.MaxVelocity,sample.Target"; + } + + @Override + public String getInitialPositions() { + return "(50,50,0), (600,50,0)"; // Make sure the robots do not collide! + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final int time = (int) event.getTurnSnapshot().getTurn(); + final double velocity = event.getTurnSnapshot().getRobots()[0].getVelocity(); + + switch (time) { + case 10: + case 20: + case 100: + Assert.assertTrue(Utils.isNear(velocity, 8)); + break; + + case 32: + case 40: + case 120: + Assert.assertTrue(Utils.isNear(velocity, -8)); + break; + + case 50: + case 60: + Assert.assertTrue(Utils.isNear(velocity, 4.2)); + break; + + case 70: + case 80: + Assert.assertTrue(Utils.isNear(velocity, -4.2)); + break; + + case 130: + case 140: + Assert.assertTrue(Utils.isNear(velocity, 2)); + break; + + case 150: + case 160: + Assert.assertTrue(Utils.isNear(velocity, -2)); + break; + + case 170: + case 180: + case 190: + case 199: + Assert.assertTrue(Utils.isNear(velocity, 0)); + break; + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestNames.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestNames.java new file mode 100644 index 0000000..3eacb74 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestNames.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; + + +/** + * @author Pavel Savara (original) + */ +public class TestNames extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + @Override + protected int getExpectedErrors() { + return 4; + } + + @Override + public int getExpectedRobotCount(String list) { + return 2; + } + + @Override + public String getRobotNames() { + return "sample.Fire,robocode.BadNamespace,tested.robots.TooLongNameThisIsReallyTooLongName,tooLongNamespaceThisIsReallyTooLongNamespace.TooLongNamespace,NoPackageButReallyLongNameIWouldSayTooLongMaybeEventLonger,NoPackageShortName"; + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestPosition.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestPosition.java new file mode 100644 index 0000000..b8055e2 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestPosition.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Test; +import robocode.control.events.RoundStartedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * Repeatable robot possition test + * + * @author Pavel Savara (original) + */ +public class TestPosition extends RobocodeTestBed { + int lastTurn; + + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "sample.Crazy,sample.Target"; + } + + @Override + public void onRoundStarted(final RoundStartedEvent event) { + super.onRoundStarted(event); + if (event.getRound() == 0) { + IRobotSnapshot crazy = event.getStartSnapshot().getRobots()[0]; + IRobotSnapshot target = event.getStartSnapshot().getRobots()[1]; + + Assert.assertNear(568.1445492, crazy.getX()); + Assert.assertNear(163.0032275, crazy.getY()); + Assert.assertNear(436.7181397, target.getX()); + Assert.assertNear(351.5039067, target.getY()); + } + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + lastTurn = event.getTurnSnapshot().getTurn(); + + IRobotSnapshot crazy = event.getTurnSnapshot().getRobots()[0]; + IRobotSnapshot target = event.getTurnSnapshot().getRobots()[1]; + + if (lastTurn == 1) { + Assert.assertNear(567.2831835, crazy.getX()); + Assert.assertNear(162.4952421, crazy.getY()); + Assert.assertNear(436.7181397, target.getX()); + Assert.assertNear(351.5039067, target.getY()); + } + + if (lastTurn == 1700) { + Assert.assertNear(373.9958377, crazy.getX()); + Assert.assertNear(196.1380677, crazy.getY()); + Assert.assertNear(340.3212984, target.getX()); + Assert.assertNear(456.5502002, target.getY()); + } + } + + @Override + protected void runTeardown() { + Assert.assertThat(lastTurn, is(2080)); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestPrivateConstructor.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestPrivateConstructor.java new file mode 100644 index 0000000..5c9b5c9 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestPrivateConstructor.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestPrivateConstructor extends RobocodeTestBed { + boolean messaged; + + @Test + public void run() { + super.run(); + } + + public void onTurnEnded(final TurnEndedEvent event) { + super.onTurnEnded(event); + final IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[1]; + + if (robot.getOutputStreamSnapshot().contains("SYSTEM: Is your constructor marked public?")) { + messaged = true; + } + Assert.assertNear(0, robot.getEnergy()); + } + + @Override + public String getRobotNames() { + return "sample.Fire,tested.robots.PrivateConstructor"; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messaged); + } + + @Override + protected int getExpectedErrors() { + return 1; // Security error must be reported as an error + } +} + diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRadarTurnRateAndSetAdjust.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRadarTurnRateAndSetAdjust.java new file mode 100644 index 0000000..f5b28bc --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRadarTurnRateAndSetAdjust.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestRadarTurnRateAndSetAdjust extends RobocodeTestBed { + + StringBuffer buf = new StringBuffer(); + + @Override + public String getRobotNames() { + return "tested.robots.RadarTurnRateAndSetAdjust,sample.Target"; + } + + @Override + public String getInitialPositions() { + return "(50,50,0), (150,50,0)"; // Make sure the robots do not collide! + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + buf.append(event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot()); + + if (event.getTurnSnapshot().getTurn() == 14) { + final String out = buf.toString(); + + Assert.assertTrue(out.contains("1: 45.0") | out.contains("1: 44.999999999")); + Assert.assertTrue(out.contains("2: 65.0") | out.contains("2: 64.999999999")); + Assert.assertTrue(out.contains("3: 75.0") | out.contains("3: 74.999999999")); + Assert.assertTrue(out.contains("4: -15.0") | out.contains("4: -14.999999999")); + Assert.assertTrue(out.contains("5: -55.0") | out.contains("5: -54.999999999")); + Assert.assertTrue(out.contains("6: -75.0") | out.contains("6: -74.999999999")); + Assert.assertTrue(out.contains("7: 32.0") | out.contains("7: 31.999999999")); + Assert.assertTrue(out.contains("8: 17.0") | out.contains("8: 16.999999999")); + Assert.assertTrue(out.contains("9: 35.0") | out.contains("9: 34.999999999")); + Assert.assertTrue(out.contains("10: 3.0") | out.contains("10: 2.999999999")); + Assert.assertTrue(out.contains("11: -21.0") | out.contains("11: -20.999999999")); + Assert.assertTrue(out.contains("12: 75.0") | out.contains("12: 74.999999999")); + Assert.assertTrue(out.contains("13: -75.0") | out.contains("13: -74.999999999")); + Assert.assertTrue(out.contains("14: -15.0") | out.contains("14: -14.999999999")); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRandom.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRandom.java new file mode 100644 index 0000000..f5d846a --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRandom.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * Repeatable random test + * + * @author Pavel Savara (original) + */ +public class TestRandom extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "sample.Fire,tested.robots.Random"; + } + + @Override + public boolean isCheckOnBattleStart() { + return true; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + Assert.assertTrue(event.getTurnSnapshot().getTurn() <= 1407); + IRobotSnapshot fire = event.getTurnSnapshot().getRobots()[0]; + IRobotSnapshot random = event.getTurnSnapshot().getRobots()[1]; + + if (event.getTurnSnapshot().getTurn() == 1241) { + Assert.assertNear(213.18621928, fire.getX()); + Assert.assertNear(371.45706118, fire.getY()); + Assert.assertNear(782.0, random.getX()); + Assert.assertNear(230.95479253, random.getY()); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRankingsWithTargetRobots.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRankingsWithTargetRobots.java new file mode 100644 index 0000000..3536f0f --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRankingsWithTargetRobots.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IScoreSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + + +/** + * This test is used for checking the rankings of two sample.Target robots, i.e. + * robots that does not shot, but is just waiting for someone to shot them. As + * two sample.Targets robots are not fighting each other, the battles are + * expected to end fairly even, but not necessarily due to collisions between + * the robots and the wall. + * + * @author Flemming N. Larsen (original) + */ +public class TestRankingsWithTargetRobots extends RobocodeTestBed { + + ITurnSnapshot lastTurnSnapshot; + + @Override + public String getRobotNames() { + return "sample.Target,sample.Target"; + } + + @Override + public int getNumRounds() { + return 20; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + lastTurnSnapshot = event.getTurnSnapshot(); + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + final IScoreSnapshot[] scores = lastTurnSnapshot.getSortedTeamScores(); + final IScoreSnapshot score1 = scores[0]; + final IScoreSnapshot score2 = scores[1]; + + // 1sts + 2nds = number of rounds, e.g. 4 + 6 = 10 (where 4 is 1st places, and 6 is 2nd places) + Assert.assertThat("1st ranked robot's total 1st and 2nd places must be equal to the number of rounds", + score1.getTotalFirsts() + score1.getTotalSeconds(), is(getNumRounds())); + Assert.assertThat("2nd ranked robot's total 1st and 2nd places must be equal to the number of rounds", + score2.getTotalFirsts() + score2.getTotalSeconds(), is(getNumRounds())); + + // If 1st robot's 1sts = 6, 2nds = 4, then 2nd robot's 1sts = 4, 2nds = 6 + /* Assert.assertThat( + "1st ranked robot's number of 1st places must be equal to the 2nd ranked robot's number of 2nd places", + score1.getTotalFirsts(), is(score2.getTotalSeconds())); + Assert.assertThat( + "2nd ranked robot's number of 1st places must be equal to the 1st ranked robot's number of 2nd places", + score2.getTotalFirsts(), is(score1.getTotalSeconds()));*/ + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRateControl.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRateControl.java new file mode 100644 index 0000000..efbd12d --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRateControl.java @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import static robocode.util.Utils.normalRelativeAngle; + +import org.junit.Test; + +import robocode.control.events.RoundStartedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + + +/** + * @author Joshua Galecki (original) + */ +public class TestRateControl extends RobocodeTestBed { + int turnNumber; + double originalHeading; + double originalX; + double originalGunHeading; + double originalRadarHeading; + + @Test + public void run() { + super.run(); + } + + @Override + public String getRobotNames() { + return "tested.robots.RateControl,sample.Target"; + } + + @Override + public String getInitialPositions() { + return "(320,220,0), (50,50,0)"; // Make sure the robot doesn't start too near to a wall + } + + @Override + public void onRoundStarted(final RoundStartedEvent event) { + super.onRoundStarted(event); + IRobotSnapshot rate = event.getStartSnapshot().getRobots()[0]; + + originalHeading = rate.getBodyHeading(); + originalX = rate.getX(); + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + turnNumber = event.getTurnSnapshot().getTurn(); + + IRobotSnapshot rate = event.getTurnSnapshot().getRobots()[0]; + + // Test turnRate + if (turnNumber == 10) { + Assert.assertNear(Math.PI / 4, normalRelativeAngle(rate.getBodyHeading() - originalHeading)); + } + if (turnNumber == 20) { + Assert.assertNear(-Math.PI / 4, normalRelativeAngle(rate.getBodyHeading() - originalHeading)); + } + if (turnNumber == 25) { + // Test that turnRate was set to zero + Assert.assertNear(-Math.PI / 4, normalRelativeAngle(rate.getBodyHeading() - originalHeading)); + + // Test velocityRate + double theta = rate.getBodyHeading(); + double deltaX = rate.getX() - originalX; + double distanceTravelled = deltaX / Math.sin(theta); + + Assert.assertNear(9, distanceTravelled); + } + if (turnNumber == 35) { + double theta = rate.getBodyHeading(); + double deltaX = rate.getX() - originalX; + double distanceTravelled = deltaX / Math.sin(theta); + + Assert.assertNear(-35, distanceTravelled); + originalGunHeading = rate.getGunHeading(); + } + if (turnNumber == 45) { + // Test that velocityRate was set to zero + double theta = rate.getBodyHeading(); + double deltaX = rate.getX() - originalX; + double distanceTravelled = deltaX / Math.sin(theta); + + Assert.assertNear(-47, distanceTravelled); + + // test gunRotationRate + Assert.assertNear(Math.PI / 2, normalRelativeAngle(rate.getGunHeading() - originalGunHeading)); + } + if (turnNumber == 55) { + Assert.assertNear(Math.PI / 4, normalRelativeAngle(rate.getGunHeading() - originalGunHeading)); + originalRadarHeading = rate.getRadarHeading(); + } + + if (turnNumber == 65) { + // test that gunRotationRate was set to zero + Assert.assertNear(Math.PI / 4, normalRelativeAngle(rate.getGunHeading() - originalGunHeading)); + + // test radarRotationRate + Assert.assertNear(Math.PI / 2, normalRelativeAngle(rate.getRadarHeading() - originalRadarHeading)); + } + if (turnNumber == 75) { + Assert.assertNear(Math.PI / 4, normalRelativeAngle(rate.getRadarHeading() - originalRadarHeading)); + } + if (turnNumber == 76) { + // test that radarRotationRate was set to zero + Assert.assertNear(Math.PI / 4, normalRelativeAngle(rate.getRadarHeading() - originalRadarHeading)); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestReflectionAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestReflectionAttack.java new file mode 100644 index 0000000..218f2de --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestReflectionAttack.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestReflectionAttack extends RobocodeTestBed { + + private boolean messagedAccessDenied; + + @Override + public String getRobotNames() { + return "tested.robots.ReflectionAttack,sample.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("access denied (java.lang.reflect.ReflectPermission") + || out.contains("access denied (\"java.lang.reflect.ReflectPermission\"")) { + messagedAccessDenied = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Reflection is not allowed", messagedAccessDenied); + } + + @Override + protected int getExpectedErrors() { + return 1; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestReverseDirection.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestReverseDirection.java new file mode 100644 index 0000000..2b0da8b --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestReverseDirection.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; +import robocode.util.Utils; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestReverseDirection extends RobocodeTestBed { + + @Override + public String getRobotNames() { + return "tested.robots.ReverseDirection,sample.Target"; + } + + @Override + public String getInitialPositions() { + return "(50,50,0), (600,50,0)"; // Make sure the robots do not collide! + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final int time = (int) event.getTurnSnapshot().getTurn(); + final double velocity = event.getTurnSnapshot().getRobots()[0].getVelocity(); + + switch (time) { + case 1: + Assert.assertTrue(Utils.isNear(velocity, 1.0)); + break; + + case 2: + Assert.assertTrue(Utils.isNear(velocity, -0.5)); + break; + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRobotDeathEvents.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRobotDeathEvents.java new file mode 100644 index 0000000..45b0781 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestRobotDeathEvents.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestRobotDeathEvents extends RobocodeTestBed { + + @Override + public String getRobotNames() { + return "tested.robots.RobotDeathEvents,sample.Crazy,sample.Target,sample.Target,sample.Target"; + } + + @Override + public int getNumRounds() { + return 5; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("enemyCount != getOthers()")) { + Assert.fail("Robot is missing RobotDeathEvent"); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestScoring.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestScoring.java new file mode 100644 index 0000000..5fb08f3 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestScoring.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.RoundEndedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IScoreSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + + +/** + * This test is used for testing if the current scores and total scores are + * calculated correctly. Current scores are tested at each turn, and the total + * scores are tested per round and per battle. + * + * @author Flemming N. Larsen (original) + */ +public class TestScoring extends RobocodeTestBed { + + ITurnSnapshot lastTurnSnapshot; + + @Override + public String getRobotNames() { + return "sample.Corners,sample.Crazy,sample.Fire,sample.RamFire,sample.SittingDuck,sample.SpinBot,sample.Tracker,sample.TrackFire,sample.Walls"; + } + + @Override + public int getNumRounds() { + return 10; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + lastTurnSnapshot = event.getTurnSnapshot(); + + for (IScoreSnapshot score : lastTurnSnapshot.getSortedTeamScores()) { + // Notice that the is no such thing as a 'current total last + // survivor bonus' + double currentScore = score.getCurrentSurvivalScore() + score.getCurrentBulletDamageScore() + + score.getCurrentBulletKillBonus() + score.getCurrentRammingDamageScore() + + score.getCurrentRammingKillBonus() + score.getCurrentSurvivalBonus(); + + Assert.assertNear(currentScore, score.getCurrentScore()); + } + } + + @Override + public void onRoundEnded(RoundEndedEvent event) { + super.onRoundEnded(event); + + for (IScoreSnapshot score : lastTurnSnapshot.getSortedTeamScores()) { + + double totalScore = score.getTotalSurvivalScore() + score.getTotalLastSurvivorBonus() + + score.getTotalBulletDamageScore() + score.getTotalBulletKillBonus() + score.getTotalRammingDamageScore() + + score.getTotalRammingKillBonus(); + + Assert.assertNear(totalScore, score.getTotalScore()); + } + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + for (IScoreSnapshot score : lastTurnSnapshot.getSortedTeamScores()) { + + double totalScore = score.getTotalSurvivalScore() + score.getTotalLastSurvivorBonus() + + score.getTotalBulletDamageScore() + score.getTotalBulletKillBonus() + score.getTotalRammingDamageScore() + + score.getTotalRammingKillBonus(); + + Assert.assertNear(totalScore, score.getTotalScore()); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestSkippedTurns.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestSkippedTurns.java new file mode 100644 index 0000000..c0f9959 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestSkippedTurns.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import org.junit.Ignore; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Pavel Savara (original) + */ +@Ignore("is very timing sensitive test, so it usually fails on different machines, please run explicitly if you did something to security or timing") +public class TestSkippedTurns extends RobocodeTestBed { + boolean messagedBattle; + boolean messagedEvent; + + @Test + public void run() { + super.run(); + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[1].getOutputStreamSnapshot(); + + if (out.contains("Skipped!!!")) { + messagedEvent = true; + } + if (out.contains("not performed any actions in a reasonable")) { + messagedBattle = true; + } + } + + @Override + public String getRobotNames() { + return "sample.TrackFire,tested.robots.SkipTurns"; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedEvent); + Assert.assertTrue(messagedBattle); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestSocketAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestSocketAttack.java new file mode 100644 index 0000000..da634ac --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestSocketAttack.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Assert; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Flemming N. Larsen (original) + */ +public class TestSocketAttack extends RobocodeTestBed { + + private boolean messagedAccessDenied; + + @Override + public String getRobotNames() { + return "tested.robots.SocketAttack,sample.Target"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("access denied (java.net.SocketPermission") + || out.contains("access denied (\"java.net.SocketPermission\"")) { + messagedAccessDenied = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue("Socket connection is not allowed", messagedAccessDenied); + } + + @Override + protected int getExpectedErrors() { + return 1; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestThreadAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestThreadAttack.java new file mode 100644 index 0000000..e4233fa --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestThreadAttack.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import org.junit.Ignore; + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import robocode.control.events.TurnEndedEvent; + + +/** + * @author Pavel Savara (original) + */ +@Ignore("Please run explicitly if you did something to security or timing") +public class TestThreadAttack extends RobocodeTestBed { + boolean messagedMax; + boolean messagedUnknown; + + @Override + public String getRobotNames() { + return "tested.robots.ThreadAttack,sample.SittingDuck"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("Robots are only allowed to create up to 5 threads!")) { + messagedMax = true; + } + + if (out.contains("Preventing Thread-") && out.contains("from access to MyAttack")) { + messagedUnknown = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedMax); + Assert.assertTrue(messagedUnknown); + } + + @Override + protected int getExpectedErrors() { + return 1; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestThreadGroupAttack.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestThreadGroupAttack.java new file mode 100644 index 0000000..efd019d --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestThreadGroupAttack.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import robocode.control.events.TurnEndedEvent; + + +/** + * This test was made due to hacker.Destroyer 1.3, which proved a security breach in + * Robocode 1.7.2.1 Beta. The security breach was reported with: + * Bug [3021140] Possible for robot to kill other robot threads. + * + * The security manager of Robocode must make sure that unsafe (robot) threads cannot + * access thread groups other than its own thread group within checkAccess(Thread). + * + * @author Flemming N. Larsen (original) + */ +public class TestThreadGroupAttack extends RobocodeTestBed { + boolean messagedInterrupted; + boolean messagedPreventing; + + @Override + public String getRobotNames() { + return "tested.robots.ThreadGroupAttack,sample.SittingDuck"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final String out = event.getTurnSnapshot().getRobots()[0].getOutputStreamSnapshot(); + + if (out.contains("Interrupted: sample.SittingDuck")) { + messagedInterrupted = true; + } + + if (out.contains("Preventing tested.robots.ThreadGroupAttack from access to sample.SittingDuck")) { + messagedPreventing = true; + } + } + + @Override + protected void runTeardown() { + Assert.assertFalse(messagedInterrupted); + Assert.assertTrue(messagedPreventing); + } + + @Override + protected int getExpectedErrors() { + return 3; // Security error must be reported as an error + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestUndeadThread.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestUndeadThread.java new file mode 100644 index 0000000..5e76bad --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestUndeadThread.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.Assert; +import net.sf.robocode.test.helpers.RobocodeTestBed; +import org.junit.Test; +import org.junit.Ignore; +import robocode.control.events.BattleErrorEvent; + + +/** + * @author Pavel Savara (original) + */ +@Ignore("is very time consuming test, please run explicitly if you did something to security or timing") +public class TestUndeadThread extends RobocodeTestBed { + boolean messagedStop; + boolean messagedForcing; + + @Test + public void run() { + super.run(); + } + + public void onBattleError(BattleErrorEvent event) { + super.onBattleError(event); + final String error = event.getError(); + + if (error.contains("is not stopping. Forcing a stop.")) { + messagedForcing = true; + } + if (error.contains("Unable to stop thread")) { + messagedStop = true; + } + } + + @Override + protected int getExpectedErrors() { + return 3; + } + + @Override + public String getRobotNames() { + return "sample.SittingDuck,tested.robots.UndeadThread"; + } + + @Override + protected void runTeardown() { + Assert.assertTrue(messagedForcing); + Assert.assertTrue(messagedStop); + } + +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestWatchBullet.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestWatchBullet.java new file mode 100644 index 0000000..7f3cbe0 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestWatchBullet.java @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; + +import org.junit.Assert; +import org.junit.Test; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + */ +public class TestWatchBullet extends RobocodeTestBed { + @Test + public void run() { + super.run(); + } + + public String getRobotNames() { + return "tested.robots.WatchBullets,sample.SittingDuck"; + } + + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + final IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[0]; + + final String out = robot.getOutputStreamSnapshot(); + final int time = event.getTurnSnapshot().getTurn(); + + test(out, time, 33, "33 487.438779505497 119.51131582855926 347.66745091446046 true"); + test(out, time, 45, "45 459.24550664858225 248.46533618316306 347.66745091446046 true"); + test(out, time, 52, "52 442.799430815382 323.6885147233484 347.66745091446046 true"); + test(out, time, 53, "53 440.4499914106391 334.43468308623204 347.66745091446046 false"); + } + + private void test(String out, int timecurr, int timeWatch, String in) { + if (timecurr == timeWatch) { + Assert.assertTrue("got: " + out + ", expected: " + in, out.contains(in)); + } + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestWin.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestWin.java new file mode 100644 index 0000000..c16b99c --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/robots/TestWin.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.robots; + + +import net.sf.robocode.test.helpers.RobocodeTestBed; +import static org.hamcrest.CoreMatchers.is; +import org.junit.Assert; +import org.junit.Test; +import robocode.BattleResults; +import robocode.control.events.BattleCompletedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; + + +/** + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public class TestWin extends RobocodeTestBed { + private BattleResults[] results; + private StringBuffer outputBuf = new StringBuffer(); + + @Test + public void run() { + super.run(); + } + + @Override + public int getNumRounds() { + return 5; + } + + @Override + public String getRobotNames() { + return "sample.MyFirstRobot,tested.robots.BattleWin"; + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + super.onTurnEnded(event); + IRobotSnapshot robot = event.getTurnSnapshot().getRobots()[1]; + final String streamSnapshot = robot.getOutputStreamSnapshot(); + + outputBuf.append(streamSnapshot); + } + + public void onBattleCompleted(BattleCompletedEvent event) { + results = event.getSortedResults(); + } + + @Override + protected void runTeardown() { + String[] lines = outputBuf.toString().split("\\n"); + + Assert.assertThat(lines[1], is("Round 1 of 5")); + Assert.assertThat(lines[3], is("RoundEnded!")); + Assert.assertThat(lines[4], is("SYSTEM: tested.robots.BattleWin has died")); + Assert.assertThat(lines[5], is("Death!")); + Assert.assertThat(lines[7], is("Round 2 of 5")); + Assert.assertThat(lines[9], is("RoundEnded!")); + Assert.assertThat(lines[10], is("SYSTEM: tested.robots.BattleWin has died")); + Assert.assertThat(lines[11], is("Death!")); + Assert.assertThat(lines[13], is("Round 3 of 5")); + Assert.assertThat(lines[15], is("SYSTEM: Bonus for killing sample.MyFirstRobot: 1")); + Assert.assertThat(lines[16], is("SYSTEM: tested.robots.BattleWin wins the round.")); + Assert.assertThat(lines[17], is("RoundEnded!")); + Assert.assertThat(lines[18], is("Win!")); + Assert.assertThat(lines[20], is("Round 4 of 5")); + Assert.assertThat(lines[22], is("SYSTEM: Bonus for killing sample.MyFirstRobot: 3")); + Assert.assertThat(lines[23], is("SYSTEM: tested.robots.BattleWin wins the round.")); + Assert.assertThat(lines[24], is("RoundEnded!")); + Assert.assertThat(lines[25], is("Win!")); + Assert.assertThat(lines[27], is("Round 5 of 5")); + Assert.assertThat(lines[29], is("SYSTEM: tested.robots.BattleWin wins the round.")); + Assert.assertThat(lines[30], is("RoundEnded!")); + Assert.assertThat(lines[31], is("Win!")); + Assert.assertThat(lines[32], is("BattleEnded!")); + + Assert.assertThat("1st robot should get right score", results[0].getScore(), is(233)); + Assert.assertThat("2nd robot should get right score", results[1].getScore(), is(216)); + } +} diff --git a/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/samples/RobocodeRunner.java b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/samples/RobocodeRunner.java new file mode 100644 index 0000000..3bb11f0 --- /dev/null +++ b/代码/workspace_robo4/robocode.tests/src/test/java/net/sf/robocode/test/samples/RobocodeRunner.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.test.samples; + + +import robocode.BattleResults; +import robocode.control.*; +import robocode.control.events.*; + + +/** + * Sample application that runs two sample robots in Robocode. + * + * @author Flemming N. Larsen (original) + */ +public class RobocodeRunner { + + public static void main(String[] args) { + + // Battle listener used for receiving battle events + BattleObserver battleListener = new BattleObserver(); + + // Create the RobocodeEngine + // IRobocodeEngine engine = new RobocodeEngine(new java.io.File("C:/Robocode")); // Run from C:/Robocode + RobocodeEngine engine = new RobocodeEngine(); // Run from current working directory + + // Add battle listener to our RobocodeEngine + engine.addBattleListener(battleListener); + + // Show the battles + engine.setVisible(true); + + // Setup the battle specification + + int numberOfRounds = 5; + BattlefieldSpecification battlefield = new BattlefieldSpecification(800, 600); // 800x600 + RobotSpecification[] selectedRobots = engine.getLocalRepository("sample.RamFire, sample.Corners"); + + BattleSpecification battleSpec = new BattleSpecification(numberOfRounds, battlefield, selectedRobots); + + // Run our specified battle and let it run till it's over + engine.runBattle(battleSpec, true/* wait till the battle is over */); + + // Cleanup our RobocodeEngine + engine.close(); + + // Make sure that the Java VM is shut down properly + System.exit(0); + } + + /** + * BattleListener for handling the battle event we are interested in. + */ + static class BattleObserver extends BattleAdaptor { + + public void onBattleStarted(BattleStartedEvent e) { + System.out.println("-- Battle was started --"); + } + + public void onBattleFinished(BattleFinishedEvent e) { + if (e.isAborted()) { + System.out.println("-- Battle was aborted --"); + } else { + System.out.println("-- Battle was finished succesfully --"); + } + } + + public void onBattleCompleted(BattleCompletedEvent e) { + System.out.println("-- Battle has completed --"); + + // Print out the sorted results with the robot names + System.out.println("\n-- Battle results --"); + for (BattleResults result : e.getSortedResults()) { + System.out.println(" " + result.getTeamLeaderName() + ": " + result.getScore()); + } + } + + public void onBattleMessage(BattleMessageEvent e) { + System.out.println("Msg> " + e.getMessage()); + } + + public void onBattleError(BattleErrorEvent e) { + System.out.println("Err> " + e.getError()); + } + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/.classpath b/代码/workspace_robo4/robocode.ui.editor/.classpath new file mode 100644 index 0000000..b053438 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.ui.editor/.project b/代码/workspace_robo4/robocode.ui.editor/.project new file mode 100644 index 0000000..10502cc --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/.project @@ -0,0 +1,22 @@ + + + robocode.ui.editor + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.ui + robocode.api + robocode.core + robocode.battle + robocode.host + robocode.repository + robocode.sound + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.ui.editor/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.ui.editor/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.ui.editor/pom.xml b/代码/workspace_robo4/robocode.ui.editor/pom.xml new file mode 100644 index 0000000..1554dfa --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/pom.xml @@ -0,0 +1,19 @@ + + + 4.0.0 + robocode.ui.editor + Robocode UI Robot editor + + robocode + net.sf.robocode + ${robocode.version} + + + + net.sf.robocode + robocode.ui + ${project.version} + + + diff --git a/代码/workspace_robo4/robocode.ui.editor/robocode.ui.editor.iml b/代码/workspace_robo4/robocode.ui.editor/robocode.ui.editor.iml new file mode 100644 index 0000000..45f9610 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/robocode.ui.editor.iml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompilerPreferencesDialog.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompilerPreferencesDialog.java new file mode 100644 index 0000000..3286733 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompilerPreferencesDialog.java @@ -0,0 +1,171 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.FileOutputStream; +import java.io.IOException; + + +/** + * @author Mathew A. Nelson (original) + * @author Matthew Reeder (contributor) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class CompilerPreferencesDialog extends JDialog { + + private JButton cancelButton; + private JTextField compilerBinaryField; + private JTextField compilerClasspathField; + private JTextField compilerOptionsField; + private JPanel compilerPreferencesContentPane; + private CompilerProperties compilerProperties; + private JButton okButton; + + private final EventHandler eventHandler = new EventHandler(); + + private class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (e.getSource().equals(getOkButton())) { + if (compilerProperties == null) { + compilerProperties = new CompilerProperties(); + } + compilerProperties.setCompilerBinary(getCompilerBinaryField().getText()); + compilerProperties.setCompilerOptions(getCompilerOptionsField().getText()); + compilerProperties.setCompilerClasspath(getCompilerClasspathField().getText()); + saveCompilerProperties(); + dispose(); + } + if (e.getSource().equals(getCancelButton())) { + dispose(); + } + } + } + + public CompilerPreferencesDialog(JFrame owner) { + super(owner, true); + this.compilerProperties = net.sf.robocode.core.Container.getComponent(RobocodeCompilerFactory.class).getCompilerProperties(); + initialize(); + } + + private void initialize() { + setTitle("Compiler Preferences"); + setContentPane(getCompilerPreferencesContentPane()); + } + + public JButton getCancelButton() { + if (cancelButton == null) { + cancelButton = new JButton("Cancel"); + cancelButton.setMnemonic('C'); + cancelButton.addActionListener(eventHandler); + } + return cancelButton; + } + + public JTextField getCompilerBinaryField() { + if (compilerBinaryField == null) { + compilerBinaryField = new JTextField(40); + compilerBinaryField.setText(compilerProperties.getCompilerBinary()); + } + return compilerBinaryField; + } + + public JTextField getCompilerClasspathField() { + if (compilerClasspathField == null) { + compilerClasspathField = new JTextField(40); + compilerClasspathField.setText(compilerProperties.getCompilerClasspath()); + } + return compilerClasspathField; + } + + public JTextField getCompilerOptionsField() { + if (compilerOptionsField == null) { + compilerOptionsField = new JTextField(40); + compilerOptionsField.setText(compilerProperties.getCompilerOptions()); + } + return compilerOptionsField; + } + + private JPanel getCompilerPreferencesContentPane() { + if (compilerPreferencesContentPane == null) { + compilerPreferencesContentPane = new JPanel(); + compilerPreferencesContentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + compilerPreferencesContentPane.setLayout(new BoxLayout(compilerPreferencesContentPane, BoxLayout.Y_AXIS)); + JLabel label = new JLabel("Compiler Binary:"); + + label.setAlignmentX(Component.LEFT_ALIGNMENT); + compilerPreferencesContentPane.add(label); + + getCompilerBinaryField().setAlignmentX(Component.LEFT_ALIGNMENT); + compilerPreferencesContentPane.add(getCompilerBinaryField()); + + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + compilerPreferencesContentPane.add(label); + label = new JLabel("Compiler Options:"); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + compilerPreferencesContentPane.add(label); + getCompilerOptionsField().setAlignmentX(Component.LEFT_ALIGNMENT); + compilerPreferencesContentPane.add(getCompilerOptionsField()); + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + compilerPreferencesContentPane.add(label); + label = new JLabel("Compiler Classpath:"); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + compilerPreferencesContentPane.add(label); + getCompilerClasspathField().setAlignmentX(Component.LEFT_ALIGNMENT); + compilerPreferencesContentPane.add(getCompilerClasspathField()); + JPanel panel = new JPanel(); + + panel.setAlignmentX(Component.LEFT_ALIGNMENT); + panel.add(getOkButton()); + panel.add(getCancelButton()); + compilerPreferencesContentPane.add(panel); + } + return compilerPreferencesContentPane; + } + + public JButton getOkButton() { + if (okButton == null) { + okButton = new JButton("OK"); + okButton.setMnemonic('O'); + okButton.addActionListener(eventHandler); + } + return okButton; + } + + public void saveCompilerProperties() { + if (compilerProperties == null) { + Logger.logError("Cannot save null compiler properties"); + return; + } + FileOutputStream out = null; + + try { + out = new FileOutputStream(FileUtil.getCompilerConfigFile()); + + compilerProperties.store(out, "Robocode Compiler Properties"); + } catch (IOException e) { + Logger.logError(e); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException ignored) {} + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompilerProperties.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompilerProperties.java new file mode 100644 index 0000000..d105f54 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompilerProperties.java @@ -0,0 +1,138 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Properties; + + +/** + * @author Mathew A. Nelson (original) + */ +public class CompilerProperties { + public final static String COMPILER_BINARY = "compiler.binary"; + public final static String COMPILER_OPTIONS = "compiler.options"; + public final static String COMPILER_CLASSPATH = "compiler.classpath"; + public final static String ROBOCODE_VERSION = "robocode.version"; + + private String compilerBinary; + private String compilerOptions; + private String compilerClasspath; + private String robocodeVersion; + + private final Properties props = new Properties(); + + public CompilerProperties() { + super(); + } + + /** + * Returns the compilerBinary. + * + * @return String + */ + public String getCompilerBinary() { + if (compilerBinary == null) { + setCompilerBinary(""); + } + return compilerBinary; + } + + /** + * Returns the compilerClasspath. + * + * @return String + */ + public String getCompilerClasspath() { + if (compilerClasspath == null) { + setCompilerClasspath(""); + } + return compilerClasspath; + } + + /** + * Returns the compilerOptions. + * + * @return String + */ + public String getCompilerOptions() { + if (compilerOptions == null) { + setCompilerOptions(""); + } + return compilerOptions; + } + + /** + * Returns the robocodeVersion. + * + * @return String + */ + public String getRobocodeVersion() { + return robocodeVersion; + } + + public void resetCompiler() { + this.compilerBinary = null; + props.remove(COMPILER_BINARY); + } + + /** + * Sets the compilerBinary. + * + * @param compilerBinary The compilerBinary to set + */ + public void setCompilerBinary(String compilerBinary) { + this.compilerBinary = compilerBinary; + props.setProperty(COMPILER_BINARY, compilerBinary); + } + + /** + * Sets the compilerClasspath. + * + * @param compilerClasspath The compilerClasspath to set + */ + public void setCompilerClasspath(String compilerClasspath) { + this.compilerClasspath = compilerClasspath; + props.setProperty(COMPILER_CLASSPATH, compilerClasspath); + } + + /** + * Sets the compilerOptions. + * + * @param compilerOptions The compilerOptions to set + */ + public void setCompilerOptions(String compilerOptions) { + this.compilerOptions = compilerOptions; + props.setProperty(COMPILER_OPTIONS, compilerOptions); + } + + /** + * Sets the robocodeVersion. + * + * @param robocodeVersion The robocodeVersion to set + */ + public void setRobocodeVersion(String robocodeVersion) { + this.robocodeVersion = robocodeVersion; + props.setProperty(ROBOCODE_VERSION, robocodeVersion); + } + + public void load(InputStream is) throws IOException { + props.load(is); + this.compilerBinary = props.getProperty(COMPILER_BINARY); + this.compilerOptions = props.getProperty(COMPILER_OPTIONS); + this.compilerClasspath = props.getProperty(COMPILER_CLASSPATH); + this.robocodeVersion = props.getProperty(ROBOCODE_VERSION); + } + + public void store(OutputStream os, String header) throws IOException { + props.store(os, header); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompoundUndoManager.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompoundUndoManager.java new file mode 100644 index 0000000..efa4ebf --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/CompoundUndoManager.java @@ -0,0 +1,147 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import javax.swing.event.UndoableEditEvent; +import javax.swing.event.DocumentEvent.EventType; +import javax.swing.text.AbstractDocument.DefaultDocumentEvent; +import javax.swing.text.BadLocationException; +import javax.swing.undo.CannotUndoException; +import javax.swing.undo.CompoundEdit; +import javax.swing.undo.UndoableEdit; + + +/** + * Undo manager that compounds undo and redo edits. + * + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class CompoundUndoManager extends UndoManagerWithActions { + + private CompoundEdit currentCompoundEdit; + private EventType lastEventType; + private boolean isCompoundMarkStart; + + public CompoundUndoManager() { + super(); + reset(); + } + + @Override + public void undoableEditHappened(UndoableEditEvent undoableEditEvent) { + UndoableEdit edit = undoableEditEvent.getEdit(); + + // Make sure this event is a document event + if (edit instanceof DefaultDocumentEvent) { + // Get the event type + DefaultDocumentEvent event = (DefaultDocumentEvent) edit; + EventType eventType = event.getType(); + + // Check if the event type is not a change on character attributes, but instead an insertion or removal of + // text. + if (eventType != EventType.CHANGE) { + boolean isEndCompoundEdit = false; + + // Check if current compound edit must be ended as it contains at least one new line + if (eventType == EventType.INSERT) { + try { + // Check if the inserted text contains a new line character + String insertedText = event.getDocument().getText(event.getOffset(), event.getLength()); + isEndCompoundEdit = insertedText.contains("\n"); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + // Make sure we are not in an explicit marked compound edit + if (!isCompoundMarkStart) { + // Check if current compound edit must be ended due to change between insertion or removal change + isEndCompoundEdit |= (eventType != lastEventType); + + // Check if the current compound edit should be ended and a new one started + if (isEndCompoundEdit) { + endCurrentCompoundEdit(); + } + // Save the last event type + lastEventType = eventType; + } + + // Create new compound edit if the current one has been ended or does not exist + if (currentCompoundEdit == null) { + newCurrentCompoundEdit(); + } + } + // Added event edit to the current compound edit + if (currentCompoundEdit != null) { + currentCompoundEdit.addEdit(edit); + } + } + // Update the state of the actions + updateUndoRedoState(); + } + + @Override + public void discardAllEdits() { + super.discardAllEdits(); + reset(); + } + + /** + * Ends the current compound edit, and mark the start for combining the next insertions or removals of text to be + * put into the same compound edit so that these combined operations acts like as one single edit. + * + * @see #markCompoundEnd() + */ + public void markCompoundStart() { + endCurrentCompoundEdit(); + isCompoundMarkStart = true; + } + + /** + * Ends the current compound edit so that previous edits acts like a single edit. + * + * @see #markCompoundStart() + */ + public void markCompoundEnd() { + endCurrentCompoundEdit(); + isCompoundMarkStart = false; + } + + private void reset() { + currentCompoundEdit = null; + lastEventType = EventType.INSERT; // important + } + + private void endCurrentCompoundEdit() { + if (currentCompoundEdit != null) { + currentCompoundEdit.end(); + currentCompoundEdit = null; + } + } + + private void newCurrentCompoundEdit() { + // Set current compound edit to a new one + currentCompoundEdit = new CompoundEdit() { + // Make sure canUndo() and canRedo() works + @Override + public boolean isInProgress() { + return false; + } + + @Override + public void undo() throws CannotUndoException { + endCurrentCompoundEdit(); + super.undo(); + } + }; + // Add the current compound edit to the internal edits + addEdit(currentCompoundEdit); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorPane.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorPane.java new file mode 100644 index 0000000..ec856d2 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorPane.java @@ -0,0 +1,374 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import java.awt.Event; +import java.awt.FontMetrics; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.Reader; + +import javax.swing.InputMap; +import javax.swing.JTextPane; +import javax.swing.JViewport; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultCaret; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; +import javax.swing.text.SimpleAttributeSet; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyledEditorKit; +import javax.swing.text.TabSet; +import javax.swing.text.TabStop; + + +/** + * Editor pane used for editing source code. + * + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class EditorPane extends JTextPane { + + private int tabSize = 4; // Default + + // Key bindings + private static final KeyStroke CUT_KEYSTROKE = KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK); + private static final KeyStroke COPY_KEYSTROKE = KeyStroke.getKeyStroke(KeyEvent.VK_C, Event.CTRL_MASK); + private static final KeyStroke PASTE_KEYSTROKE = KeyStroke.getKeyStroke(KeyEvent.VK_V, Event.CTRL_MASK); + private static final KeyStroke UNDO_KEYSTROKE = KeyStroke.getKeyStroke(KeyEvent.VK_Z, Event.CTRL_MASK); + private static final KeyStroke REDO_KEYSTROKE = KeyStroke.getKeyStroke(KeyEvent.VK_Y, Event.CTRL_MASK); + + private final JavaDocument document; + + private final CompoundUndoManager undoManager = new CompoundUndoManager(); + + private final TextTool textTool = new TextTool(); + + private JViewport viewport; + + public EditorPane(JViewport viewport) { + super(); + this.viewport = viewport; + document = new JavaDocument(this); + + DefaultCaret caret = (DefaultCaret) getCaret(); + caret.setUpdatePolicy(DefaultCaret.NEVER_UPDATE); + + new LineNumberArea(this); + + LineHighlighter.install(this); + + EditorKit editorKit = new StyledEditorKit() { + @Override + public Document createDefaultDocument() { + return document; + } + }; + + setEditorKitForContentType("text/java", editorKit); + setContentType("text/java"); + + addPropertyChangeListener("font", new FontHandler()); + addKeyListener(new KeyHandler()); + + setKeyBindings(); + setActionBindings(); + + getDocument().addUndoableEditListener(undoManager); + } + + public JViewport getViewport() { + return viewport; + } + + // No line wrapping! + @Override + public boolean getScrollableTracksViewportWidth() { + return getUI().getPreferredSize(this).width <= getParent().getSize().width; + } + + // Don't enforce height -> Avoid line height changes + @Override + public boolean getScrollableTracksViewportHeight() { + return false; + } + + // Make sure to discard all undo/redo edits when text completely replaced + @Override + public void setText(final String text) { + // Adding this call to the EDT prevents problems with deleting text that eats text before the deletion + SwingUtilities.invokeLater(new Runnable() { + public void run() { + JavaDocument javaDocument = (JavaDocument) getDocument(); + + // Bug-357: Tab characters are inserted in the last line of a robot source file when opening it. + // This bug was fixed by disabling auto-indentation while reading the file. + javaDocument.setReplacingText(true); + EditorPane.super.setText(text); + javaDocument.setReplacingText(false); + + resetCaretPosition(); + + undoManager.discardAllEdits(); + } + }); + } + + // Make sure to discard all undo/redo edits when text is read as one block + @Override + public void read(Reader in, Object desc) throws IOException { + JavaDocument javaDocument = (JavaDocument) getDocument(); + + // Bug-357: Tab characters are inserted in the last line of a robot source file when opening it. + // This bug was fixed by disabling auto-indentation while reading the file. + javaDocument.setReplacingText(true); + super.read(in, desc); + javaDocument.setReplacingText(false); + + resetCaretPosition(); + + undoManager.discardAllEdits(); + } + + public boolean isModified() { + return undoManager.canUndo(); + } + + public void undo() { + if (undoManager.canUndo()) { + undoManager.undo(); + } + } + + public void redo() { + if (undoManager.canRedo()) { + undoManager.redo(); + } + } + + private void setKeyBindings() { + InputMap inputMap = this.getInputMap(); + + inputMap.put(CUT_KEYSTROKE, DefaultEditorKit.cutAction); + inputMap.put(COPY_KEYSTROKE, DefaultEditorKit.copyAction); + inputMap.put(PASTE_KEYSTROKE, DefaultEditorKit.pasteAction); + inputMap.put(UNDO_KEYSTROKE, undoManager.getUndoAction()); + inputMap.put(REDO_KEYSTROKE, undoManager.getRedoAction()); + } + + private void setActionBindings() { + getActionMap().put("undo-keystroke", undoManager.getUndoAction()); + getActionMap().put("redo-keystroke", undoManager.getRedoAction()); + } + + private void setTabSize(int tabSize) { + document.setTabSize(tabSize); + + FontMetrics fm = getFontMetrics(getFont()); + + int charWidth = fm.charWidth('#'); + int tabWidth = charWidth * tabSize; + + TabStop[] tabs = new TabStop[100]; + for (int j = 0; j < tabs.length; j++) { + tabs[j] = new TabStop((j + 1) * tabWidth); + } + + SimpleAttributeSet attributes = new SimpleAttributeSet(); + + StyleConstants.setTabSet(attributes, new TabSet(tabs)); + + getDocument().removeUndoableEditListener(undoManager); // Avoid this change to be undone + getStyledDocument().setParagraphAttributes(0, getDocument().getLength(), attributes, false); + getDocument().addUndoableEditListener(undoManager); + } + + private void resetCaretPosition() { + // Make sure to put this request on the EDT or the caret position might not be reset after all. + SwingUtilities.invokeLater(new Runnable() { + public void run() { + setCaretPosition(0); + } + }); + } + + private void onTabCharPressed(boolean isUnindent) { + + int selectionStart = getSelectionStart(); + int selectionEnd = getSelectionEnd(); + + if (selectionStart == selectionEnd) { + // No selection -> Handle normal tab indentation + + if (isUnindent) { + textTool.removeLastTab(getCaretPosition()); + } else { + textTool.insertString(getCaretPosition(), "\t"); + } + } else { + // Start block indentation + + // Make sure that the start selection is lesser than the end selection + if (selectionStart > selectionEnd) { + // Swap selection start and selection end + int tmp = selectionStart; + + selectionStart = selectionEnd; + selectionEnd = tmp; + } + + StringBuilder newText = new StringBuilder(); + int count = 0; + boolean stopUnindent = false; + + // Handle each line + + String selectedText = textTool.getSelectedText(); + + selectedText = selectedText.replaceAll("\\s*$", ""); + + String[] lines = selectedText.split(String.valueOf('\n')); + + // iterate lines, rebuilding tabs and newlines + for (int i = 0; i < lines.length; i++) { + String line = lines[i]; + + if (isUnindent) { + if (line.charAt(0) != '\t') { + stopUnindent = true; + break; + } else { + newText.append(line.substring(1, line.length())); + count++; + } + } else { + newText.append('\t').append(line); + count++; + } + if (i != lines.length - 1) { + newText.append('\n'); + } + } + + if (!stopUnindent) { + try { + // Replace the indented/unindented text in one single compound edit + undoManager.markCompoundStart(); + getDocument().remove(selectionStart, selectedText.length()); + textTool.insertString(selectionStart, newText.toString()); + undoManager.markCompoundStart(); + } catch (BadLocationException e) { + e.printStackTrace(); + } + + // Compute the new selection + int mod = isUnindent ? -1 : 1; + + // Make new selection using the EDT, as replacing the text above must run before a new selection can be made + + final int newSelectionStart = selectionStart; + final int newSelectionEnd = selectionStart + selectedText.length() + count * mod; + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + setSelectionStart(newSelectionStart); + setSelectionEnd(newSelectionEnd); + } + }); + } + } + } + + private class FontHandler implements PropertyChangeListener { + public void propertyChange(PropertyChangeEvent e) { + setTabSize(tabSize); + } + } + + + private class KeyHandler extends KeyAdapter { + + @Override + public void keyPressed(KeyEvent e) { + switch (e.getKeyCode()) { + case KeyEvent.VK_TAB: + onTabCharPressed(e.isShiftDown()); + e.consume(); + break; + } + } + } + + + /** + * Handy text tool. + */ + private class TextTool { + + String getSelectedText() { + int start = getSelectionStart(); + int end = getSelectionEnd(); + + try { + return getDocument().getText(start, end - start); + } catch (BadLocationException e) { + e.printStackTrace(); + } + return null; + } + + void insertString(int offset, String str) { + insertString(offset, str, null); + } + + void insertString(final int offset, final String str, final AttributeSet a) { + try { + getDocument().insertString(offset, str, a); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + void removeLastTab(int offset) { + int pos = offset; + + while (--pos >= 0) { + try { + char ch = getDocument().getText(pos, 1).charAt(0); + + if (ch == '\t') { + remove(pos, 1); + return; + } + if (ch == '\n') { + return; + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } + + void remove(final int offset, final int len) { + try { + getDocument().remove(offset, len); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorPanel.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorPanel.java new file mode 100644 index 0000000..0ffd6c4 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorPanel.java @@ -0,0 +1,181 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; + +import javax.swing.BorderFactory; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.border.Border; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import javax.swing.text.Utilities; + +import net.sf.robocode.ui.editor.theme.EditorThemeProperties; +import net.sf.robocode.ui.editor.theme.EditorThemePropertiesManager; +import net.sf.robocode.ui.editor.theme.EditorThemePropertyChangeAdapter; + + +/** + * Editor panel containing editor pane in a scroll pane, a line number area, and a statusTextField text field. + * + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class EditorPanel extends JPanel { + + private JTextField statusTextField; + private final JScrollPane scrollPane; + private final EditorPane editorPane; + private final LineNumberArea lineNumberArea; + + public EditorPanel() { + super(); + + setLayout(new BorderLayout()); + + statusTextField = new JTextField(); + statusTextField.setEditable(false); + + scrollPane = new JScrollPane(); + + editorPane = new EditorPane(scrollPane.getViewport()); + editorPane.addCaretListener(new CaretListener() { + public void caretUpdate(CaretEvent e) { + updateStatus(getRow(e.getDot(), editorPane), getColumn(e.getDot(), editorPane)); + } + }); + + scrollPane.setViewportView(editorPane); + + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + setBackgroundColor(themeProps.getBackgroundColor()); + setSelectionColor(themeProps.getSelectionColor()); + setSelectedTextColor(themeProps.getSelectedTextColor()); + + lineNumberArea = new LineNumberArea(editorPane); + scrollPane.setRowHeaderView(lineNumberArea); + + add(scrollPane, BorderLayout.CENTER); + add(statusTextField, BorderLayout.SOUTH); + + updateStatus(1, 1); + + EditorThemePropertiesManager.addListener(new EditorThemePropertyChangeAdapter() { + @Override + public void onBackgroundColorChanged(Color newColor) { + setBackgroundColor(newColor); + } + + @Override + public void onSelectionColorChanged(Color newColor) { + setSelectionColor(newColor); + } + + @Override + public void onSelectedTextColorChanged(Color newColor) { + setSelectedTextColor(newColor); + } + }); + } + + @Override + public void requestFocus() { + super.requestFocus(); + if (editorPane != null) { + editorPane.requestFocus(); + editorPane.requestFocusInWindow(); + } + } + + @Override + public void setFont(Font font) { + super.setFont(font); + if (editorPane != null) { + editorPane.setFont(font); + + Border border = BorderFactory.createEmptyBorder(3, 3, 3, 3); + editorPane.setBorder(border); + } + if (lineNumberArea != null) { + lineNumberArea.setFont(font); + + FontMetrics fm = getFontMetrics(font); + int delta = fm.getHeight() - fm.getDescent() - fm.getAscent(); + Border border = BorderFactory.createEmptyBorder(delta + 3, 3, 3, 3); + lineNumberArea.setBorder(border); + } + } + + public EditorPane getEditorPane() { + return editorPane; + } + + private void updateStatus(int linenumber, int columnnumber) { + statusTextField.setText("Line: " + linenumber + " Column: " + columnnumber); + } + + private static int getRow(int pos, JTextComponent editor) { + int rn = (pos == 0) ? 1 : 0; + + try { + int offs = pos; + + while (offs > 0) { + offs = Utilities.getRowStart(editor, offs) - 1; + rn++; + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + return rn; + } + + private static int getColumn(int pos, JTextComponent editor) { + try { + return pos - Utilities.getRowStart(editor, pos) + 1; + } catch (BadLocationException e) { + e.printStackTrace(); + } + return -1; + } + + private void setBackgroundColor(final Color backgroundColor) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + scrollPane.getViewport().setBackground(backgroundColor); + editorPane.setBackground(backgroundColor); + } + }); + } + + private void setSelectionColor(final Color selectionColor) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + editorPane.setSelectionColor(selectionColor); + } + }); + } + + private void setSelectedTextColor(final Color selectedTextColor) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + editorPane.setSelectedTextColor(selectedTextColor); + } + }); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorThemeConfigDialog.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorThemeConfigDialog.java new file mode 100644 index 0000000..a773203 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/EditorThemeConfigDialog.java @@ -0,0 +1,978 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import javax.swing.*; +import javax.swing.filechooser.FileFilter; + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.ui.editor.theme.ColorAndStyle; +import net.sf.robocode.ui.editor.theme.ColorAndStyleAdapter; +import net.sf.robocode.ui.editor.theme.ComboBoxUtil; +import net.sf.robocode.ui.editor.theme.EditorPropertiesManager; +import net.sf.robocode.ui.editor.theme.EditorThemeProperties; +import net.sf.robocode.ui.editor.theme.EditorThemePropertiesManager; +import net.sf.robocode.ui.editor.theme.IEditorThemeProperties; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.GraphicsEnvironment; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + + +/** + * @author Flemming N. Larsen (original) + * + * @since 1.8.3.0 + */ +@SuppressWarnings("serial") +public class EditorThemeConfigDialog extends JDialog { + + private static final boolean ONLY_MONOSPACED = true; + + private static final String[] FONT_SIZES = { + "8", "9", "10", "11", "12", "14", "16", "18", "20", "22", "24", "26", "28", "36", "48", "72" + }; + + private JButton saveButton; + private JButton closeButton; + + private JComboBox fontNameComboBox; + private JComboBox fontStyleComboBox; + private JComboBox fontSizeComboBox; + + private JLabel previewLabel; + + private JComboBox themeComboBox; + + private ColorAndStyle backgroundColorAndStyle; + private ColorAndStyle lineNumberBackgroundColorAndStyle; + private ColorAndStyle lineNumberTextColorAndStyle; + private ColorAndStyle highlightedLineColorAndStyle; + private ColorAndStyle selectionColorAndStyle; + private ColorAndStyle selectedTextColorAndStyle; + private ColorAndStyle normalTextColorAndStyle; + private ColorAndStyle quotedTextColorAndStyle; + private ColorAndStyle keywordTextColorAndStyle; + private ColorAndStyle literalTextColorAndStyle; + private ColorAndStyle annotationTextColorAndStyle; + private ColorAndStyle commentTextColorAndStyle; + + private final EventHandler eventHandler = new EventHandler(); + + public EditorThemeConfigDialog(JFrame owner) { + super(owner, true); + initialize(); + } + + private void initialize() { + setTitle("Editor Theme Configurator"); + setLayout(new GridBagLayout()); + setResizable(false); + + // Initialize the font and theme ---- + initializeFontAndTheme(); + + getSaveButton().setEnabled(false); + + // ---- General font settings ---- + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.insets = new Insets(5, 5, 5, 5); + gbc.anchor = GridBagConstraints.WEST; + + int gridy = 0; + + gbc.gridx = 0; + gbc.gridy = gridy; + gbc.fill = GridBagConstraints.HORIZONTAL; + + gbc.weightx = 0.6; + add(getFontNamePanel(), gbc); + + gbc.gridx = 1; + gbc.weightx = 0.3; + add(getFontStylePanel(), gbc); + + gbc.gridx = 2; + gbc.weightx = 0.1; + add(getFontSizePanel(), gbc); + + gbc.gridx = 0; + gbc.gridy = ++gridy; + gbc.gridwidth = 3; + gbc.gridheight = 1; + + gbc.fill = GridBagConstraints.BOTH; + gbc.weightx = 1.0; + gbc.weighty = 1.0; + add(getPreviewPanel(), gbc); + + // ----- Theme settings ---- + + gbc.weightx = 0; + gbc.weighty = 0; + + gbc.gridx = 0; + gbc.gridy = ++gridy; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.gridwidth = 1; + add(getThemeComboBox(), gbc); + + // ---- Color buttons and font styles ---- + + gbc.gridwidth = 1; + + gbc.gridx = 0; + gbc.gridy = ++gridy; + gbc.gridwidth = 1; + + gbc.fill = GridBagConstraints.NONE; + + JPanel colorButtonsPanel = new JPanel(); + colorButtonsPanel.setLayout(new GridBagLayout()); + add(colorButtonsPanel, gbc); + + GridBagConstraints gbc2 = new GridBagConstraints(); + gbc2.insets = new Insets(5, 5, 5, 5); + gbc2.anchor = GridBagConstraints.WEST; + + int gridy2 = 0; + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getBackgroundColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getLineNumberBackgroundColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getLineNumberTextColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getHighlightedLineColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getSelectionColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getSelectedTextColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getNormalTextColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getCommentTextColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getQuotedTextColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getKeywordTextColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getLiteralTextColorAndStyle(), colorButtonsPanel, gbc2); + + gbc2.gridy = gridy2++; + addColoredButtonAndFontStyleToPanel(getAnnotationTextColorAndStyle(), colorButtonsPanel, gbc2); + + // ------ OK & Cancel buttons ---- + + JPanel okCancelPanel = new JPanel(); + okCancelPanel.add(getSaveButton()); + okCancelPanel.add(getCloseButton(), gbc); + + gbc.gridy = ++gridy; + add(okCancelPanel, gbc); + } + + private JButton getSaveButton() { + if (saveButton == null) { + saveButton = new JButton("Save & Close"); + saveButton.setMnemonic('S'); + saveButton.addActionListener(eventHandler); + } + return saveButton; + } + + private JButton getCloseButton() { + if (closeButton == null) { + closeButton = new JButton("Close"); + closeButton.setMnemonic('C'); + closeButton.addActionListener(eventHandler); + } + return closeButton; + } + + private JComboBox getFontNameComboBox() { + if (fontNameComboBox == null) { + String[] fontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + List fontFamilyNameList = Arrays.asList(fontFamilyNames); + + List fontNameList = new ArrayList(); + + if (ONLY_MONOSPACED) { + for (String monospacedFontName : getMonospacedFontNames()) { + if (fontFamilyNameList.contains(monospacedFontName)) { + fontNameList.add(monospacedFontName); + } + } + } else { + fontNameList.addAll(fontFamilyNameList); + } + if (!fontNameList.contains("Monospaced")) { + fontNameList.add("Monospaced"); + } + Collections.sort(fontNameList); + + fontNameComboBox = new JComboBox(fontNameList.toArray()); + fontNameComboBox.setRenderer(new FontCellRenderer()); + + fontNameComboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + + String oldFontName = themeProps.getFontName(); + String newFontName = ComboBoxUtil.getSelectedName(fontNameComboBox); + if (!newFontName.equals(oldFontName)) { + String oldThemeName = themeProps.getThemeName(); + String newThemeName = ComboBoxUtil.getSelectedName(getThemeComboBox()); + if (newThemeName.equals(oldThemeName)) { + themeProps.setFontName(newFontName); + updateSaveButton(); + } + } + } + }); + } + return fontNameComboBox; + } + + private JComboBox getFontStyleComboBox() { + if (fontStyleComboBox == null) { + fontStyleComboBox = ComboBoxUtil.createFontStyleComboBox(FontStyle.PLAIN); + + fontStyleComboBox.addActionListener( + new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + + FontStyle oldFontStyle = themeProps.getNormalTextStyle(); + FontStyle newFontStyle = ComboBoxUtil.getSelectedStyle(getFontStyleComboBox()); + if (newFontStyle != oldFontStyle) { + themeProps.setNormalTextStyle(newFontStyle); + + ComboBoxUtil.setSelected(getNormalTextColorAndStyle().getFontStyleComboBox(), + (String) getFontStyleComboBox().getSelectedItem()); + + updateSaveButton(); + } + } + }); + } + return fontStyleComboBox; + } + + private JComboBox getFontSizeComboBox() { + if (fontSizeComboBox == null) { + fontSizeComboBox = new JComboBox(FONT_SIZES); + fontSizeComboBox.setSelectedIndex(5); + + fontSizeComboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + + int oldFontSize = themeProps.getFontSize(); + int newFontSize = Integer.parseInt((String) getFontSizeComboBox().getSelectedItem()); + if (newFontSize != oldFontSize) { + themeProps.setFontSize(newFontSize); + updateSaveButton(); + } + } + }); + } + return fontSizeComboBox; + } + + private JPanel getFontNamePanel() { + JPanel panel = new JPanel(); + JLabel label = new JLabel("Font Name"); + + panel.setLayout(new GridBagLayout()); + + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.NORTHWEST; + panel.add(label, gbc); + + gbc.gridx = 0; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + panel.add(getFontNameComboBox(), gbc); + + return panel; + } + + private JPanel getFontStylePanel() { + JPanel panel = new JPanel(); + JLabel label = new JLabel("Style"); + + panel.setLayout(new GridBagLayout()); + + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.NORTHWEST; + panel.add(label, gbc); + + gbc.gridx = 0; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + panel.add(getFontStyleComboBox(), gbc); + + return panel; + } + + private JPanel getFontSizePanel() { + JPanel panel = new JPanel(); + JLabel label = new JLabel("Size"); + + panel.setLayout(new GridBagLayout()); + + GridBagConstraints gbc = new GridBagConstraints(); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.anchor = GridBagConstraints.NORTHWEST; + panel.add(label, gbc); + + gbc.gridx = 0; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + panel.add(getFontSizeComboBox(), gbc); + + return panel; + } + + private JLabel getPreviewLabel() { + if (previewLabel == null) { + previewLabel = new JLabel("AaBbYyZz"); + } + return previewLabel; + } + + private JPanel getPreviewPanel() { + final JPanel panel = new JPanel(); + panel.setLayout(new GridBagLayout()); + + panel.setBorder(BorderFactory.createEtchedBorder()); + panel.setBackground(Color.WHITE); + panel.setForeground(Color.BLACK); + panel.setPreferredSize(new Dimension(400, 120)); + + ActionListener actionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setPreviewLabelFont(panel); + panel.repaint(); + } + }; + + getFontNameComboBox().addActionListener(actionListener); + getFontStyleComboBox().addActionListener(actionListener); + getFontSizeComboBox().addActionListener(actionListener); + + setPreviewLabelFont(panel); + panel.add(getPreviewLabel(), SwingConstants.CENTER); + + return panel; + } + + private ColorAndStyle getBackgroundColorAndStyle() { + if (backgroundColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + backgroundColorAndStyle = new ColorAndStyle("Background Color", props.getBackgroundColor(), null); + backgroundColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setBackgroundColor(newColor); + + updateSaveButton(); + } + }); + } + return backgroundColorAndStyle; + } + + private ColorAndStyle getLineNumberBackgroundColorAndStyle() { + if (lineNumberBackgroundColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + lineNumberBackgroundColorAndStyle = new ColorAndStyle("Line Number Background Color", + props.getLineNumberBackgroundColor(), null); + lineNumberBackgroundColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setLineNumberBackgroundColor(newColor); + + updateSaveButton(); + } + }); + } + return lineNumberBackgroundColorAndStyle; + } + + private ColorAndStyle getLineNumberTextColorAndStyle() { + if (lineNumberTextColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + lineNumberTextColorAndStyle = new ColorAndStyle("Line Number Text Color", props.getLineNumberTextColor(), + null); + lineNumberTextColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setLineNumberTextColor(newColor); + + updateSaveButton(); + } + }); + } + return lineNumberTextColorAndStyle; + } + + private ColorAndStyle getHighlightedLineColorAndStyle() { + if (highlightedLineColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + highlightedLineColorAndStyle = new ColorAndStyle("Highlighted Line Color", props.getHighlightedLineColor(), + null); + highlightedLineColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setHighlightedLineColor(newColor); + + updateSaveButton(); + } + }); + } + return highlightedLineColorAndStyle; + } + + private ColorAndStyle getSelectionColorAndStyle() { + if (selectionColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + selectionColorAndStyle = new ColorAndStyle("Selection Color", props.getSelectionColor(), null); + selectionColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setSelectionColor(newColor); + + updateSaveButton(); + } + }); + } + return selectionColorAndStyle; + } + + private ColorAndStyle getSelectedTextColorAndStyle() { + if (selectedTextColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + selectedTextColorAndStyle = new ColorAndStyle("Selected Text Color", props.getSelectedTextColor(), null); + selectedTextColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setSelectedTextColor(newColor); + } + }); + } + return selectedTextColorAndStyle; + } + + private ColorAndStyle getNormalTextColorAndStyle() { + if (normalTextColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + normalTextColorAndStyle = new ColorAndStyle("Normal Text Color", props.getNormalTextColor(), + props.getNormalTextStyle()); + normalTextColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setNormalTextColor(newColor); + + updateSaveButton(); + } + + @Override + public void styleChanged(FontStyle newStyle) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setNormalTextStyle(newStyle); + + updateSaveButton(); + + // Make sure to update the font style combo box + ComboBoxUtil.setSelected(getFontStyleComboBox(), newStyle); + } + }); + } + return normalTextColorAndStyle; + } + + private ColorAndStyle getQuotedTextColorAndStyle() { + if (quotedTextColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + quotedTextColorAndStyle = new ColorAndStyle("Quoted Text Color", props.getQuotedTextColor(), + props.getQuotedTextStyle()); + quotedTextColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setQuotedTextColor(newColor); + + updateSaveButton(); + } + + @Override + public void styleChanged(FontStyle newStyle) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setQuotedTextStyle(newStyle); + + updateSaveButton(); + } + }); + } + return quotedTextColorAndStyle; + } + + private ColorAndStyle getKeywordTextColorAndStyle() { + if (keywordTextColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + keywordTextColorAndStyle = new ColorAndStyle("Keyword Color", props.getKeywordTextColor(), + props.getKeywordTextStyle()); + keywordTextColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setKeywordTextColor(newColor); + + updateSaveButton(); + } + + @Override + public void styleChanged(FontStyle newStyle) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setKeywordTextStyle(newStyle); + + updateSaveButton(); + } + }); + } + return keywordTextColorAndStyle; + } + + private ColorAndStyle getLiteralTextColorAndStyle() { + if (literalTextColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + literalTextColorAndStyle = new ColorAndStyle("Literal Color", props.getLiteralTextColor(), + props.getLiteralTextStyle()); + literalTextColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setLiteralTextColor(newColor); + + updateSaveButton(); + } + + @Override + public void styleChanged(FontStyle newStyle) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setLiteralTextStyle(newStyle); + + updateSaveButton(); + } + }); + } + return literalTextColorAndStyle; + } + + private ColorAndStyle getAnnotationTextColorAndStyle() { + if (annotationTextColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + annotationTextColorAndStyle = new ColorAndStyle("Annotation Color", props.getAnnotationTextColor(), + props.getAnnotationTextStyle()); + annotationTextColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setAnnotationTextColor(newColor); + + updateSaveButton(); + } + + @Override + public void styleChanged(FontStyle newStyle) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setAnnotationTextStyle(newStyle); + + updateSaveButton(); + } + }); + } + return annotationTextColorAndStyle; + } + + private ColorAndStyle getCommentTextColorAndStyle() { + if (commentTextColorAndStyle == null) { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + commentTextColorAndStyle = new ColorAndStyle("Comment Color", props.getCommentTextColor(), + props.getCommentTextStyle()); + commentTextColorAndStyle.addListener(new ColorAndStyleAdapter() { + @Override + public void colorChanged(Color newColor) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setCommentTextColor(newColor); + + updateSaveButton(); + } + + @Override + public void styleChanged(FontStyle newStyle) { + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setCommentTextStyle(newStyle); + + updateSaveButton(); + } + }); + } + return commentTextColorAndStyle; + } + + private JComboBox getThemeComboBox() { + if (themeComboBox == null) { + final String fileExt = EditorThemePropertiesManager.getFileExt(); + + File[] themeFiles = FileUtil.getEditorThemeConfigDir().listFiles(new java.io.FileFilter() { + public boolean accept(File filepath) { + return filepath.getName().endsWith(fileExt); + } + }); + + List themeNames = new ArrayList(); + for (File file : themeFiles) { + String themeName = file.getName(); + themeName = themeName.substring(0, themeName.lastIndexOf(fileExt)); + themeNames.add(themeName); + } + + themeComboBox = new JComboBox(themeNames.toArray()); + themeComboBox.addActionListener(eventHandler); + } + return themeComboBox; + } + + private void setPreviewLabelFont(JPanel panel) { + String fontName = (String) getFontNameComboBox().getSelectedItem(); + int fontStyleFlags = FontStyle.fromName((String) getFontStyleComboBox().getSelectedItem()).getFontStyleFlags(); + int fontSize = Integer.parseInt((String) getFontSizeComboBox().getSelectedItem()); + + Font font = new Font(fontName, fontStyleFlags, fontSize); + + getPreviewLabel().setFont(font); + + FontMetrics fontMetrics = panel.getFontMetrics(font); + + int width = fontMetrics.stringWidth(getPreviewLabel().getText()); + int height = fontMetrics.getHeight(); + + getPreviewLabel().setPreferredSize(new Dimension(width, height)); + } + + private void initializeFontAndTheme() { + // Read the theme properties + IEditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + + // Set selected theme + ComboBoxUtil.setSelected(getThemeComboBox(), themeProps.getThemeName()); + + // Set selected font name + ComboBoxUtil.setSelected(getFontNameComboBox(), themeProps.getFontName()); + + // Set selected font style + ComboBoxUtil.setSelected(getFontStyleComboBox(), themeProps.getNormalTextStyle()); + + // Set selected font size + ComboBoxUtil.setSelected(getFontSizeComboBox(), "" + themeProps.getFontSize()); + } + + private class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + if (source.equals(getThemeComboBox())) { + performThemeComboBoxAction(); + } else if (e.getSource().equals(getSaveButton())) { + performSaveButtonAction(); + } else if (e.getSource().equals(getCloseButton())) { + dispose(); + } + } + } + + private List getMonospacedFontNames() { + List monospacedFontNames = new ArrayList(); + + Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); + for (Font font : allFonts) { + if (isMonospaced(font)) { + monospacedFontNames.add(font.getFontName()); + } + } + return monospacedFontNames; + } + + private boolean isMonospaced(Font font) { + FontMetrics fontMetrics = getFontMetrics(font); + + int lastCharWidth = -1; + + for (int charCode = 0; charCode < 128; charCode++) { + if (Character.isValidCodePoint(charCode) && (Character.isLetter(charCode) || Character.isDigit(charCode))) { + int charWidth = fontMetrics.charWidth((char) charCode); + if (lastCharWidth >= 0 && charWidth != lastCharWidth) { + return false; // font is not mono-spaced + } + lastCharWidth = charWidth; + } + } + return true; // font is mono-spaced + } + + private static void addColoredButtonAndFontStyleToPanel(ColorAndStyle group, JPanel panel, GridBagConstraints gbc) { + gbc.gridx = 0; + panel.add(group.getColoredButton(), gbc); + + gbc.gridx = 1; + panel.add(group.getLabel(), gbc); + + if (group.getFontStyleComboBox() != null) { + gbc.gridx = 2; + panel.add(group.getFontStyleComboBox(), gbc); + } + } + + private void udateComponentsTheme(final String themeName) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + // Store current theme name + EditorPropertiesManager.getEditorProperties().setThemeName(themeName); + EditorPropertiesManager.saveEditorProperties(); + + // Load theme properties + File filepath = EditorThemePropertiesManager.getFilepath(themeName); + EditorThemePropertiesManager.loadEditorThemeProperties(filepath); + + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + + ComboBoxUtil.setSelected(getFontNameComboBox(), themeProps.getFontName()); + ComboBoxUtil.setSelected(getFontSizeComboBox(), "" + themeProps.getFontSize()); + + getBackgroundColorAndStyle().setSelectedColor(themeProps.getBackgroundColor()); + + getLineNumberBackgroundColorAndStyle().setSelectedColor(themeProps.getLineNumberBackgroundColor()); + getLineNumberTextColorAndStyle().setSelectedColor(themeProps.getLineNumberTextColor()); + + getHighlightedLineColorAndStyle().setSelectedColor(themeProps.getHighlightedLineColor()); + + getSelectionColorAndStyle().setSelectedColor(themeProps.getSelectionColor()); + getSelectedTextColorAndStyle().setSelectedColor(themeProps.getSelectedTextColor()); + + getNormalTextColorAndStyle().setSelectedColor(themeProps.getNormalTextColor()); + getNormalTextColorAndStyle().setSelectedStyle(themeProps.getNormalTextStyle()); + + getCommentTextColorAndStyle().setSelectedColor(themeProps.getCommentTextColor()); + getCommentTextColorAndStyle().setSelectedStyle(themeProps.getCommentTextStyle()); + + getQuotedTextColorAndStyle().setSelectedColor(themeProps.getQuotedTextColor()); + getQuotedTextColorAndStyle().setSelectedStyle(themeProps.getQuotedTextStyle()); + + getKeywordTextColorAndStyle().setSelectedColor(themeProps.getKeywordTextColor()); + getKeywordTextColorAndStyle().setSelectedStyle(themeProps.getKeywordTextStyle()); + + getLiteralTextColorAndStyle().setSelectedColor(themeProps.getLiteralTextColor()); + getLiteralTextColorAndStyle().setSelectedStyle(themeProps.getLiteralTextStyle()); + + getAnnotationTextColorAndStyle().setSelectedColor(themeProps.getAnnotationTextColor()); + getAnnotationTextColorAndStyle().setSelectedStyle(themeProps.getAnnotationTextStyle()); + + updateSaveButton(); + } + }); + } + + private void updateSaveButton() { + EditorThemeProperties props = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + boolean enabled = props.isChanged(); + getSaveButton().setEnabled(enabled); + } + + private void performThemeComboBoxAction() { + EditorThemeProperties currentThemeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + + String oldThemeName = currentThemeProps.getThemeName(); + String newThemeName = (String) getThemeComboBox().getSelectedItem(); + if (!oldThemeName.equals(newThemeName)) { + if (currentThemeProps.isChanged()) { + Object[] options = { "Yes, save changes", "No, forget changes", "Cancel"}; + + int option = JOptionPane.showOptionDialog(null, + "Changes have been made to the theme:\n" + oldThemeName + + "\nDo you want save the changes to this theme?", + "Warning", + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[2]); + + if (option == JOptionPane.YES_OPTION) { + File filepath = EditorThemePropertiesManager.getFilepath(oldThemeName); + if (filepath != null && !filepath.exists()) { + try { + filepath.createNewFile(); + } catch (IOException e) { + Logger.logError(e); + return; + } + } + EditorThemePropertiesManager.saveEditorThemeProperties(filepath); + + } else if (option == JOptionPane.CANCEL_OPTION) { + ComboBoxUtil.setSelected(getThemeComboBox(), oldThemeName); + return; + } + } + // Switch to new theme + udateComponentsTheme(newThemeName); + } + } + + private void performSaveButtonAction() { + String themeName = "My theme"; + File file = EditorThemePropertiesManager.getFilepath(themeName); + + JFileChooser saveThemeDialog = new JFileChooser(FileUtil.getEditorThemeConfigDir()); + saveThemeDialog.setDialogTitle("Save Theme"); + saveThemeDialog.setSelectedFile(file); + + FileFilter fileFilter = new FileFilter() { + @Override + public boolean accept(File filepath) { + return filepath.getName().endsWith(EditorThemePropertiesManager.getFileExt()); + } + + @Override + public String getDescription() { + return "Robocode Editor Theme properties"; + } + }; + + saveThemeDialog.addChoosableFileFilter(fileFilter); + saveThemeDialog.setAcceptAllFileFilterUsed(false); + + int returnState = saveThemeDialog.showSaveDialog(this); + + file = saveThemeDialog.getSelectedFile(); + + if (!file.getName().endsWith(EditorThemePropertiesManager.getFileExt())) { + file = new File(file.getAbsolutePath() + EditorThemePropertiesManager.getFileExt()); + } + + if (!FileUtil.isFilenameValid(file.getName())) { + JOptionPane.showMessageDialog(this, "Not a valid file name:\n" + file.getName(), "Error", + JOptionPane.ERROR_MESSAGE); + + } else if (returnState == JFileChooser.APPROVE_OPTION) { + + if (file.exists()) { + Object[] options = { "Yes, overwrite", "No, do not overwrite"}; + + int option = JOptionPane.showOptionDialog(this, + "File already exists:\n" + file.getName() + "\nDo you want to overwrite this file?", "Warning", + JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[1]); + + if (option == JOptionPane.NO_OPTION) { + return; + } + } else { + try { + file.createNewFile(); // File must be created if it does not exist already + } catch (IOException e) { + Logger.logError(e); + return; + } + } + + ComboBoxUtil.setSelected(getThemeComboBox(), themeName); + EditorPropertiesManager.getEditorProperties().setThemeName(themeName); + EditorPropertiesManager.saveEditorProperties(); + + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + themeProps.setThemeName(themeName); + + themeProps.setFontName(ComboBoxUtil.getSelectedName(getFontNameComboBox())); + themeProps.setFontSize(Integer.parseInt(ComboBoxUtil.getSelectedName(getFontSizeComboBox()))); + + EditorThemePropertiesManager.saveEditorThemeProperties(file); + + dispose(); // Only when save was successful + + } else if (returnState == JFileChooser.ERROR_OPTION) { + JOptionPane.showMessageDialog(this, "The editor theme was not saved.", "Warning", + JOptionPane.WARNING_MESSAGE); + } + } + + private class FontCellRenderer extends DefaultListCellRenderer { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + Font font = new Font((String) value, Font.PLAIN, 20); + if (font.canDisplayUpTo(label.getText()) == -1) { // -1 means, can display all of the string + label.setFont(font); + } + return label; + } + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/FindReplaceDialog.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/FindReplaceDialog.java new file mode 100644 index 0000000..fedc9c9 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/FindReplaceDialog.java @@ -0,0 +1,386 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import static javax.swing.GroupLayout.Alignment.*; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +/** + * @author Matthew Reeder (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class FindReplaceDialog extends JDialog implements ActionListener { + private JTextField findTextField; + private JTextField replaceTextField; + private JButton findNextButton; + private JButton replaceFindButton; + private JButton replaceButton; + private JButton replaceAllButton; + private JButton closeButton; + private JCheckBox caseSensitiveCheckBox; + private JCheckBox wholeWordCheckBox; + private JRadioButton regexButton; + private JRadioButton wildCardsButton; + private JRadioButton literalButton; + private JLabel findLabel; + private JLabel replaceLabel; + private boolean initLoc; + private final RobocodeEditor editor; + + public FindReplaceDialog(RobocodeEditor owner) { + super(owner, false); + editor = owner; + + GroupLayout layout = new GroupLayout(getContentPane()); + + getContentPane().setLayout(layout); + layout.setAutoCreateGaps(true); + layout.setAutoCreateContainerGaps(true); + + JPanel optionsPanel = new JPanel(); + + optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS)); + optionsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Options")); + optionsPanel.add(getCaseSensitiveCheckBox()); + optionsPanel.add(getWholeWordCheckBox()); + optionsPanel.setAlignmentY(TOP_ALIGNMENT); + + JPanel usePanel = new JPanel(); + + usePanel.setLayout(new BoxLayout(usePanel, BoxLayout.Y_AXIS)); + usePanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Use")); + usePanel.add(getLiteralButton()); + usePanel.add(getWildCardsButton()); + usePanel.add(getRegexButton()); + usePanel.setAlignmentY(TOP_ALIGNMENT); + + ButtonGroup buttonGroup = new ButtonGroup(); + + buttonGroup.add(getLiteralButton()); + buttonGroup.add(getWildCardsButton()); + buttonGroup.add(getRegexButton()); + + layout.setHorizontalGroup( + layout.createSequentialGroup().addGroup(layout.createParallelGroup(LEADING).addGroup(layout.createSequentialGroup().addComponent(getFindLabel()).addComponent(getFindTextField())).addGroup(layout.createSequentialGroup().addComponent(getReplaceLabel()).addComponent(getReplaceTextField())).addGroup(layout.createSequentialGroup().addComponent(optionsPanel).addComponent(usePanel))).addGroup( + layout.createParallelGroup(LEADING).addComponent(getFindNextButton()).addComponent(getReplaceFindButton()).addComponent(getReplaceButton()).addComponent(getReplaceAllButton()).addComponent( + getCloseButton()))); + + layout.linkSize(SwingConstants.HORIZONTAL, getFindLabel(), getReplaceLabel()); + layout.linkSize(SwingConstants.HORIZONTAL, getFindNextButton(), getReplaceFindButton(), getReplaceButton(), + getReplaceAllButton(), getCloseButton()); + + layout.setVerticalGroup( + layout.createSequentialGroup().addGroup(layout.createParallelGroup(BASELINE).addComponent(getFindLabel()).addComponent(getFindTextField()).addComponent(getFindNextButton())).addGroup(layout.createParallelGroup(BASELINE).addComponent(getReplaceLabel()).addComponent(getReplaceTextField()).addComponent(getReplaceButton())).addGroup( + layout.createParallelGroup(BASELINE).addComponent(optionsPanel).addComponent(usePanel).addGroup( + layout.createSequentialGroup().addComponent(getReplaceFindButton()).addComponent(getReplaceAllButton()).addComponent( + getCloseButton())))); + + pack(); + setResizable(false); + } + + public void showDialog(boolean showReplace) { + getReplaceLabel().setVisible(showReplace); + getReplaceTextField().setVisible(showReplace); + getReplaceButton().setVisible(showReplace); + getReplaceAllButton().setVisible(showReplace); + if (showReplace) { + setTitle("Replace"); + getRootPane().setDefaultButton(getReplaceButton()); + getReplaceFindButton().setText("Find..."); + getReplaceFindButton().setMnemonic('d'); + getReplaceFindButton().setDisplayedMnemonicIndex(3); + } else { + setTitle("Find"); + getRootPane().setDefaultButton(getFindNextButton()); + getReplaceFindButton().setText("Replace..."); + getReplaceFindButton().setMnemonic('R'); + getReplaceFindButton().setDisplayedMnemonicIndex(0); + } + + pack(); + + if (!initLoc && editor != null) { + Rectangle bounds = editor.getBounds(); + Dimension size = getSize(); + + setLocation((int) (bounds.getX() + (bounds.getWidth() - size.getWidth()) / 2), + (int) (bounds.getY() + (bounds.getHeight() - size.getHeight()) / 2)); + initLoc = true; + } + + // Bugfix [2664844] - Editor: Find (set cursor position) + getFindTextField().requestFocus(); + + setVisible(true); + } + + public JLabel getFindLabel() { + if (findLabel == null) { + findLabel = new JLabel(); + findLabel.setText("Find:"); + findLabel.setDisplayedMnemonicIndex(3); + } + return findLabel; + } + + public JLabel getReplaceLabel() { + if (replaceLabel == null) { + replaceLabel = new JLabel(); + replaceLabel.setText("Replace:"); + replaceLabel.setDisplayedMnemonicIndex(3); + } + return replaceLabel; + } + + public JTextField getFindTextField() { + if (findTextField == null) { + findTextField = new JTextField(); + findTextField.setFocusAccelerator('n'); + findTextField.addActionListener(this); + } + return findTextField; + } + + public JTextField getReplaceTextField() { + if (replaceTextField == null) { + replaceTextField = new JTextField(); + replaceTextField.setFocusAccelerator('p'); + replaceTextField.addActionListener(this); + } + return replaceTextField; + } + + public JButton getFindNextButton() { + if (findNextButton == null) { + findNextButton = new JButton(); + findNextButton.setText("Find Next"); + findNextButton.setMnemonic('F'); + findNextButton.setDefaultCapable(true); + findNextButton.addActionListener(this); + } + return findNextButton; + } + + public JButton getReplaceFindButton() { + if (replaceFindButton == null) { + replaceFindButton = new JButton("Replace..."); + replaceFindButton.setMnemonic('R'); + replaceFindButton.addActionListener(this); + } + return replaceFindButton; + } + + public JButton getReplaceButton() { + if (replaceButton == null) { + replaceButton = new JButton(); + replaceButton.setText("Replace"); + replaceButton.setMnemonic('R'); + replaceButton.setDefaultCapable(true); + replaceButton.addActionListener(this); + } + return replaceButton; + } + + public JButton getReplaceAllButton() { + if (replaceAllButton == null) { + replaceAllButton = new JButton(); + replaceAllButton.setText("Replace All"); + replaceAllButton.setMnemonic('A'); + replaceAllButton.setDisplayedMnemonicIndex(8); + replaceAllButton.addActionListener(this); + } + return replaceAllButton; + } + + public JButton getCloseButton() { + if (closeButton == null) { + closeButton = new JButton(); + closeButton.setText("Close"); + closeButton.setMnemonic('C'); + closeButton.addActionListener(this); + } + return closeButton; + } + + public JCheckBox getCaseSensitiveCheckBox() { + if (caseSensitiveCheckBox == null) { + caseSensitiveCheckBox = new JCheckBox(); + caseSensitiveCheckBox.setText("Case Sensitive"); + caseSensitiveCheckBox.setMnemonic('v'); + caseSensitiveCheckBox.setDisplayedMnemonicIndex(12); + caseSensitiveCheckBox.addActionListener(this); + } + return caseSensitiveCheckBox; + } + + public JCheckBox getWholeWordCheckBox() { + if (wholeWordCheckBox == null) { + wholeWordCheckBox = new JCheckBox(); + wholeWordCheckBox.setText("Whole Words Only"); + wholeWordCheckBox.setMnemonic('W'); + wholeWordCheckBox.addActionListener(this); + } + return wholeWordCheckBox; + } + + public JRadioButton getLiteralButton() { + if (literalButton == null) { + literalButton = new JRadioButton(); + literalButton.setText("Literal"); + literalButton.setMnemonic('L'); + literalButton.setSelected(true); + literalButton.addActionListener(this); + } + return literalButton; + } + + public JRadioButton getWildCardsButton() { + if (wildCardsButton == null) { + wildCardsButton = new JRadioButton(); + wildCardsButton.setText("Wild Cards"); + wildCardsButton.setMnemonic('i'); + wildCardsButton.setDisplayedMnemonicIndex(1); + wildCardsButton.addActionListener(this); + } + return wildCardsButton; + } + + public JRadioButton getRegexButton() { + if (regexButton == null) { + regexButton = new JRadioButton(); + regexButton.setText("Regular Expressions"); + regexButton.setMnemonic('x'); + regexButton.setDisplayedMnemonicIndex(9); + regexButton.addActionListener(this); + } + return regexButton; + } + + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + + if (source == getFindNextButton()) { + findNext(); + } else if (source == getReplaceButton()) { + doReplacement(); + findNext(); + } else if (source == getReplaceAllButton()) { + doReplaceAll(); + } else if (source == getCloseButton()) { + setVisible(false); + } else if (source == getReplaceFindButton()) { + showDialog(!getReplaceButton().isVisible()); + } else if (source instanceof JTextField) { + getRootPane().getDefaultButton().doClick(); + } + } + + private Pattern getCurrentPattern() { + String pattern = getFindTextField().getText(); + int flags = Pattern.DOTALL; + + if (!getRegexButton().isSelected()) { + StringBuffer newpattern = new StringBuffer(); + + // 'quote' the pattern + for (int i = 0; i < pattern.length(); i++) { + if ("\\[]^$&|().*+?{}".indexOf(pattern.charAt(i)) >= 0) { + newpattern.append('\\'); + } + newpattern.append(pattern.charAt(i)); + } + pattern = newpattern.toString(); + + // make "*" .* and "?" . + if (getWildCardsButton().isSelected()) { + pattern = pattern.replaceAll("\\\\\\*", ".+?"); + pattern = pattern.replaceAll("\\\\\\?", "."); + } + } + if (!getCaseSensitiveCheckBox().isSelected()) { + flags |= Pattern.CASE_INSENSITIVE; + } + if (getWholeWordCheckBox().isSelected()) { + pattern = "\\b" + pattern + "\\b"; + } + return Pattern.compile(pattern, flags); + } + + public void findNext() { + EditWindow currentWindow = editor.getActiveWindow(); + + if (currentWindow == null || getFindTextField().getText().length() == 0) { + // launch error dialog? + return; + } + Pattern p = getCurrentPattern(); + JEditorPane editorPane = currentWindow.getEditorPane(); + + // for some reason, getText() trims off \r but the indexes in + // the editor pane don't. + String text = editorPane.getText().replaceAll("\\r", ""); + Matcher m = p.matcher(text); + int index = editorPane.getSelectionEnd(); + + if (!(m.find(index) || m.find())) { + return; + } + editorPane.setSelectionStart(m.start()); + editorPane.setSelectionEnd(m.end()); + } + + public void doReplacement() { + EditWindow currentWindow = editor.getActiveWindow(); + + if (currentWindow == null || getFindTextField().getText().length() == 0) { + // launch error dialog? + return; + } + JEditorPane editorPane = currentWindow.getEditorPane(); + String text = editorPane.getSelectedText(); + + if (text == null) { + // no selection + return; + } + Matcher m = getCurrentPattern().matcher(text); + + if (m.matches()) { + String replacement = getReplaceTextField().getText(); + + if (getRegexButton().isSelected()) { + replacement = m.replaceFirst(replacement); + } + editorPane.replaceSelection(replacement); + } + } + + public void doReplaceAll() { + EditWindow currentWindow = editor.getActiveWindow(); + + if (currentWindow == null || getFindTextField().getText().length() == 0) { + // launch error dialog? + return; + } + JEditorPane editorPane = currentWindow.getEditorPane(); + String text = editorPane.getText(); + + String replacement = getReplaceTextField().getText(); + + editorPane.setText(getCurrentPattern().matcher(text).replaceAll(replacement)); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/FontStyle.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/FontStyle.java new file mode 100644 index 0000000..c593c2e --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/FontStyle.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import java.awt.Font; + + +/** + * Font style enumeration type, which provides an abstraction over the style flags from + * the integer flags from the {@link Font#getStyle()} method. + * + * @author Flemming N. Larsen (original) + */ +public enum FontStyle { + + PLAIN(Font.PLAIN, "Plain"), + BOLD(Font.BOLD, "Bold"), + ITALIC(Font.ITALIC, "Italic"), + BOLD_ITALIC(Font.BOLD + Font.ITALIC, "Bold Italic"); + + private final int fontStyleFlags; + private final String name; + + private FontStyle(int fontStyleFlags, String name) { + this.fontStyleFlags = fontStyleFlags; + this.name = name; + } + + public static FontStyle fromName(String name) { + for (FontStyle value : values()) { + if (value.name.equalsIgnoreCase(name)) { + return value; + } + } + return null; + } + + public static FontStyle fromStyleFlags(int flags) { + for (FontStyle value : values()) { + if (value.fontStyleFlags == flags) { + return value; + } + } + return null; + } + + public int getFontStyleFlags() { + return fontStyleFlags; + } + + public String getName() { + return name; + } + + public boolean isBold() { + return this == BOLD || this == BOLD_ITALIC; + } + + public boolean isItalic() { + return this == ITALIC || this == BOLD_ITALIC; + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/IEditorProperties.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/IEditorProperties.java new file mode 100644 index 0000000..40f090d --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/IEditorProperties.java @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +/** + * Interface for editor properties. + * + * @author Flemming N. Larsen (original) + * + * @since 1.8.3.0 + */ +public interface IEditorProperties { + + String getThemeName(); +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/JavaDocument.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/JavaDocument.java new file mode 100644 index 0000000..7497f42 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/JavaDocument.java @@ -0,0 +1,1137 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import javax.swing.JViewport; +import javax.swing.SwingUtilities; +import javax.swing.event.ChangeListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.*; + +import net.sf.robocode.ui.editor.theme.EditorThemePropertiesManager; +import net.sf.robocode.ui.editor.theme.EditorThemePropertyChangeAdapter; +import net.sf.robocode.ui.editor.theme.IEditorThemeProperties; +import net.sf.robocode.util.StringUtil; + + +// FIXME: Column in status bar does not take tab size into account + +// TODO: Make it configurable to extend the Java keywords. +// TODO: Highlight methods from Robocode API? +// TODO: Highlight numbers? +// TODO: Method names and method invocations in bold? +// TODO: Trim trailing white-spaces from all lines? + +/** + * Represents a styled Java document used for syntax high-lightning. + * + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class JavaDocument extends StyledDocument { + + /** The text pane this document is used with necessary for setting the caret position when auto indenting */ + private final EditorPane textPane; + + /** Flag defining if the contained text is being loaded or replaced externally */ + private boolean isReplacingText; + + // Indentation // + + /** Flag defining if auto indentation is enabled */ + private boolean isAutoIndentEnabled = true; + + /** Flag defining if spaces must be used for indentation; otherwise tabulation characters are being used */ + private boolean useSpacesForIndentation = false; + + /** Tab size (column width) */ + private int tabSize = 4; // Default is every 4th column + + /** Java language quote delimiter characters represented in a string */ + private static final String QUOTE_DELIMITERS = "\"'"; + + /** Java keywords */ + private static final Set KEYWORDS = new HashSet( + Arrays.asList( + new String[] { + "abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", + "default", "do", "double", "else", "enum", "extends", "final", "finally", "float", "for", "goto", "if", + "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "package", "private", + "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", + "throw", "throws", "transient", "try", "void", "volatile", "while" })); + + /** Predefined Java literals */ + private static final Set PREDEFINED_LITERALS = new HashSet( + Arrays.asList(new String[] { "false", "true", "null" })); + + /** Normal text attribute set */ + private final SimpleAttributeSet normalAttrSet = new SimpleAttributeSet(); + + /** Quoted text attribute set */ + private final SimpleAttributeSet quoteAttrSet = new SimpleAttributeSet(); + + /** Keyword attribute set */ + private final SimpleAttributeSet keywordAttrSet = new SimpleAttributeSet(); + + /** Predefined literal attribute set */ + private final SimpleAttributeSet literalAttrSet = new SimpleAttributeSet(); + + /** Annotation attribute set */ + private final SimpleAttributeSet annotationAttrSet = new SimpleAttributeSet(); + + /** Comment attribute set */ + private SimpleAttributeSet commentAttrSet = new SimpleAttributeSet(); + + /** String buffer holding only space characters for fast replacement of tabulator characters */ + private String spaceBuffer; + + /** Old start offset for syntax highlighting */ + private int lastSyntaxHighlightStartOffset; + + /** Old end offset for syntax highlighting */ + private int lastSyntaxHighlightEndOffset; + + private int autoIndentationCaretPos = -1; + + private boolean updateSyntaxHighlightingEDTidle = true; + + /** + * Constructor that creates a Java document. + * + * @param textPane + * is the text pane that this Java documents must apply to. + */ + public JavaDocument(EditorPane textPane) { + super(); + this.textPane = textPane; + + // Setup text colors and styles + setTextColorsAndStyles(null); + + // Setup document listener in order to update caret position and update syntax highlighting + addDocumentListener(new JavaDocumentListener()); + + // Setup editor properties change listener + EditorThemePropertiesManager.addListener(new EditorThemePropertyChangeAdapter() { + @Override + public void onNormalTextColorChanged(Color newColor) { + setNormalTextColor(newColor); + updateSyntaxHighlighting(true); + } + + @Override + public void onNormalTextStyleChanged(FontStyle newStyle) { + setNormalTextStyle(newStyle); + updateSyntaxHighlighting(true); + } + + @Override + public void onQuotedTextColorChanged(Color newColor) { + setQuotedTextColor(newColor); + updateSyntaxHighlighting(true); + } + + @Override + public void onQuotedTextStyleChanged(FontStyle newStyle) { + setQuotedTextStyle(newStyle); + updateSyntaxHighlighting(true); + } + + @Override + public void onKeywordTextColorChanged(Color newColor) { + setKeywordTextColor(newColor); + updateSyntaxHighlighting(true); + } + + @Override + public void onKeywordTextStyleChanged(FontStyle newStyle) { + setKeywordTextStyle(newStyle); + updateSyntaxHighlighting(true); + } + + @Override + public void onLiteralTextColorChanged(Color newColor) { + setLiteralTextColor(newColor); + updateSyntaxHighlighting(true); + } + + @Override + public void onLiteralTextStyleChanged(FontStyle newStyle) { + setLiteralTextStyle(newStyle); + updateSyntaxHighlighting(true); + } + + @Override + public void onAnnotationTextColorChanged(Color newColor) { + setAnnotationTextColor(newColor); + updateSyntaxHighlighting(true); + } + + @Override + public void onAnnotationTextStyleChanged(FontStyle newStyle) { + setAnnotationTextStyle(newStyle); + updateSyntaxHighlighting(true); + } + + @Override + public void onCommentTextColorChanged(Color newColor) { + setCommentTextColor(newColor); + updateSyntaxHighlighting(true); + } + + @Override + public void onCommentTextStyleChanged(FontStyle newStyle) { + setCommentTextStyle(newStyle); + updateSyntaxHighlighting(true); + } + }); + + // Setup change listener and focus listener on the viewport of the text pane + + JViewport viewport = textPane.getViewport(); + + viewport.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + updateSyntaxHighlighting(false); + } + }); + + viewport.addFocusListener(new FocusListener() { + public void focusGained(FocusEvent e) { + updateSyntaxHighlighting(false); + } + + public void focusLost(FocusEvent e) {} + }); + } + + /** + * Checks if auto indentation is enabled. + * + * @return true if auto indentation is enabled; false otherwise. + */ + public boolean isAutoIndentEnabled() { + return isReplacingText ? false : isAutoIndentEnabled; + } + + /** + * Enable or disable auto indentation. + * + * @param enable is set to true, if auto indentation must be enabled; false is auto indentation must be disabled. + */ + public void setAutoIndentEnabled(boolean enable) { + isAutoIndentEnabled = enable; + } + + /** + * Checks if the contained text is currently being replaced externally. + * + * @return true if the text is being replaced; false otherwise. + */ + public boolean isReplacingText() { + return isReplacingText; + } + + /** + * Sets the flag if the contained text is currently being replaced externally or not. + * + * @param isReplacingText is true if the text is currently being replaced; false otherwise. + */ + public void setReplacingText(boolean isReplacingText) { + this.isReplacingText = isReplacingText; + } + + @Override + public void insertString(int offset, String str, AttributeSet a) throws BadLocationException { + // Process auto indentation on inserted string + final Indentation indent = applyAutoIndentation(offset, str); + + // Replace indentation tabulation characters with spaces if spaces must be used instead of tabulation characters + str = replaceTabulatorCharacters(getEndOffset(getElementFromOffset(offset)), indent.text); + + // Set the new caret position on the text pane if the caret position has been set + autoIndentationCaretPos = indent.caretPos; + + // Insert the modified string using the original method for inserting string into this document + super.insertString(offset, str, a); + } + + /** + * Sets the tabulation column size. + * + * @param tabSize + * is the new tabulation column size, which must be >= 1. + */ + public void setTabSize(int tabSize) { + this.tabSize = tabSize; + } + + private void setTextColorsAndStyles(IEditorThemeProperties themeProps) { + if (themeProps == null) { + themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + } + setNormalTextColor(themeProps.getNormalTextColor()); + setNormalTextStyle(themeProps.getNormalTextStyle()); + setQuotedTextColor(themeProps.getQuotedTextColor()); + setQuotedTextStyle(themeProps.getQuotedTextStyle()); + setKeywordTextColor(themeProps.getKeywordTextColor()); + setKeywordTextStyle(themeProps.getKeywordTextStyle()); + setLiteralTextColor(themeProps.getLiteralTextColor()); + setLiteralTextStyle(themeProps.getLiteralTextStyle()); + setAnnotationTextColor(themeProps.getAnnotationTextColor()); + setAnnotationTextStyle(themeProps.getAnnotationTextStyle()); + setCommentTextColor(themeProps.getCommentTextColor()); + setCommentTextStyle(themeProps.getCommentTextStyle()); + } + + private void setNormalTextColor(Color newColor) { + StyleConstants.setForeground(normalAttrSet, newColor); + } + + private void setNormalTextStyle(FontStyle newStyle) { + StyleConstants.setBold(normalAttrSet, newStyle.isBold()); + StyleConstants.setItalic(normalAttrSet, newStyle.isItalic()); + } + + private void setQuotedTextColor(Color newColor) { + StyleConstants.setForeground(quoteAttrSet, newColor); + } + + private void setQuotedTextStyle(FontStyle newStyle) { + StyleConstants.setBold(quoteAttrSet, newStyle.isBold()); + StyleConstants.setItalic(quoteAttrSet, newStyle.isItalic()); + } + + private void setKeywordTextColor(Color newColor) { + StyleConstants.setForeground(keywordAttrSet, newColor); + } + + private void setKeywordTextStyle(FontStyle newStyle) { + StyleConstants.setBold(keywordAttrSet, newStyle.isBold()); + StyleConstants.setItalic(keywordAttrSet, newStyle.isItalic()); + } + + private void setLiteralTextColor(Color newColor) { + StyleConstants.setForeground(literalAttrSet, newColor); + } + + private void setLiteralTextStyle(FontStyle newStyle) { + StyleConstants.setBold(literalAttrSet, newStyle.isBold()); + StyleConstants.setItalic(literalAttrSet, newStyle.isItalic()); + } + + private void setAnnotationTextColor(Color newColor) { + StyleConstants.setForeground(annotationAttrSet, newColor); + } + + private void setAnnotationTextStyle(FontStyle newStyle) { + StyleConstants.setBold(annotationAttrSet, newStyle.isBold()); + StyleConstants.setItalic(annotationAttrSet, newStyle.isItalic()); + } + + private void setCommentTextColor(Color newColor) { + StyleConstants.setForeground(commentAttrSet, newColor); + } + + private void setCommentTextStyle(FontStyle newStyle) { + StyleConstants.setBold(commentAttrSet, newStyle.isBold()); + StyleConstants.setItalic(commentAttrSet, newStyle.isItalic()); + } + + /** + * Applies indentation for an inserted string at a given offset if auto indentation is enabled. + * + * @param offset + * is the offset of the inserted string. + * @param str + * is the inserted string. + * @return an Indentation container with indentation details. + * @throws BadLocationException + */ + private Indentation applyAutoIndentation(int offset, String str) throws BadLocationException { + // Prepare indentation container + Indentation indentation = new Indentation(); + + indentation.caretPos = -1; // Meaning that caret position is not changed + indentation.text = str; + + // Apply auto indentation if it is enabled, and the new line character has been entered + if (isAutoIndentEnabled() && str.equals("\n")) { + + // Save the current indentation for later, as it might change from here on + int currentIndentation = getIndentationLengthFromOffset(offset); + + // Read the line content from the offset + String line = getLineFromOffset(offset); + + // Calculate the end offset of the line + int lineEndOffset = getElementFromOffset(offset).getStartOffset() + line.length(); + + // Continue if the line has content and the offset is after the line end offset + if (line.length() > 0 && offset >= lineEndOffset) { + + // Check/compose and return a body start indentation a '{' is found + if (composeBodyStartIndentation(offset, line, indentation)) { + return indentation; + } + // Check/compose and return a multiline comment start indentation if a '/*' is found + if (composeMultilineCommentStartIndentation(offset, line, indentation)) { + return indentation; + } + // Check/compose and return a continued multiline comment if a '*' is found inside a multiline comment + if (composeMultilineCommentContinuedIndentation(offset, line, indentation)) { + return indentation; + } + // Check/compose and return a multiline comment end indentation if a '*/' is found + if (composeMultilineCommentEndIndentation(offset, line, indentation)) { + return indentation; + } + // Extend the current indentation text based on the current indentation + // Note: Will replace tabulator characters with spaces etc. if this must be done. + indentation.text += getStartIndentation(currentIndentation); // FIXME + } + } + return indentation; + } + + /** + * Returns a string where tabulator characters in the given string is replaced with spaces, but only if these must + * be replaced with spaces by configuration. + * + * @param startIndex + * is the start index of the string in a line used for determine the current tabulator column. + * @param str + * is the string containing tabulator characters that might need to be replaced with spaces. + * @return a string where tabulator characters might have been replaced with spaces. + */ + private String replaceTabulatorCharacters(int startIndex, String str) { + // Check if tabulator characters needs to be replaced with space characters + if (useSpacesForIndentation) { + // Prepare string buffer containing replaced text + StringBuilder sb = new StringBuilder(); + + int tabIndex; // Index of current tabulator character + + // Run loop as long as we find a tabulator character from the start index + while ((tabIndex = str.indexOf('\t', startIndex)) >= 0) { + // Put the current text (non tabulator characters) into the string buffer + sb.append(str.substring(startIndex, tabIndex)); + + // Calculate the number of spaces that remain before the next tabulator column + int numSpaces = tabSize - (sb.length() % tabSize); + + // Run loop while the follower character is a tabulator character + while (++tabIndex < str.length() && str.charAt(tabIndex) == '\t') { + // Increment the number of spaces that to use to replace tabulator characters with the tabulator + // column size. + numSpaces += tabSize; + } + // Append the calculated number of space characters to replace the tabulator characters + sb.append(getSpaces(numSpaces)); + + // The new start index is the current tabulator index + startIndex = tabIndex; + } + // Append the text that remain to the string buffer from the current start index + sb.append(str.substring(startIndex)); + + // Set the result to the build string from the string buffer + str = sb.toString(); + } + // Return the resulting string + return str; + } + + /** + * Returns a string containing a specific number of spaces only. + * + * @param count + * is the number of spaces the the string should contain. + * @return a string containing only the given number of space characters. + */ + private String getSpaces(int count) { + if (count == 0) { + return ""; + } + // Determine the current buffer size + int bufferSize = (spaceBuffer == null) ? 0 : spaceBuffer.length(); + + // Check if we need to reallocate the buffer to accommodate the given number of spaces + if (count > bufferSize) { + // Determine the new buffer size, which is set to twice the number of spaces, but minimum 100 characters + bufferSize = Math.max(2 * count, 100); + // Create a new string containing spaces with the new buffer size + char[] chars = new char[bufferSize]; + + Arrays.fill(chars, ' '); + spaceBuffer = new String(chars); + } + // Return a string containing the given number of spaces + return spaceBuffer.substring(0, count); + } + + /** + * Composes a body start indentation block starting with a '{' and ending with a '}' and update the caret position. + * + * @param offset + * is the offset of the inserted string. + * @param line + * is the line, where the indentation block must be appended to. + * @param indentation + * is containing the current indentation date. + * @return true if a body start indentation block should be inserted after the given line; false otherwise. + * @throws BadLocationException + */ + private boolean composeBodyStartIndentation(int offset, String line, Indentation indentation) + throws BadLocationException { + // Check if the given line ends with a body start character, i.e. '{' + if (line.endsWith("{")) { + // We only start a new body indentation if the number of body start characters in the first part of the + // text up to specified offset lesser than the number of body end characters in the last part of the text + String textFirstHalf = getText(0, offset); + String textLastHalf = getText(offset, getLength() - offset); + if (StringUtil.countChar(textLastHalf, '}') >= StringUtil.countChar(textFirstHalf, '{')) { + return false; + } + // Calculated current start indentation length from the given offset + int startIndentLen = getIndentationLengthFromOffset(offset); + // Calculate the start indentation string + String startIndent = getStartIndentation(startIndentLen); + // Prapare buffer for containing the indentation block + StringBuilder sb = new StringBuilder("\n"); + + // Append new indented line to the buffer, that is indented based on the start indentation + sb.append(getStartIndentation(startIndentLen + tabSize)).append('\n'); + // Update the caret position to be placed in the end of the new indented line + indentation.caretPos = offset + sb.toString().length() - 1; + // Append the body end character on a new line + sb.append(startIndent).append('}'); + // Set the indentation block text to the string containing from the buffer + indentation.text = sb.toString(); + // Indentation block was created + return true; + } + // Indentation block was not created + return false; + } + + /** + * Composes a multiline comment start indentation block. + * + * @param offset + * is the offset of the inserted string. + * @param line + * is the line, where the indentation block must be appended to. + * @param indentation + * is containing the current indentation date. + * @return true if a multiline comment start indentation block should be inserted after the given line; false + * otherwise. + * @throws BadLocationException + */ + private boolean composeMultilineCommentStartIndentation(int offset, String line, Indentation indentation) + throws BadLocationException { + + // Check if the given line contains a multiline start string, i.e. '/*' + if (line.trim().startsWith("/*")) { + // Calculated current start indentation length from the given offset + int startIndentLen = getIndentationLengthFromOffset(offset); + // Calculate the start indentation string + String startIndent = getStartIndentation(startIndentLen); + // Prepare buffer for containing the indentation block + StringBuilder sb = new StringBuilder("\n"); + + // Append new indented multiline comment line to the buffer, that is indented based on the start indentation + sb.append(startIndent).append(" * \n"); + // Update the caret position to be placed in the end of the new indented line + indentation.caretPos = offset + sb.toString().length() - 1; + // Append the multiline comment end character on a new line + sb.append(startIndent).append(" */"); + // Set the indentation block text to the string containing from the buffer + indentation.text = sb.toString(); + // Indentation block was created + return true; + } + // Indentation block was not created + return false; + } + + /** + * Composes a continued multiline comment indentation block. + * + * @param offset + * is the offset of the inserted string. + * @param line + * is the line, where the indentation block must be appended to. + * @param indentation + * is containing the current indentation date. + * @return true if a continued multiline comment indentation block should be inserted after the given line; false + * otherwise. + * @throws BadLocationException + */ + private boolean composeMultilineCommentContinuedIndentation(int offset, String line, Indentation indentation) + throws BadLocationException { + + // Check if the given line contains a '*' and is located inside of a multiline comment + if (line.trim().startsWith("*") && isInMultilineComment(offset)) { + // Calculated current start indentation length from the given offset + int startIndentLen = getIndentationLengthFromOffset(offset); + // Calculate the start indentation string + String startIndent = getStartIndentation(startIndentLen); + // Prepare buffer for containing the indentation block + StringBuilder sb = new StringBuilder("\n"); + + // Append new indented multiline comment line to the buffer, that is indented based on the start indentation + sb.append(startIndent).append("* "); + // Update the caret position to be placed in the end of the new indented line + indentation.caretPos = offset + sb.toString().length(); + // Set the indentation block text to the string containing from the buffer + indentation.text = sb.toString(); + // Indentation block was created + return true; + } + // Indentation block was not created + return false; + } + + /** + * Composes a multiline end start indentation block. + * + * @param offset + * is the offset of the inserted string. + * @param line + * is the line, where the indentation block must be appended to. + * @param indentation + * is containing the current indentation date. + * @return true if a multiline comment end indentation block should be inserted after the given line; false + * otherwise. + * @throws BadLocationException + */ + private boolean composeMultilineCommentEndIndentation(int offset, String line, Indentation indentation) + throws BadLocationException { + + // Check if the given line contains a multiline end string, i.e. '*/' + if (line.trim().endsWith("*/")) { + // Get the line index from the current offset + int lineIndex = getElementIndex(offset); + + // Run loop as long as the line index is still positive (till the start of the document text) + while (lineIndex >= 0) { + // Check if the current line line is not in a multiline comment + int lineOffset = getElement(lineIndex).getStartOffset(); + + if (!isInMultilineComment(lineOffset)) { + // Append indentation that matches the start offset of the current line + indentation.text += getStartIndentation(getIndentationLengthFromOffset(lineOffset)); + break; + } + // Move to previous line + lineIndex--; + } + // Indentation block was created + return true; + } + // Indentation block was not created + return false; + } + + /** + * Returns line from the specified offset where trailing white spaces are removed. Note: The white spaces in the + * beginning of the line is not removed as these serve to determine start indentation for inserted lines following + * this line. + * + * @param offset + * is the offset to retrieve the line from. + * @return the line at the given offset where trailing white spaces have been trimmed. + * @throws BadLocationException + */ + private String getLineFromOffset(int offset) throws BadLocationException { + // Get the start and end index of the line + Element element = getElementFromOffset(offset); + int start = element.getStartOffset(); + int end = getEndOffset(element); + + if (end == start) { + return ""; + } + + // Get the line content + String origLine = getText(start, end - start); + // Trim trailing white spaces + String trimmedLine = origLine.replaceAll("\\s*$", ""); + + // Return the trimmed line, but only if it did not contain only white spaces as we need the white spaces for + // indentation for lines inserted after this line. + return trimmedLine.length() > 0 ? trimmedLine : origLine; + } + + /** + * Calculates and returns the indentation length (number of space characters) of the line at the given offset. + * + * @param offset + * is the document offset of the line. + * @return the calculated indentation length of the line at the given offset. + * @throws BadLocationException + */ + private int getIndentationLengthFromOffset(int offset) throws BadLocationException { + // Gets the start offset of the line at the given offset + int startOffset = getElementFromOffset(offset).getStartOffset(); + + // Run loop while the next character is a space of tabulator character. + int length = 0; + + for (;;) { + // Get the next character + char ch = getText(startOffset++, 1).charAt(0); + + if (ch == ' ') { + // Increment the length by 1 if the character is a space + length++; + } else if (ch == '\t') { + // Increment the length by the number of spaces the remain in order to reach the next tabulator column, + // if the character is a tabulator character. + length = tabSize * (length / tabSize + 1); + } else { + // Otherwise, stop looping + break; + } + } + // Return the calculated indentation length + return length; + } + + /** + * Returns a start indentation string of the given length. + * + * @param length + * is the length of the indentation measured in number of spaces. + * @return a string to apply to the start of a line in order to indent the line. + */ + private String getStartIndentation(int length) { + if (length == 0) { + return ""; + } + + // Prepare string buffer for containing the indentation string + StringBuilder sb = new StringBuilder(); + + // Check if tabulator characters must be used for indentation + if (!useSpacesForIndentation) { + // Append as many tabulator characters to the indentation string that fits into the given length + for (int i = length / tabSize; i > 0; i--) { + sb.append('\t'); + } + // Set the length to the spaces remaining to reach the input length + length %= tabSize; + } + // Apply spaces to the string buffer (might be the spaces that remain to fit the given length) + sb.append(getSpaces(length)); + // Return the indentation string contained in the string buffer + return sb.toString(); + } + + /** + * Updates the syntax highlighting on the document using the EDT. + */ + private void updateSyntaxHighlighting(final boolean force) { + // Only invoke the EDT, if this operation is not already initiated + if (updateSyntaxHighlightingEDTidle) { + updateSyntaxHighlightingEDTidle = false; + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + try { + // Apply syntax highlighting from the current offset + performSyntaxHighlighting(force); + updateSyntaxHighlightingEDTidle = true; + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + }); + } + } + + /** + * Perform syntax highlighting on the document. This implementation only performs syntax highlighting on the current + * visible text in the view port of the text pane, and detects if the text has been changed before performing the + * syntax highlighting. + * + * @throws BadLocationException + */ + private void performSyntaxHighlighting(boolean force) throws BadLocationException { + // Return if there is nothing to highlight + if (getLength() == 0 && !force) { + return; + } + + // Get the start and end offset of the visible text + + JViewport viewport = textPane.getViewport(); + Point startPoint = viewport.getViewPosition(); + Dimension size = viewport.getExtentSize(); + Point endPoint = new Point(startPoint.x + size.width, startPoint.y + size.height); + + int startOffset = textPane.viewToModel(startPoint); + int endOffset = textPane.viewToModel(endPoint); + + // Return if the current start and end offset is equal to the last ones + if (!force && startOffset == lastSyntaxHighlightStartOffset && endOffset == lastSyntaxHighlightEndOffset) { + return; + } + + lastSyntaxHighlightStartOffset = startOffset; + lastSyntaxHighlightEndOffset = endOffset; + + setCharacterAttributes(startOffset, endOffset - startOffset, normalAttrSet, true); + + // Get start and end line + int startLine = getElementIndex(startOffset); + int endLine = getElementIndex(endOffset); + + // Process each changed line one by one from the start line to the end line + for (int line = startLine; line <= endLine; line++) { + processChangedLine(line); + } + } + + /** + * Process changed line by applying syntax highlighting on the entire line at the given index. + * + * @param lineIndex + * is the index of the line. + * @throws BadLocationException + */ + private void processChangedLine(int lineIndex) throws BadLocationException { + // Process the syntax tokens on the given line + Element element = getElement(lineIndex); + + processLineTokens(element.getStartOffset(), getEndOffset(element)); + } + + /** + * Process the syntax tokens contained in a line. + * + * @param startOffset + * is the document start offset of the line to process. + * @param endOffset + * is the document end offset of the line to process. + * @throws BadLocationException + */ + private void processLineTokens(int startOffset, int endOffset) throws BadLocationException { + // Calculate the length of the line based on the given start and end offset + int len = endOffset - startOffset; + + // Process tokens one by one + String textFragment = getText(startOffset, len); + int index = 0; + + while (index < len) { + index += processToken(textFragment.substring(index), startOffset + index); + } + } + + /** + * Process the syntax token contained in a text fragment. + * + * @param textFragment + * is the text fragment. + * @param startOffset + * is the start offset of the text fragment to process. + * @return the number of processed characters. + * @throws BadLocationException + */ + private int processToken(final String textFragment, final int startOffset) throws BadLocationException { + // Process quote token if the first character in the text fragment is a quote delimiter + if (isQuoteDelimiter(textFragment.charAt(0))) { + return processQuoteToken(textFragment, startOffset); + } + int len; + + // Check if the token is a single line comment + // Note: Single line comment has higher precedence than a multiline comment. + if (textFragment.startsWith("//")) { + len = textFragment.length(); + setCharacterAttributes(startOffset, len, commentAttrSet, true); + return len; + } + // Check if the token is a multiline comment + if (textFragment.startsWith("/*")) { + return processStartMultilineCommentToken(textFragment, startOffset); + } + // Check if the token is in the middle of a multiline comment + if (isInMultilineComment(startOffset)) { + // Check if the token contains the end mark of the multiline comment + int endCommentIndex = textFragment.indexOf("*/"); + + if (endCommentIndex >= 0) { + len = endCommentIndex + 2; // Limit length to the end mark + } else { + len = textFragment.length(); // Use the whole token + } + setCharacterAttributes(startOffset, len, commentAttrSet, true); + return len; + } + + // Skip delimiter characters + len = 1; + while (len < textFragment.length()) { + char ch = textFragment.charAt(len); + + if (!Character.isLetter(ch)) { + break; + } + len++; + } + + // Limit token to current length, e.g. if it contained delimiter characters + String token = textFragment.substring(0, len); + + // Check if the token is a keyword or an annotation + if (startOffset > 0 && !Character.isLetter(getText(startOffset - 1, 1).charAt(0)) || startOffset == 0) { + if (isKeyword(token)) { + setCharacterAttributes(startOffset, len, keywordAttrSet, true); + } else if (isPredefinedLiteral(token)) { + setCharacterAttributes(startOffset, len, literalAttrSet, true); + } else if (isAnnotation(token)) { + setCharacterAttributes(startOffset, len, annotationAttrSet, true); + } else { + len = 1; + } + } else { + len = 1; + } + // Return the number of processed characters + return len; + } + + /** + * Process a quote token. + * + * @param textFragment + * is the text fragment. + * @param startOffset + * is the start offset of the text fragment to process. + * @return the number of processed characters. + * @throws BadLocationException + */ + private int processQuoteToken(final String textFragment, final int startOffset) { + char quoteDelimiter = textFragment.charAt(0); + + // Find end quote if it exists. Ignore escaped quotes + int indexQuote = 1; + int quoteEndIndex = -1; + + for (;;) { + indexQuote = textFragment.indexOf(quoteDelimiter, indexQuote); + if (indexQuote <= 0 || indexQuote > textFragment.length()) { + break; + } + if (textFragment.charAt(indexQuote - 1) != '\\') { + quoteEndIndex = indexQuote; + break; + } + indexQuote++; + } + + // Set length of token, if end quote was found + int len = quoteEndIndex >= 0 ? quoteEndIndex + 1 : textFragment.length(); + + // Set quote attribute set + setCharacterAttributes(startOffset, len, quoteAttrSet, true); + + return len; + } + + /** + * Process a multiline comment token. + * + * @param textFragment + * is the text fragment. + * @param startOffset + * is the start offset of the text fragment to process. + * @return the number of processed characters. + * @throws BadLocationException + */ + private int processStartMultilineCommentToken(final String textFragment, final int startOffset) { + int endIndex = textFragment.indexOf("*/", 1); + int len = endIndex >= 0 ? endIndex + 2 : textFragment.length(); + + setCharacterAttributes(startOffset, len, commentAttrSet, true); + + return len; + } + + /** + * Checks if the current text offset is within a multiline comment. + * + * @param offset + * is the text offset. + * @return true if the given offset is within a multiline comment; false otherwise. + * @throws BadLocationException + */ + private boolean isInMultilineComment(final int offset) throws BadLocationException { + return isInMultilineComment(getElementIndex(offset), offset); + } + + /** + * Checks if the current text offset is within a multiline comment. + * + * @oaram lineIndex is the element index of a line. + * @param offset + * is the text offset. + * @return true if the given line element index and offset is within a multiline comment; false otherwise. + * @throws BadLocationException + */ + private boolean isInMultilineComment(final int lineIndex, final int offset) throws BadLocationException { + int startOffset = getElement(lineIndex).getStartOffset(); + String lineText = getLineFromOffset(startOffset); + int len = Math.min((offset - startOffset), lineText.length()); + + lineText = lineText.substring(0, len); + + int commentStart = lineText.lastIndexOf("/*"); + int commentEnd = lineText.lastIndexOf("*/"); + + if (commentStart >= 0) { + if (commentEnd >= 0) { + if (commentEnd > commentStart) { + return (len < commentEnd); + } + } else { + return true; + } + } + if (commentEnd >= 0) { + return false; + } + + int prevLine = lineIndex - 1; + + return (prevLine >= 0) ? isInMultilineComment(prevLine, offset) : false; + } + + /** + * Checks if a character is a quote delimiter character. + * + * @param ch + * is the character. + * @return true if the given character is a quote delimiter character; false otherwise. + */ + private static boolean isQuoteDelimiter(char ch) { + return QUOTE_DELIMITERS.indexOf(ch) >= 0; + } + + /** + * Checks if a token is a keyword. + * + * @param token + * is the token. + * @return true if the given token is a keyword; false otherwise. + */ + private static boolean isKeyword(String token) { + return KEYWORDS.contains(token); + } + + /** + * Checks if a token is a predefined literal. + * + * @param token + * is the token. + * @return true if the given token is a predefined literal; false otherwise. + */ + private static boolean isPredefinedLiteral(String token) { + return PREDEFINED_LITERALS.contains(token); + } + + /** + * Checks if a token is an annotation. + * + * @param token + * is the token. + * @return true if the given token is an annotation; false otherwise. + */ + private static boolean isAnnotation(String token) { + return token.matches("@\\w.*"); + } + + /** + * Class containing data for indentation. + */ + private class Indentation { + // Is the new caret position after the indentation has been made. -1 means no change. + int caretPos; + // Is the indentation text + String text; + } + + + /** + * This document listener is used for updating the caret position and update syntax highlighting when the contents + * of the document is changed. + */ + private class JavaDocumentListener implements DocumentListener { + + // Caret position updater + final CaretPositionUpdater caretPositionUpdater = new CaretPositionUpdater(); + + public void insertUpdate(final DocumentEvent e) { + int newCaretPosition; + + // Check if the caret position has been changed by auto indentation + if (autoIndentationCaretPos >= 0) { + // Set the new caret position to the one set for auto indentation + newCaretPosition = autoIndentationCaretPos; + // Signal that the caret position for auto indentation has been set + autoIndentationCaretPos = -1; + } else { + // Set the new caret position to the end of the inserted text + newCaretPosition = e.getOffset() + e.getLength(); + } + // Update the caret position to the new position + caretPositionUpdater.updateCaretPosition(newCaretPosition); + + // Apply syntax highlighting from the current offset + updateSyntaxHighlighting(false); + } + + public void removeUpdate(final DocumentEvent e) { + // Set the caret position where the text was removed. + caretPositionUpdater.updateCaretPosition(e.getOffset()); + + // Apply syntax highlighting from the current offset + updateSyntaxHighlighting(false); + } + + public void changedUpdate(DocumentEvent e) {} + + private final class CaretPositionUpdater { + + /** + * Updates the caret position via the EDT. + * + * @param newCaretPosition is the new caret position. + */ + public void updateCaretPosition(int newCaretPosition) { + // Set the caret position, and take care that it is not out of range + textPane.setCaretPosition(Math.min(newCaretPosition, getLength())); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/LineHighlighter.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/LineHighlighter.java new file mode 100644 index 0000000..6f8a7e1 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/LineHighlighter.java @@ -0,0 +1,141 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.MouseMotionListener; + +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.Highlighter; +import javax.swing.text.JTextComponent; + +import net.sf.robocode.ui.editor.theme.EditorThemePropertiesManager; +import net.sf.robocode.ui.editor.theme.EditorThemePropertyChangeAdapter; + + +/** + * Class used for highlighting the current line for a JTextComponent. + * + * @author Santhosh Kumar T (original) + * @author Peter De Bruycker (contributor) + * @author Flemming N. Larsen (contributor) + */ +public final class LineHighlighter { + private static final String LINE_HIGHLIGHT = "line-highlight"; + private static final String PREVIOUS_CARET = "previous-caret"; + + private static Color color; // Color used for highlighting the line + + private LineHighlighter() {} + + /** + * Installs CurrentLineHilighter for the given JTextComponent. + * @param c is the text component + */ + public static void install(JTextComponent c) { + try { + Object obj = c.getHighlighter().addHighlight(0, 0, painter); + c.putClientProperty(LINE_HIGHLIGHT, obj); + c.putClientProperty(PREVIOUS_CARET, new Integer(c.getCaretPosition())); + c.addCaretListener(caretListener); + c.addMouseListener(mouseListener); + c.addMouseMotionListener(mouseMotionListener); + + color = EditorThemePropertiesManager.getCurrentEditorThemeProperties().getHighlightedLineColor(); + EditorThemePropertiesManager.addListener(editorThemePropertyChangeListener); + } catch (BadLocationException ex) {} + } + + /** + * Uninstalls CurrentLineHighligher for the given JTextComponent. + * @param c is the text component + */ + public static void uninstall(JTextComponent c) { + c.putClientProperty(LINE_HIGHLIGHT, null); + c.putClientProperty(PREVIOUS_CARET, null); + c.removeCaretListener(caretListener); + c.removeMouseListener(mouseListener); + c.removeMouseMotionListener(mouseMotionListener); + EditorThemePropertiesManager.removeListener(editorThemePropertyChangeListener); + } + + /** + * Fetches the previous caret location, stores the current caret location, + * If the caret is on another line, repaint the previous line and the current line + * @param c is the text component + */ + private static void caretUpdate(JTextComponent c) { + try { + int previousCaret = ((Integer) c.getClientProperty(PREVIOUS_CARET)).intValue(); + final int actualCaretPosition = c.getCaretPosition(); + c.putClientProperty(PREVIOUS_CARET, new Integer(actualCaretPosition)); + Rectangle prev = c.modelToView(previousCaret); + Rectangle r = c.modelToView(actualCaretPosition); + // c.putClientProperty(PREVIOUS_CARET, new Integer(actualCaretPosition)); + + if (prev != null && prev.y != r.y) { + c.repaint(0, prev.y, c.getWidth(), r.height); + c.repaint(0, r.y, c.getWidth(), r.height); + } + } catch (BadLocationException ignore) {} + } + + private static CaretListener caretListener = new CaretListener() { + @Override + public void caretUpdate(CaretEvent e) { + JTextComponent c = (JTextComponent) e.getSource(); + LineHighlighter.caretUpdate(c); + } + }; + + private static MouseListener mouseListener = new MouseAdapter() { + // highlight the line the user clicks on + @Override + public void mousePressed(MouseEvent e) { + JTextComponent c = (JTextComponent) e.getSource(); + caretUpdate(c); + } + }; + + private static MouseMotionListener mouseMotionListener = new MouseMotionAdapter() { + @Override + public void mouseDragged(MouseEvent e) { + JTextComponent c = (JTextComponent) e.getSource(); + caretUpdate(c); + } + }; + + private static EditorThemePropertyChangeAdapter editorThemePropertyChangeListener = new EditorThemePropertyChangeAdapter() { + public void onHighlightedLineColorChanged(Color newColor) { + if (!color.equals(newColor)) { + color = newColor; + } + } + }; + + private static Highlighter.HighlightPainter painter = new Highlighter.HighlightPainter() { + @Override + public void paint(Graphics g, int p0, int p1, Shape bounds, JTextComponent c) { + try { + Rectangle r = c.modelToView(c.getCaretPosition()); + g.setColor(color); + g.fillRect(0, r.y, c.getWidth(), r.height); + } catch (BadLocationException ignore) {} + } + }; +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/LineNumberArea.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/LineNumberArea.java new file mode 100644 index 0000000..675ea1f --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/LineNumberArea.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import java.awt.Color; +import java.awt.Rectangle; + +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.Document; +import javax.swing.text.JTextComponent; + +import net.sf.robocode.ui.editor.theme.EditorThemeProperties; +import net.sf.robocode.ui.editor.theme.EditorThemePropertiesManager; +import net.sf.robocode.ui.editor.theme.EditorThemePropertyChangeAdapter; + + +/** + * A text area containing line numbers for the editor pane and editor panel. + * + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class LineNumberArea extends JTextArea { + + private final DocumentListener documentListener = new TextDocumentListener(); + + public LineNumberArea(JTextComponent textComponent) { + super("1"); + + setEditable(false); + setLineWrap(false); + + EditorThemeProperties themeProps = EditorThemePropertiesManager.getCurrentEditorThemeProperties(); + setBackgroundColor(themeProps.getLineNumberBackgroundColor()); + setTextColor(themeProps.getLineNumberTextColor()); + + textComponent.getDocument().addDocumentListener(documentListener); + + EditorThemePropertiesManager.addListener(new EditorThemePropertyChangeAdapter() { + @Override + public void onLineNumberBackgroundColorChanged(Color newColor) { + setBackgroundColor(newColor); + } + + @Override + public void onLineNumberTextColorChanged(Color newColor) { + setTextColor(newColor); + } + }); + } + + private class TextDocumentListener implements DocumentListener { + int lastNumLines = 1; + + public void insertUpdate(DocumentEvent e) { + updateText(e.getDocument()); + } + + public void removeUpdate(DocumentEvent e) { + updateText(e.getDocument()); + } + + public void changedUpdate(DocumentEvent e) { + updateText(e.getDocument()); + } + + private void updateText(final Document doc) { + + final int numLines = getNumLines(doc); + + if (numLines == lastNumLines) { + return; + } + lastNumLines = numLines; + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + final Rectangle visibleRect = getVisibleRect(); + + setIgnoreRepaint(true); // avoid flickering + setText(generateLinesText(numLines)); + + // Must be done this way to keep aligned with scroll bar! + SwingUtilities.invokeLater(new Runnable() { + public void run() { + scrollRectToVisible(visibleRect); + setIgnoreRepaint(false); // avoid flickering + } + }); + } + }); + } + + /** + * Returns a string containing text lines for all line numbers. + * Each line number is right-aligned and ended a space + a new-line character. + * + * @param numLines is the number of lines to create the line number text for. + * @return a string containing line numbers. + */ + private String generateLinesText(int numLines) { + String format = "%" + ("" + (numLines + 1)).length() + "s "; + + StringBuilder lines = new StringBuilder(); + int i = 1; + while (i <= numLines) { + String s = String.format(format, "" + i++); + lines.append(s).append('\n'); + } + lines.append(String.format(format, "" + i)); + return lines.toString(); + } + + private int getNumLines(Document doc) { + return doc.getDefaultRootElement().getElementIndex(doc.getLength()); + } + } + + private void setBackgroundColor(Color newBackgroundColor) { + setBackground(newBackgroundColor); + setSelectionColor(newBackgroundColor); + } + + private void setTextColor(Color newTextColor) { + setForeground(newTextColor); + setSelectedTextColor(newTextColor); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/Module.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/Module.java new file mode 100644 index 0000000..17a07cf --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/Module.java @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import net.sf.robocode.core.BaseModule; +import net.sf.robocode.core.Container; + + +/** + * @author Pavel Savara (original) + */ +public class Module extends BaseModule { + static { + Container.cache.addComponent(RobocodeCompilerFactory.class); + Container.cache.addComponent(RobocodeEditor.class); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/MoreWindowsDialog.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/MoreWindowsDialog.java new file mode 100644 index 0000000..0154521 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/MoreWindowsDialog.java @@ -0,0 +1,138 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.Vector; + + +/** + * @author Matthew Reeder (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class MoreWindowsDialog extends JDialog implements ActionListener, MouseListener { + private JButton activateButton; + private JButton cancelButton; + private JButton closeButton; + private JList windowList; + private final Vector windowListItems; + + public MoreWindowsDialog(RobocodeEditor window) { + super(window, "More Windows...", false); + windowListItems = new Vector(); + JPanel listPanel = new JPanel(new GridLayout(1, 1)); + + listPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Open Windows")); + listPanel.add(new JScrollPane(getWindowList())); + JPanel buttonPanel = new JPanel(); + + buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS)); + buttonPanel.add(getActivateButton()); + buttonPanel.add(getCancelButton()); + buttonPanel.add(getCloseButton()); + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(buttonPanel, BorderLayout.SOUTH); + getContentPane().add(listPanel); + setSize(400, 400); + } + + public void addWindowItem(WindowMenuItem item) { + windowListItems.add(item); + getWindowList().setListData(windowListItems); + } + + public void removeWindowItem(WindowMenuItem item) { + windowListItems.remove(item); + getWindowList().setListData(windowListItems); + } + + public JButton getActivateButton() { + if (activateButton == null) { + activateButton = new JButton(); + activateButton.setText("Activate"); + activateButton.setMnemonic('A'); + activateButton.setDefaultCapable(true); + activateButton.addActionListener(this); + } + return activateButton; + } + + public JButton getCancelButton() { + if (cancelButton == null) { + cancelButton = new JButton(); + cancelButton.setText("Cancel"); + cancelButton.setMnemonic('C'); + cancelButton.addActionListener(this); + } + return cancelButton; + } + + public JButton getCloseButton() { + if (closeButton == null) { + closeButton = new JButton(); + closeButton.setText("Close"); + closeButton.setMnemonic('l'); + closeButton.setDisplayedMnemonicIndex(1); + closeButton.addActionListener(this); + } + return closeButton; + } + + public JList getWindowList() { + if (windowList == null) { + windowList = new JList(); + windowList.addMouseListener(this); + windowList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + } + return windowList; + } + + public void actionPerformed(ActionEvent e) { + if (e.getSource() == closeButton) { + WindowMenuItem item = (WindowMenuItem) windowList.getSelectedValue(); + + if (item != null && item.getEditWindow() != null) { + item.getEditWindow().doDefaultCloseAction(); + } + } else { + if (e.getSource() == activateButton) { + WindowMenuItem item = (WindowMenuItem) windowList.getSelectedValue(); + + if (item != null) { + item.actionPerformed(null); + } + } + setVisible(false); + } + } + + public void mouseClicked(MouseEvent e) { + if (e.getSource() == getWindowList() && e.getClickCount() == 2) { + WindowMenuItem item = windowListItems.get(windowList.locationToIndex(e.getPoint())); + + item.actionPerformed(null); // Good thing WindowMenuItem doesn't + // reference the ActionEvent? + setVisible(false); + } + } + + public void mousePressed(MouseEvent e) {} + + public void mouseReleased(MouseEvent e) {} + + public void mouseEntered(MouseEvent e) {} + + public void mouseExited(MouseEvent e) {} +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeCompiler.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeCompiler.java new file mode 100644 index 0000000..2a4f649 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeCompiler.java @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.CodeSizeCalculator; +import net.sf.robocode.ui.dialog.ConsoleDialog; +import net.sf.robocode.ui.dialog.WindowUtil; + +import java.io.File; +import java.io.IOException; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobocodeCompiler { + + private final String compilerBinary; + private final RobocodeEditor editor; + private final String compilerOptions; + private final String compilerClassPath; + + protected RobocodeCompiler(RobocodeEditor editor, String binary, String options, String classPath) { + super(); + this.compilerBinary = binary; + this.compilerOptions = options; + this.compilerClassPath = classPath; + this.editor = editor; + } + + public void compile(String directory, String fileName) { + fileName = FileUtil.quoteFileName(fileName); + + ConsoleDialog console; + + if (editor != null) { + console = new ConsoleDialog(editor, "Compiling", false); + } else { + console = new ConsoleDialog(); + } + console.setSize(500, 400); + console.setText("Compiling...\n"); + WindowUtil.centerShow(editor, console); + + try { + StringBuffer command = new StringBuffer(compilerBinary).append(' ').append(compilerOptions).append(' ').append(compilerClassPath).append(' ').append( + fileName); + + Logger.logMessage("Compile command: " + command); + + ProcessBuilder pb = new ProcessBuilder(command.toString().split(" ")); + + pb.redirectErrorStream(true); + pb.directory(FileUtil.getCwd()); + Process p = pb.start(); + + // The waitFor() must done after reading the input and error stream of the process + console.processStream(p.getInputStream()); + p.waitFor(); + + if (p.exitValue() == 0) { + console.append("Compiled successfully.\n"); + console.setTitle("Compiled successfully."); + } else { + console.append("Compile Failed (" + p.exitValue() + ")\n"); + console.setTitle("Compile failed."); + } + } catch (IOException e) { + console.append("Unable to compile!\n"); + console.append("Exception was: " + e.toString() + "\n"); + console.append("Does " + compilerBinary + " exist?\n"); + console.setTitle("Exception while compiling"); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + + console.append("Compile interrupted.\n"); + console.setTitle("Compile interrupted."); + } + + Integer codesize = CodeSizeCalculator.getDirectoryCodeSize(new File(directory)); + if (codesize != null) { + String weightClass = null; + + if (codesize >= 1500) { + weightClass = "MegaBot (codesize >= 1500 bytes)"; + } else if (codesize > 750) { + weightClass = "MiniBot (codesize < 1500 bytes)"; + } else if (codesize > 250) { + weightClass = "MicroBot (codesize < 750 bytes)"; + } else { + weightClass = "NanoBot (codesize < 250 bytes)"; + } + StringBuilder sb = new StringBuilder(); + + sb.append("\n\n---- Codesize ----\n"); + sb.append("Codesize: ").append(codesize).append(" bytes\n"); + sb.append("Robot weight class: ").append(weightClass).append('\n'); + + console.append(sb.toString()); + } + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeCompilerFactory.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeCompilerFactory.java new file mode 100644 index 0000000..2d515ee --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeCompilerFactory.java @@ -0,0 +1,219 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import net.sf.robocode.core.ContainerBase; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.manager.IVersionManagerBase; +import static net.sf.robocode.io.Logger.logError; +import static net.sf.robocode.io.Logger.logMessage; +import net.sf.robocode.ui.dialog.ConsoleDialog; +import net.sf.robocode.ui.dialog.WindowUtil; + +import javax.swing.*; +import java.io.*; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class RobocodeCompilerFactory { + + private static final String COMPILER_CLASSPATH = "-classpath " + getJavaLib() + File.pathSeparator + "libs" + + File.separator + "robocode.jar" + File.pathSeparator + + FileUtil.quoteFileName(FileUtil.getRobotsDir().toString()); + + private CompilerProperties compilerProperties; + + public RobocodeCompiler createCompiler(RobocodeEditor editor) { + compilerProperties = null; + if (getCompilerProperties().getCompilerBinary() == null + || getCompilerProperties().getCompilerBinary().length() == 0) { + if (configureCompiler(editor)) { + return new RobocodeCompiler(editor, getCompilerProperties().getCompilerBinary(), + getCompilerProperties().getCompilerOptions(), getCompilerProperties().getCompilerClasspath()); + } + logError("Unable to create compiler."); + return null; + } + return new RobocodeCompiler(editor, getCompilerProperties().getCompilerBinary(), + getCompilerProperties().getCompilerOptions(), getCompilerProperties().getCompilerClasspath()); + } + + public CompilerProperties getCompilerProperties() { + if (compilerProperties == null) { + compilerProperties = new CompilerProperties(); + + FileInputStream in = null; + File file = null; + + try { + file = FileUtil.getCompilerConfigFile(); + in = new FileInputStream(file); + compilerProperties.load(in); + if (compilerProperties.getRobocodeVersion() == null) { + logMessage("Setting up new compiler."); + compilerProperties.setCompilerBinary(""); + } + } catch (FileNotFoundException e) { + logMessage("Compiler configuration file was not found. A new one will be created."); + } catch (IOException e) { + logError("Error while reading " + file, e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) {} + } + } + } + return compilerProperties; + } + + private static String getJavaLib() { + String javahome = System.getProperty("java.home"); + String javalib; + if (System.getProperty("os.name").indexOf("Mac") == 0) { + javalib = new File(javahome).getParentFile().getPath() + "/Classes/classes.jar"; + } else { + javalib = javahome + "/lib/rt.jar"; + } + + return FileUtil.quoteFileName(javalib); + } + + public boolean configureCompiler(RobocodeEditor editor) { + ConsoleDialog console = new ConsoleDialog(editor, "Setting up compiler", false); + + console.setSize(500, 400); + console.getOkButton().setEnabled(false); + console.setText("Please wait while Robocode sets up a compiler for you...\n\n"); + WindowUtil.centerShow(editor, console); + + console.append("Setting up compiler\n"); + console.append("Java home is " + System.getProperty("java.home") + "\n\n"); + + String compilerName = "Java Compiler (javac)"; + String compilerBinary = "javac"; + String compilerOptions = "-deprecation -g -source 1.6 -encoding UTF-8"; + + boolean javacOK = testCompiler(compilerName, compilerBinary, console); + boolean ecjOK = false; + + if (javacOK) { + int rc = JOptionPane.showConfirmDialog(editor, + "Robocode has found a working javac (Java Compiler) on this system.\nWould you like to use it?\n" + + "(If you click No, Robocode will use the build-in Eclipse Compiler for Java (ECJ))", + "Confirm javac", + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); + + if (rc == JOptionPane.NO_OPTION) { + javacOK = false; + } + } + + if (!javacOK) { + compilerName = "Eclipse Compiler for Java (ECJ)"; + compilerBinary = "java -cp compilers/ecj.jar org.eclipse.jdt.internal.compiler.batch.Main"; + + ecjOK = testCompiler("Eclipse Compiler for Java (ECJ)", compilerBinary, console); + } + + boolean compilerOK = javacOK || ecjOK; + + if (compilerOK) { + console.append("\nCompiler has been set up successfully.\nClick OK to continue.\n"); + + } else { + final String errorText = "Could not set up a working compiler for Robocode.\n" + + "Please consult the console window for errors.\n\n" + + "For help with this, please post to Help forum here:\n" + + "http://sourceforge.net/projects/robocode/forums/forum/116459"; + + console.append("\nUnable to set up a working compiler for Robocode.\n"); + + JOptionPane.showMessageDialog(editor, errorText, "Error", JOptionPane.ERROR_MESSAGE); + + compilerBinary = ""; + compilerOptions = ""; + } + + getCompilerProperties().setRobocodeVersion(ContainerBase.getComponent(IVersionManagerBase.class).getVersion()); + getCompilerProperties().setCompilerBinary(compilerBinary); + getCompilerProperties().setCompilerOptions(compilerOptions); + getCompilerProperties().setCompilerClasspath(COMPILER_CLASSPATH); + saveCompilerProperties(); + + console.scrollToBottom(); + console.getOkButton().setEnabled(true); + + return compilerOK; + } + + public void saveCompilerProperties() { + FileOutputStream out = null; + + try { + out = new FileOutputStream(FileUtil.getCompilerConfigFile()); + + getCompilerProperties().store(out, "Robocode Compiler Properties"); + } catch (IOException e) { + Logger.logError(e); + } finally { + FileUtil.cleanupStream(out); + } + } + + /** + * Tests a compiler by trying to let it compile the CompilerTest.java file. + * + * @param friendlyName friendly name of the compiler to test. + * @param filepath the file path of the compiler. + * @param console the console which outputs the result. + * @return true if the compiler was found and did compile the test file; false otherwise. + */ + private static boolean testCompiler(String friendlyName, String filepath, ConsoleDialog console) { + console.append("Testing compile with " + friendlyName + "\n"); + + boolean result = false; + + try { + String cmdAndArgs = filepath + " compilers/CompilerTest.java"; + + // Must be split command and arguments individually + ProcessBuilder pb = new ProcessBuilder(cmdAndArgs.split(" ")); + + pb.directory(FileUtil.getCwd()); + pb.redirectErrorStream(true); // we can use p.getInputStream() + Process p = pb.start(); + + // The waitFor() must done after reading the input and error stream of the process + console.processStream(p.getInputStream()); + p.waitFor(); + + result = (p.exitValue() == 0); + + } catch (IOException e) { + logError(e); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + } + + if (result) { + console.append(friendlyName + " was found and is working.\n"); + } else { + console.append(friendlyName + " does not exists or cannot compile.\n"); + } + return result; + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeEditor.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeEditor.java new file mode 100644 index 0000000..2a13525 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeEditor.java @@ -0,0 +1,664 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.IRepositoryManager; +import net.sf.robocode.ui.BrowserManager; +import net.sf.robocode.ui.IWindowManager; +import net.sf.robocode.ui.IWindowManagerExt; +import net.sf.robocode.ui.gfx.ImageUtil; + +import javax.swing.*; +import javax.swing.filechooser.FileFilter; +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyVetoException; +import java.io.*; + + +/** + * The source code editor window containing all components. + * + * @author Mathew A. Nelson (original) + * @author Matthew Reeder (contributor) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class RobocodeEditor extends JFrame implements Runnable, IRobocodeEditor { + private static final int MAX_PACKAGE_NAME_LENGTH = 16; + private static final int MAX_ROBOT_NAME_LENGTH = 32; + + private JPanel robocodeEditorContentPane; + + private RobocodeEditorMenuBar robocodeEditorMenuBar; + private JDesktopPane desktopPane; + + private final Point origin = new Point(); + private final File robotsDirectory; + + private JToolBar statusBar; + private JLabel lineLabel; + + private File editorDirectory; + private final IRepositoryManager repositoryManager; + private final IWindowManagerExt windowManager; + + private FindReplaceDialog findReplaceDialog; + private ReplaceAction replaceAction; + + final EventHandler eventHandler = new EventHandler(); + + class EventHandler implements ComponentListener { + public void componentMoved(ComponentEvent e) {} + + public void componentHidden(ComponentEvent e) {} + + public void componentShown(ComponentEvent e) { + new Thread(RobocodeEditor.this).start(); + } + + public void componentResized(ComponentEvent e) {} + } + + + /** + * Action that launches the Replace dialog. + *

+ * The reason this is needed (and the menubar isn't sufficient) is that + * ctrl+H is bound in JTextComponents at a lower level to backspace and in + * order to override this, I need to rebind it to an Action when the + * JEditorPane is created. + */ + class ReplaceAction extends AbstractAction { + public void actionPerformed(ActionEvent e) { + replaceDialog(); + } + } + + public RobocodeEditor(IRepositoryManager repositoryManager, IWindowManager windowManager) { + super(); + this.windowManager = (IWindowManagerExt) windowManager; + this.repositoryManager = repositoryManager; + robotsDirectory = FileUtil.getRobotsDir(); + initialize(); + } + + public void addPlaceShowFocus(JInternalFrame internalFrame) { + getDesktopPane().add(internalFrame); + + // Center a window + Dimension screenSize = getDesktopPane().getSize(); + Dimension size = internalFrame.getSize(); + + if (size.height > screenSize.height) { + size.height = screenSize.height; + } + if (size.width > screenSize.width) { + size.width = screenSize.width; + } + + if (origin.x + size.width > screenSize.width) { + origin.x = 0; + } + if (origin.y + size.height > screenSize.height) { + origin.y = 0; + } + internalFrame.setLocation(origin); + origin.x += 10; + origin.y += 10; + + internalFrame.setVisible(true); + getDesktopPane().moveToFront(internalFrame); + if (internalFrame instanceof EditWindow) { + ((EditWindow) internalFrame).getEditorPane().requestFocus(); + } else { + internalFrame.requestFocus(); + } + + // Make sure the internal frame is being maximized to fit the window when it is opened + try { + internalFrame.setMaximum(true); + } catch (PropertyVetoException e) { + Logger.logError(e); + } + } + + public boolean close() { + JInternalFrame[] frames = getDesktopPane().getAllFrames(); + if (frames != null) { + for (JInternalFrame frame : frames) { + if (frame != null) { + frame.moveToFront(); + if ((frame instanceof EditWindow) && !((EditWindow) frame).fileSave(true)) { + return false; + } + } + } + } + dispose(); + return true; + } + + public void createNewJavaFile() { + String packageName = null; + + if (getActiveWindow() != null) { + packageName = getActiveWindow().getPackage(); + } + if (packageName == null) { + packageName = "mypackage"; + } + + EditWindow editWindow = new EditWindow(repositoryManager, this, robotsDirectory); + + String templateName = "templates" + File.separatorChar + "newjavafile.tpt"; + + String template = ""; + + File f = new File(FileUtil.getCwd(), templateName); + int size = (int) (f.length()); + byte buff[] = new byte[size]; + + FileInputStream fis = null; + DataInputStream dis = null; + + try { + fis = new FileInputStream(f); + dis = new DataInputStream(fis); + + dis.readFully(buff); + template = new String(buff); + } catch (IOException e) { + template = "Unable to read template file: " + FileUtil.getCwd() + File.separatorChar + templateName; + } finally { + FileUtil.cleanupStream(fis); + FileUtil.cleanupStream(dis); + } + + String name = "MyClass"; + + int index = template.indexOf("$"); + + while (index >= 0) { + if (template.substring(index, index + 10).equals("$CLASSNAME")) { + template = template.substring(0, index) + name + template.substring(index + 10); + index += name.length(); + } else if (template.substring(index, index + 8).equals("$PACKAGE")) { + template = template.substring(0, index) + packageName + template.substring(index + 8); + index += packageName.length(); + } else { + index++; + } + index = template.indexOf("$", index); + } + + EditorPane editorPane = editWindow.getEditorPane(); + + editorPane.setText(template); + editorPane.setCaretPosition(0); + + addPlaceShowFocus(editWindow); + } + + public void createNewRobot() { + createNewRobot("Robot"); + } + + public void createNewJuniorRobot() { + createNewRobot("JuniorRobot"); + } + + private void createNewRobot(final String robotType) { + String message = "Enter the name of your new robot.\nExample: MyFirst" + robotType + + "\nNote that the name cannot contain spaces."; + String name = ""; + + boolean done = false; + + while (!done) { + name = (String) JOptionPane.showInputDialog(this, message, "New " + robotType, JOptionPane.PLAIN_MESSAGE, + null, null, name); + name = (name == null) ? "" : name.trim(); + if (name.length() == 0) { + return; + } + if (name.length() > MAX_ROBOT_NAME_LENGTH) { + name = name.substring(0, MAX_ROBOT_NAME_LENGTH); + message = "Please choose a shorter name (up to " + MAX_ROBOT_NAME_LENGTH + " characters)"; + continue; + } + + done = true; + + char firstLetter = name.charAt(0); + + if (firstLetter == '$' || firstLetter == '_') { + name = name.substring(1); + done = false; + } + int firstLetterCodePoint = name.codePointAt(0); // used for supporting Unicode methods + + if (!Character.isJavaIdentifierStart(firstLetterCodePoint) || Character.isLowerCase(firstLetterCodePoint)) { + name = (char) Character.toUpperCase(firstLetterCodePoint) + name.substring(1); + done = false; + } + if (!done) { + message = "Please start your robot name with a big letter,\n" + + "as should the first letter of every word in the name.\nExample: MyFirstRobot"; + continue; + } + + char ch = 0; + + for (int i = 1; i < name.length(); i++) { + ch = name.charAt(i); + int codePoint = name.codePointAt(i); + + if (!Character.isJavaIdentifierPart(codePoint) || ch == '$') { + done = false; + break; + } + } + if (!done) { + message = "Your robot name contains an invalid character: '" + ch + + "'\nPlease use only letters and digits."; + continue; + } + } + + message = "Enter a short package name for your new robot and without spaces (lower-case letters are prefered).\n" + + "Your initials will work well here.\n" + + "Your robot will be put into this package to avoid name conflict with other robots.\n" + + "The package name is used to identify your robot(s) in the game, especially if you\n" + + "want to let your robot(s) participate in competitions like e.g. RoboRumble@Home.\n" + + "Hence, you should enter the same package name for all of your robots."; + + String packageName = ""; + + done = false; + while (!done) { + packageName = (String) JOptionPane.showInputDialog(this, message, "Package name for " + name, + JOptionPane.PLAIN_MESSAGE, null, null, packageName); + packageName = (packageName == null) ? "" : packageName.trim(); + if (packageName.length() == 0) { + return; + } + if (packageName.length() > MAX_PACKAGE_NAME_LENGTH) { + packageName = packageName.substring(0, MAX_PACKAGE_NAME_LENGTH); + message = "Please choose a shorter name (up to " + MAX_PACKAGE_NAME_LENGTH + " characters)"; + continue; + } + + done = true; + + char firstLetter = packageName.charAt(0); + + if (firstLetter == '$' || firstLetter == '_') { + packageName = packageName.substring(1); + done = false; + } + int firstLetterCodePoint = packageName.codePointAt(0); // used for supporting Unicode methods + + if (!Character.isJavaIdentifierStart(firstLetterCodePoint)) { + done = false; + } + if (!done) { + message = "Please start the package name with a small letter.\n" + + "The entire package name should be written in lower-case letters\n" + + "(Java convention), although Robocode will accept big case letters as well."; + continue; + } + + char ch = 0; + + for (int i = 1; i < packageName.length(); i++) { + ch = packageName.charAt(i); + int codePoint = packageName.codePointAt(i); + + if (!(Character.isJavaIdentifierPart(codePoint) || ch == '.') || ch == '$') { + done = false; + break; + } + } + if (!done) { + message = "Your package name contains an invalid character: '" + ch + + "'\nPlease use only small letters and digits."; + continue; + } + + if (packageName.charAt(packageName.length() - 1) == '.') { + message = "The package name cannot end with a dot"; + done = false; + continue; + } + + boolean wrong_dot_combination = false; + int lastDotIndex = -1; + + for (int i = 0; i < packageName.length(); i++) { + if (packageName.charAt(i) == '.') { + if (i - lastDotIndex == 1) { + wrong_dot_combination = true; + break; + } + lastDotIndex = i; + } + } + if (wrong_dot_combination) { + message = "The package name contain two dots next to each other"; + done = false; + continue; + } + + if (repositoryManager != null) { + done = repositoryManager.verifyRobotName(packageName + "." + name, name); + } + if (!done) { + message = "The package name is reserved:\n" + packageName + "\nPlease enter a different package name."; + continue; + } + } + + EditWindow editWindow = new EditWindow(repositoryManager, this, robotsDirectory); + editWindow.setRobotName(name); + + String templateName = "templates" + File.separatorChar + "new" + robotType.toLowerCase() + ".tpt"; + + String template = ""; + + File f = new File(FileUtil.getCwd(), templateName); + int size = (int) (f.length()); + byte buff[] = new byte[size]; + FileInputStream fis = null; + DataInputStream dis = null; + + try { + fis = new FileInputStream(f); + dis = new DataInputStream(fis); + dis.readFully(buff); + template = new String(buff); + } catch (IOException e) { + template = "Unable to read template file: " + FileUtil.getCwd() + File.separatorChar + templateName; + } finally { + FileUtil.cleanupStream(fis); + FileUtil.cleanupStream(dis); + } + + int index = template.indexOf("$"); + + while (index >= 0) { + if (template.substring(index, index + 10).equals("$CLASSNAME")) { + template = template.substring(0, index) + name + template.substring(index + 10); + index += name.length(); + } else if (template.substring(index, index + 8).equals("$PACKAGE")) { + template = template.substring(0, index) + packageName + template.substring(index + 8); + index += packageName.length(); + } else { + index++; + } + index = template.indexOf("$", index); + } + + EditorPane editorPane = editWindow.getEditorPane(); + editorPane.setText(template); + editorPane.setCaretPosition(0); + + addPlaceShowFocus(editWindow); + if (repositoryManager != null) { + repositoryManager.refresh(); + } + } + + public void findDialog() { + getFindReplaceDialog().showDialog(false); + } + + public void replaceDialog() { + getFindReplaceDialog().showDialog(true); + } + + public EditWindow getActiveWindow() { + JInternalFrame[] frames = getDesktopPane().getAllFrames(); + EditWindow editWindow = null; + + if (frames != null) { + for (JInternalFrame frame : frames) { + if (frame.isSelected()) { + if (frame instanceof EditWindow) { + editWindow = (EditWindow) frame; + } + break; + } + } + } + return editWindow; + } + + public RobocodeCompiler getCompiler() { + return Container.getComponent(RobocodeCompilerFactory.class).createCompiler(this); + } + + public JDesktopPane getDesktopPane() { + if (desktopPane == null) { + desktopPane = new JDesktopPane(); + desktopPane.setBackground(Color.GRAY); + desktopPane.setPreferredSize(new Dimension(750, 550)); + } + return desktopPane; + } + + private JLabel getLineLabel() { + if (lineLabel == null) { + lineLabel = new JLabel(); + } + return lineLabel; + } + + private JPanel getRobocodeEditorContentPane() { + if (robocodeEditorContentPane == null) { + robocodeEditorContentPane = new JPanel(); + robocodeEditorContentPane.setLayout(new BorderLayout()); + robocodeEditorContentPane.add(getDesktopPane(), "Center"); + robocodeEditorContentPane.add(getStatusBar(), "South"); + } + return robocodeEditorContentPane; + } + + private RobocodeEditorMenuBar getRobocodeEditorMenuBar() { + if (robocodeEditorMenuBar == null) { + robocodeEditorMenuBar = new RobocodeEditorMenuBar(this); + } + return robocodeEditorMenuBar; + } + + private JToolBar getStatusBar() { + if (statusBar == null) { + statusBar = new JToolBar(); + statusBar.setLayout(new BorderLayout()); + statusBar.add(getLineLabel(), BorderLayout.WEST); + } + return statusBar; + } + + public FindReplaceDialog getFindReplaceDialog() { + if (findReplaceDialog == null) { + findReplaceDialog = new FindReplaceDialog(this); + } + return findReplaceDialog; + } + + public Action getReplaceAction() { + if (replaceAction == null) { + replaceAction = new ReplaceAction(); + } + return replaceAction; + } + + public void addToWindowMenu(EditWindow window) { + WindowMenuItem item = new WindowMenuItem(window, getRobocodeEditorMenuBar().getWindowMenu()); + + getRobocodeEditorMenuBar().getMoreWindowsDialog().addWindowItem(item); + } + + public void removeFromWindowMenu(EditWindow window) { + for (Component c : getRobocodeEditorMenuBar().getWindowMenu().getMenuComponents()) { + if (c instanceof WindowMenuItem) { + WindowMenuItem item = (WindowMenuItem) c; + + if (item.getEditWindow() == window) { + getRobocodeEditorMenuBar().getWindowMenu().remove(item); + getRobocodeEditorMenuBar().getMoreWindowsDialog().removeWindowItem(item); + break; + } + } + } + } + + private void initialize() { + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + close(); + } + }); + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + setIconImage(ImageUtil.getImage("/net/sf/robocode/ui/icons/robocode-icon.png")); + setTitle("Robot Editor"); + setJMenuBar(getRobocodeEditorMenuBar()); + setContentPane(getRobocodeEditorContentPane()); + addComponentListener(eventHandler); + } + + public void openRobot() { + if (editorDirectory == null) { + editorDirectory = robotsDirectory; + } + JFileChooser chooser; + + chooser = new JFileChooser(editorDirectory); + FileFilter filter = new FileFilter() { + @Override + public boolean accept(File pathname) { + if (pathname.isHidden()) { + return false; + } + if (pathname.isDirectory()) { + return true; + } + String fn = pathname.getName(); + int idx = fn.lastIndexOf('.'); + String extension = ""; + + if (idx >= 0) { + extension = fn.substring(idx); + } + return extension.equalsIgnoreCase(".java"); + } + + @Override + public String getDescription() { + return "Robots"; + } + }; + + chooser.setFileFilter(filter); + int rv = chooser.showOpenDialog(this); + + if (rv == JFileChooser.APPROVE_OPTION) { + String robotFilename = chooser.getSelectedFile().getPath(); + + editorDirectory = chooser.getSelectedFile().getParentFile(); + + BufferedReader bufferedReader = null; + InputStreamReader inputStreamReader = null; + FileInputStream fileInputStream = null; + + try { + fileInputStream = new FileInputStream(robotFilename); + inputStreamReader = new InputStreamReader(fileInputStream, "UTF8"); + bufferedReader = new BufferedReader(inputStreamReader); + + EditWindow editWindow = new EditWindow(repositoryManager, this, robotsDirectory); + + EditorPane editorPane = editWindow.getEditorPane(); + + editorPane.read(bufferedReader, new File(robotFilename)); + + editWindow.setFileName(robotFilename); + + addPlaceShowFocus(editWindow); + } catch (Exception e) { + JOptionPane.showMessageDialog(this, e.toString()); + Logger.logError(e); + } finally { + FileUtil.cleanupStream(bufferedReader); + } + } + } + + public void extractRobot() { + windowManager.showRobotExtractor(this); + } + + public void run() { + getCompiler(); + } + + public void saveAsRobot() { + EditWindow editWindow = getActiveWindow(); + + if (editWindow != null) { + editWindow.fileSaveAs(); + } + } + + public void resetCompilerProperties() { + CompilerProperties props = Container.getComponent(RobocodeCompilerFactory.class).getCompilerProperties(); + + props.resetCompiler(); + Container.getComponent(RobocodeCompilerFactory.class).saveCompilerProperties(); + getCompiler(); + } + + public void saveRobot() { + EditWindow editWindow = getActiveWindow(); + + if (editWindow != null) { + editWindow.fileSave(false); + } + } + + public void setLineStatus(int line) { + if (line >= 0) { + getLineLabel().setText("Line: " + (line + 1)); + } else { + getLineLabel().setText(""); + } + } + + public void showHelpApi() { + String helpurl = "file:" + new File(FileUtil.getCwd(), "").getAbsoluteFile() + File.separator + "javadoc" + + File.separator + "index.html"; + + try { + BrowserManager.openURL(helpurl); + } catch (IOException e) { + JOptionPane.showMessageDialog(this, e.getMessage(), "Unable to open browser!", + JOptionPane.INFORMATION_MESSAGE); + } + } + + public void setSaveFileMenuItemsEnabled(boolean enabled) { + robocodeEditorMenuBar.getFileSaveAsMenuItem().setEnabled(enabled); + robocodeEditorMenuBar.getFileSaveMenuItem().setEnabled(enabled); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeEditorMenuBar.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeEditorMenuBar.java new file mode 100644 index 0000000..e3bde6a --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/RobocodeEditorMenuBar.java @@ -0,0 +1,722 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import net.sf.robocode.ui.dialog.WindowUtil; +import static net.sf.robocode.ui.util.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; + +import javax.swing.*; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + + +/** + * Menu bar for the Robocode source code editor. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Matthew Reeder (contributor) + */ +@SuppressWarnings("serial") +public class RobocodeEditorMenuBar extends JMenuBar { + + private final RobocodeEditor editor; + private final EventHandler eventHandler = new EventHandler(); + + private class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + final Object source = e.getSource(); + + if (source == RobocodeEditorMenuBar.this.getFileNewRobotMenuItem()) { + fileNewRobotActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getFileNewJuniorRobotMenuItem()) { + fileNewJuniorRobotActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getFileNewJavaFileMenuItem()) { + fileNewJavaFileActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getFileOpenMenuItem()) { + fileOpenActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getFileExtractMenuItem()) { + fileExtractActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getFileSaveMenuItem()) { + fileSaveActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getFileSaveAsMenuItem()) { + fileSaveAsActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getFileExitMenuItem()) { + fileExitActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getCompilerCompileMenuItem()) { + compilerCompileActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getCompilerOptionsPreferencesMenuItem()) { + compilerOptionsPreferencesActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getCompilerOptionsResetCompilerMenuItem()) { + compilerOptionsResetCompilerActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getHelpRobocodeApiMenuItem()) { + helpRobocodeApiActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditUndoMenuItem()) { + editUndoActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditRedoMenuItem()) { + editRedoActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditCutMenuItem()) { + editCutActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditCopyMenuItem()) { + editCopyActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditPasteMenuItem()) { + editPasteActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditDeleteMenuItem()) { + editDeleteActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditSelectAllMenuItem()) { + editSelectAllActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditFindMenuItem()) { + editFindActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditFindNextMenuItem()) { + editFindNextActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getEditReplaceMenuItem()) { + editReplaceActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getWindowCloseMenuItem()) { + windowCloseActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getWindowCloseAllMenuItem()) { + windowCloseAllActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getWindowWindowsDialogMenuItem()) { + windowMoreWindowsActionPerformed(); + } else if (source == RobocodeEditorMenuBar.this.getViewEditorThemeConfigDialogMenuItem()) { + viewEditorThemeConfigDialogActionPerformed(); + } + } + } + + // File menu + private JMenu fileMenu; + private JMenuItem fileOpenMenuItem; + private JMenuItem fileExtractMenuItem; + private JMenuItem fileSaveMenuItem; + private JMenuItem fileSaveAsMenuItem; + private JMenuItem fileExitMenuItem; + private JMenuItem fileNewJavaFileMenuItem; + private JMenu fileNewMenu; + private JMenuItem fileNewRobotMenuItem; + private JMenuItem fileNewJuniorRobotMenuItem; + + // Compiler menu + private JMenuItem compilerCompileMenuItem; + private JMenu compilerMenu; + private JMenu compilerOptionsMenu; + private JMenuItem compilerOptionsPreferencesMenuItem; + private JMenuItem compilerOptionsResetCompilerMenuItem; + + // Edit menu + private JMenu editMenu; + private JMenuItem editUndoMenuItem; + private JMenuItem editRedoMenuItem; + private JMenuItem editCutMenuItem; + private JMenuItem editCopyMenuItem; + private JMenuItem editPasteMenuItem; + private JMenuItem editDeleteMenuItem; + private JMenuItem editFindMenuItem; + private JMenuItem editFindNextMenuItem; + private JMenuItem editReplaceMenuItem; + private JMenuItem editSelectAllMenuItem; + + // View menu + private JMenu viewMenu; + private JMenuItem viewEditorThemeConfigDialogMenuItem; + + // Window menu + private JMenu windowMenu; + private JMenuItem windowCloseMenuItem; + private JMenuItem windowCloseAllMenuItem; + private JMenuItem windowWindowsDialogMenuItem; + private MoreWindowsDialog moreWindowsDialog; + + // Help menu + private JMenu helpMenu; + private JMenuItem helpRobocodeApiMenuItem; + + public RobocodeEditorMenuBar(RobocodeEditor editor) { + super(); + this.editor = editor; + initialize(); + } + + private void initialize() { + add(getFileMenu()); + add(getEditMenu()); + add(getViewMenu()); + add(getCompilerMenu()); + add(getWindowMenu()); + add(getHelpMenu()); + } + + private void compilerCompileActionPerformed() { + EditWindow editWindow = editor.getActiveWindow(); + if (editWindow != null) { + editWindow.compile(); + } + } + + private void compilerOptionsPreferencesActionPerformed() { + CompilerPreferencesDialog dialog = new CompilerPreferencesDialog(editor); + WindowUtil.packCenterShow(editor, dialog); + } + + private void compilerOptionsResetCompilerActionPerformed() { + if (JOptionPane.showConfirmDialog(editor, + "You are about to reset the compiler preferences. Do you wish to proceed?", "Reset Compiler Preferences", + JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) + == JOptionPane.NO_OPTION) { + return; + } + + new Thread(new Runnable() { + public void run() { + editor.resetCompilerProperties(); + } + }).start(); + } + + private void fileExitActionPerformed() { + editor.dispose(); + } + + private void fileNewJavaFileActionPerformed() { + editor.createNewJavaFile(); + + getFileSaveMenuItem().setEnabled(true); + getFileSaveAsMenuItem().setEnabled(true); + } + + private void fileNewRobotActionPerformed() { + editor.createNewRobot(); + + getFileSaveMenuItem().setEnabled(true); + getFileSaveAsMenuItem().setEnabled(true); + } + + private void fileNewJuniorRobotActionPerformed() { + editor.createNewJuniorRobot(); + + getFileSaveMenuItem().setEnabled(true); + getFileSaveAsMenuItem().setEnabled(true); + } + + private void fileOpenActionPerformed() { + editor.openRobot(); + } + + private void fileExtractActionPerformed() { + editor.extractRobot(); + } + + private void fileSaveActionPerformed() { + editor.saveRobot(); + } + + private void fileSaveAsActionPerformed() { + editor.saveAsRobot(); + } + + private void editUndoActionPerformed() { + EditWindow editWindow = editor.getActiveWindow(); + if (editWindow != null) { + editWindow.getEditorPane().undo(); + } + } + + private void editRedoActionPerformed() { + EditWindow editWindow = editor.getActiveWindow(); + if (editWindow != null) { + editWindow.getEditorPane().redo(); + } + } + + private void editCutActionPerformed() { + EditWindow editWindow = editor.getActiveWindow(); + + if (editWindow != null) { + editWindow.getEditorPane().cut(); + } + } + + private void editCopyActionPerformed() { + EditWindow editWindow = editor.getActiveWindow(); + if (editWindow != null) { + editWindow.getEditorPane().copy(); + } + } + + private void editPasteActionPerformed() { + EditWindow editWindow = editor.getActiveWindow(); + if (editWindow != null) { + editWindow.getEditorPane().paste(); + } + } + + private void editDeleteActionPerformed() { + EditWindow editWindow = editor.getActiveWindow(); + if (editWindow != null) { + editWindow.getEditorPane().replaceSelection(null); + } + } + + private void editSelectAllActionPerformed() { + EditWindow editWindow = editor.getActiveWindow(); + if (editWindow != null) { + editWindow.getEditorPane().selectAll(); + } + } + + private void editFindActionPerformed() { + editor.findDialog(); + } + + private void editReplaceActionPerformed() { + editor.replaceDialog(); + } + + private void editFindNextActionPerformed() { + editor.getFindReplaceDialog().findNext(); + } + + private void windowCloseActionPerformed() { + EditWindow editWindow = editor.getActiveWindow(); + if (editWindow != null) { + editWindow.doDefaultCloseAction(); + } + } + + private void windowCloseAllActionPerformed() { + JInternalFrame[] frames = editor.getDesktopPane().getAllFrames(); + if (frames != null) { + for (JInternalFrame frame : frames) { + frame.doDefaultCloseAction(); + } + } + } + + private void windowMoreWindowsActionPerformed() { + getMoreWindowsDialog().setVisible(true); + } + + private void viewEditorThemeConfigDialogActionPerformed() { + EditorThemeConfigDialog dialog = new EditorThemeConfigDialog(editor); + WindowUtil.packCenterShow(dialog); + } + + private JMenuItem getCompilerCompileMenuItem() { + if (compilerCompileMenuItem == null) { + compilerCompileMenuItem = new JMenuItem(); + compilerCompileMenuItem.setText("Compile"); + compilerCompileMenuItem.setMnemonic('m'); + compilerCompileMenuItem.setDisplayedMnemonicIndex(2); + compilerCompileMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, MENU_SHORTCUT_KEY_MASK)); + compilerCompileMenuItem.addActionListener(eventHandler); + } + return compilerCompileMenuItem; + } + + private JMenu getCompilerMenu() { + if (compilerMenu == null) { + compilerMenu = new JMenu(); + compilerMenu.setText("Compiler"); + compilerMenu.setMnemonic('C'); + compilerMenu.add(getCompilerCompileMenuItem()); + compilerMenu.add(getCompilerOptionsMenu()); + } + return compilerMenu; + } + + private JMenu getCompilerOptionsMenu() { + if (compilerOptionsMenu == null) { + compilerOptionsMenu = new JMenu(); + compilerOptionsMenu.setText("Options"); + compilerOptionsMenu.setMnemonic('O'); + compilerOptionsMenu.add(getCompilerOptionsPreferencesMenuItem()); + compilerOptionsMenu.add(getCompilerOptionsResetCompilerMenuItem()); + } + return compilerOptionsMenu; + } + + private JMenuItem getCompilerOptionsPreferencesMenuItem() { + if (compilerOptionsPreferencesMenuItem == null) { + compilerOptionsPreferencesMenuItem = new JMenuItem(); + compilerOptionsPreferencesMenuItem.setText("Preferences"); + compilerOptionsPreferencesMenuItem.setMnemonic('P'); + compilerOptionsPreferencesMenuItem.addActionListener(eventHandler); + } + return compilerOptionsPreferencesMenuItem; + } + + private JMenuItem getCompilerOptionsResetCompilerMenuItem() { + if (compilerOptionsResetCompilerMenuItem == null) { + compilerOptionsResetCompilerMenuItem = new JMenuItem(); + compilerOptionsResetCompilerMenuItem.setText("Reset Compiler"); + compilerOptionsResetCompilerMenuItem.setMnemonic('R'); + compilerOptionsResetCompilerMenuItem.addActionListener(eventHandler); + } + return compilerOptionsResetCompilerMenuItem; + } + + private JMenuItem getFileExitMenuItem() { + if (fileExitMenuItem == null) { + fileExitMenuItem = new JMenuItem(); + fileExitMenuItem.setText("Exit"); + fileExitMenuItem.setMnemonic('x'); + fileExitMenuItem.setDisplayedMnemonicIndex(1); + fileExitMenuItem.addActionListener(eventHandler); + } + return fileExitMenuItem; + } + + private JMenu getFileMenu() { + if (fileMenu == null) { + fileMenu = new JMenu(); + fileMenu.setText("File"); + fileMenu.setMnemonic('F'); + fileMenu.add(getFileNewMenu()); + fileMenu.add(getFileOpenMenuItem()); + fileMenu.add(getFileExtractMenuItem()); + fileMenu.add(getFileSaveMenuItem()); + fileMenu.add(getFileSaveAsMenuItem()); + fileMenu.add(new JSeparator()); + fileMenu.add(getFileExitMenuItem()); + } + return fileMenu; + } + + private JMenuItem getFileNewJavaFileMenuItem() { + if (fileNewJavaFileMenuItem == null) { + fileNewJavaFileMenuItem = new JMenuItem(); + fileNewJavaFileMenuItem.setText("Java File"); + fileNewJavaFileMenuItem.setMnemonic('J'); + fileNewJavaFileMenuItem.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_N, MENU_SHORTCUT_KEY_MASK | Event.SHIFT_MASK)); + fileNewJavaFileMenuItem.addActionListener(eventHandler); + } + return fileNewJavaFileMenuItem; + } + + private JMenu getFileNewMenu() { + if (fileNewMenu == null) { + fileNewMenu = new JMenu(); + fileNewMenu.setText("New"); + fileNewMenu.setMnemonic('N'); + fileNewMenu.add(getFileNewRobotMenuItem()); + fileNewMenu.add(getFileNewJuniorRobotMenuItem()); + fileNewMenu.add(getFileNewJavaFileMenuItem()); + } + return fileNewMenu; + } + + private JMenuItem getFileNewRobotMenuItem() { + if (fileNewRobotMenuItem == null) { + fileNewRobotMenuItem = new JMenuItem(); + fileNewRobotMenuItem.setText("Robot"); + fileNewRobotMenuItem.setMnemonic('R'); + fileNewRobotMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, MENU_SHORTCUT_KEY_MASK)); + fileNewRobotMenuItem.addActionListener(eventHandler); + } + return fileNewRobotMenuItem; + } + + private JMenuItem getFileNewJuniorRobotMenuItem() { + if (fileNewJuniorRobotMenuItem == null) { + fileNewJuniorRobotMenuItem = new JMenuItem(); + fileNewJuniorRobotMenuItem.setText("JuniorRobot"); + fileNewJuniorRobotMenuItem.setMnemonic('J'); + fileNewJuniorRobotMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_J, MENU_SHORTCUT_KEY_MASK)); + fileNewJuniorRobotMenuItem.addActionListener(eventHandler); + } + return fileNewJuniorRobotMenuItem; + } + + private JMenuItem getFileOpenMenuItem() { + if (fileOpenMenuItem == null) { + fileOpenMenuItem = new JMenuItem(); + fileOpenMenuItem.setText("Open"); + fileOpenMenuItem.setMnemonic('O'); + fileOpenMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, MENU_SHORTCUT_KEY_MASK)); + fileOpenMenuItem.addActionListener(eventHandler); + } + return fileOpenMenuItem; + } + + private JMenuItem getFileExtractMenuItem() { + if (fileExtractMenuItem == null) { + fileExtractMenuItem = new JMenuItem(); + fileExtractMenuItem.setText("Extract downloaded robot for editing"); + fileExtractMenuItem.setMnemonic('t'); + fileExtractMenuItem.setDisplayedMnemonicIndex(2); + fileExtractMenuItem.addActionListener(eventHandler); + } + return fileExtractMenuItem; + } + + public JMenuItem getFileSaveAsMenuItem() { + if (fileSaveAsMenuItem == null) { + fileSaveAsMenuItem = new JMenuItem(); + fileSaveAsMenuItem.setText("Save As"); + fileSaveAsMenuItem.setMnemonic('A'); + fileSaveAsMenuItem.setDisplayedMnemonicIndex(5); + fileSaveAsMenuItem.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_SHORTCUT_KEY_MASK | Event.SHIFT_MASK)); + fileSaveAsMenuItem.addActionListener(eventHandler); + fileSaveAsMenuItem.setEnabled(false); + } + return fileSaveAsMenuItem; + } + + public JMenuItem getFileSaveMenuItem() { + if (fileSaveMenuItem == null) { + fileSaveMenuItem = new JMenuItem(); + fileSaveMenuItem.setText("Save"); + fileSaveMenuItem.setMnemonic('S'); + fileSaveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_SHORTCUT_KEY_MASK)); + fileSaveMenuItem.addActionListener(eventHandler); + fileSaveMenuItem.setEnabled(false); + } + return fileSaveMenuItem; + } + + @Override + public JMenu getHelpMenu() { + if (helpMenu == null) { + helpMenu = new JMenu(); + helpMenu.setText("Help"); + helpMenu.setMnemonic('H'); + helpMenu.add(getHelpRobocodeApiMenuItem()); + } + return helpMenu; + } + + private JMenuItem getHelpRobocodeApiMenuItem() { + if (helpRobocodeApiMenuItem == null) { + helpRobocodeApiMenuItem = new JMenuItem(); + helpRobocodeApiMenuItem.setText("Robocode API"); + helpRobocodeApiMenuItem.setMnemonic('A'); + helpRobocodeApiMenuItem.setDisplayedMnemonicIndex(9); + helpRobocodeApiMenuItem.addActionListener(eventHandler); + } + return helpRobocodeApiMenuItem; + } + + private JMenu getEditMenu() { + if (editMenu == null) { + editMenu = new JMenu(); + editMenu.setText("Edit"); + editMenu.setMnemonic('E'); + editMenu.add(getEditUndoMenuItem()); + editMenu.add(getEditRedoMenuItem()); + editMenu.addSeparator(); + editMenu.add(getEditCutMenuItem()); + editMenu.add(getEditCopyMenuItem()); + editMenu.add(getEditPasteMenuItem()); + editMenu.add(getEditDeleteMenuItem()); + editMenu.addSeparator(); + editMenu.add(getEditFindMenuItem()); + editMenu.add(getEditFindNextMenuItem()); + editMenu.add(getEditReplaceMenuItem()); + editMenu.addSeparator(); + editMenu.add(getEditSelectAllMenuItem()); + } + return editMenu; + } + + private JMenuItem getEditUndoMenuItem() { + if (editUndoMenuItem == null) { + editUndoMenuItem = new JMenuItem(); + editUndoMenuItem.setText("Undo"); + editUndoMenuItem.setMnemonic('U'); + editUndoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, MENU_SHORTCUT_KEY_MASK)); + editUndoMenuItem.addActionListener(eventHandler); + } + return editUndoMenuItem; + } + + private JMenuItem getEditRedoMenuItem() { + if (editRedoMenuItem == null) { + editRedoMenuItem = new JMenuItem(); + editRedoMenuItem.setText("Redo"); + editRedoMenuItem.setMnemonic('R'); + editRedoMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, MENU_SHORTCUT_KEY_MASK)); + editRedoMenuItem.addActionListener(eventHandler); + } + return editRedoMenuItem; + } + + private JMenuItem getEditCutMenuItem() { + if (editCutMenuItem == null) { + editCutMenuItem = new JMenuItem(); + editCutMenuItem.setText("Cut"); + editCutMenuItem.setMnemonic('t'); + editCutMenuItem.setDisplayedMnemonicIndex(2); + editCutMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, MENU_SHORTCUT_KEY_MASK)); + editCutMenuItem.addActionListener(eventHandler); + } + return editCutMenuItem; + } + + private JMenuItem getEditCopyMenuItem() { + if (editCopyMenuItem == null) { + editCopyMenuItem = new JMenuItem(); + editCopyMenuItem.setText("Copy"); + editCopyMenuItem.setMnemonic('C'); + editCopyMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, MENU_SHORTCUT_KEY_MASK)); + editCopyMenuItem.addActionListener(eventHandler); + } + return editCopyMenuItem; + } + + private JMenuItem getEditPasteMenuItem() { + if (editPasteMenuItem == null) { + editPasteMenuItem = new JMenuItem(); + editPasteMenuItem.setText("Paste"); + editPasteMenuItem.setMnemonic('P'); + editPasteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, MENU_SHORTCUT_KEY_MASK)); + editPasteMenuItem.addActionListener(eventHandler); + } + return editPasteMenuItem; + } + + private JMenuItem getEditDeleteMenuItem() { + if (editDeleteMenuItem == null) { + editDeleteMenuItem = new JMenuItem(); + editDeleteMenuItem.setText("Delete"); + editDeleteMenuItem.setMnemonic('l'); + editDeleteMenuItem.setDisplayedMnemonicIndex(2); + editDeleteMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)); + editDeleteMenuItem.addActionListener(eventHandler); + } + return editDeleteMenuItem; + } + + private JMenuItem getEditFindMenuItem() { + if (editFindMenuItem == null) { + editFindMenuItem = new JMenuItem(); + editFindMenuItem.setText("Find..."); + editFindMenuItem.setMnemonic('F'); + editFindMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, MENU_SHORTCUT_KEY_MASK)); + editFindMenuItem.addActionListener(eventHandler); + } + return editFindMenuItem; + } + + private JMenuItem getEditFindNextMenuItem() { + if (editFindNextMenuItem == null) { + editFindNextMenuItem = new JMenuItem(); + editFindNextMenuItem.setText("Find Next"); + editFindNextMenuItem.setMnemonic('N'); + editFindNextMenuItem.setDisplayedMnemonicIndex(5); + editFindNextMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, MENU_SHORTCUT_KEY_MASK)); + editFindNextMenuItem.addActionListener(eventHandler); + } + return editFindNextMenuItem; + } + + private JMenuItem getEditReplaceMenuItem() { + if (editReplaceMenuItem == null) { + editReplaceMenuItem = new JMenuItem(); + editReplaceMenuItem.setText("Replace..."); + editReplaceMenuItem.setMnemonic('R'); + editReplaceMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, MENU_SHORTCUT_KEY_MASK)); + editReplaceMenuItem.addActionListener(eventHandler); + } + return editReplaceMenuItem; + } + + private JMenuItem getEditSelectAllMenuItem() { + if (editSelectAllMenuItem == null) { + editSelectAllMenuItem = new JMenuItem(); + editSelectAllMenuItem.setText("Select All"); + editSelectAllMenuItem.setMnemonic('A'); + editSelectAllMenuItem.setDisplayedMnemonicIndex(7); + editSelectAllMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, MENU_SHORTCUT_KEY_MASK)); + editSelectAllMenuItem.addActionListener(eventHandler); + } + return editSelectAllMenuItem; + } + + public JMenu getWindowMenu() { + if (windowMenu == null) { + windowMenu = new JMenu(); + windowMenu.setText("Window"); + windowMenu.setMnemonic('W'); + // If you add more items to this menu, you need to update the + // constants in WindowMenuItem, too, or the dynamic part of the + // window menu won't operate correctly. + windowMenu.add(getWindowCloseMenuItem()); + windowMenu.add(getWindowCloseAllMenuItem()); + windowMenu.addSeparator(); + // stuff will be inserted here... + windowMenu.add(getWindowWindowsDialogMenuItem()); + } + return windowMenu; + } + + private JMenuItem getWindowCloseMenuItem() { + if (windowCloseMenuItem == null) { + windowCloseMenuItem = new JMenuItem(); + windowCloseMenuItem.setText("Close"); + windowCloseMenuItem.setMnemonic('C'); + windowCloseMenuItem.addActionListener(eventHandler); + } + return windowCloseMenuItem; + } + + private JMenuItem getWindowCloseAllMenuItem() { + if (windowCloseAllMenuItem == null) { + windowCloseAllMenuItem = new JMenuItem(); + windowCloseAllMenuItem.setText("Close All"); + windowCloseAllMenuItem.setMnemonic('A'); + windowCloseAllMenuItem.setDisplayedMnemonicIndex(6); + windowCloseAllMenuItem.addActionListener(eventHandler); + } + return windowCloseAllMenuItem; + } + + private JMenuItem getWindowWindowsDialogMenuItem() { + if (windowWindowsDialogMenuItem == null) { + windowWindowsDialogMenuItem = new WindowMenuItem(); + windowWindowsDialogMenuItem.addActionListener(eventHandler); + } + return windowWindowsDialogMenuItem; + } + + public MoreWindowsDialog getMoreWindowsDialog() { + if (moreWindowsDialog == null) { + moreWindowsDialog = new MoreWindowsDialog(editor); + } + return moreWindowsDialog; + } + + private void helpRobocodeApiActionPerformed() { + editor.showHelpApi(); + } + + private JMenu getViewMenu() { + if (viewMenu == null) { + viewMenu = new JMenu(); + viewMenu.setText("View"); + viewMenu.setMnemonic('V'); + + viewMenu.add(getViewEditorThemeConfigDialogMenuItem()); + } + return viewMenu; + } + + private JMenuItem getViewEditorThemeConfigDialogMenuItem() { + if (viewEditorThemeConfigDialogMenuItem == null) { + viewEditorThemeConfigDialogMenuItem = new JMenuItem(); + viewEditorThemeConfigDialogMenuItem.setText("Change Editor Theme"); + viewEditorThemeConfigDialogMenuItem.setMnemonic('T'); + viewEditorThemeConfigDialogMenuItem.addActionListener(eventHandler); + } + return viewEditorThemeConfigDialogMenuItem; + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/StyledDocument.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/StyledDocument.java new file mode 100644 index 0000000..9a66fbf --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/StyledDocument.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import javax.swing.text.DefaultStyledDocument; +import javax.swing.text.Element; + + +/** + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class StyledDocument extends DefaultStyledDocument { + + /** + * Returns the element index from an offset. + * + * @param offset + * is the offset to retrieve the element index from. + * @return the element index >= 0. + */ + protected int getElementIndex(int offset) { + return getDefaultRootElement().getElementIndex(offset); + } + + /** + * Returns the end offset of an element. + * Notice, that the end offset is off-by-one, and hence this method wraps the Element.getEndOffset() + * + * @param element is the element to get the end offset from. + * @return the end offset of the element. + */ + protected int getEndOffset(Element element) { + return Math.min(getLength(), element.getEndOffset()); + } + + /** + * Returns the child element at the given element index. + * + * @param index + * is the element index. + * @return the child element. + */ + protected Element getElement(int index) { + return getDefaultRootElement().getElement(index); + } + + /** + * Returns the child element at the given document offset. + * + * @param offset + * is the document offset. + * @return the child element. + */ + protected Element getElementFromOffset(int offset) { + return getElement(getElementIndex(offset)); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/UndoManagerWithActions.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/UndoManagerWithActions.java new file mode 100644 index 0000000..4293351 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/UndoManagerWithActions.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.event.UndoableEditEvent; +import javax.swing.undo.CannotUndoException; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.UndoManager; + + +/** + * Undo manager containing actions for performing undo and redo edits. + * + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class UndoManagerWithActions extends UndoManager { + + private Action undoAction = new UndoAction(); + private Action redoAction = new RedoAction(); + + public UndoManagerWithActions() { + super(); + updateUndoRedoState(); + } + + @Override + public synchronized void undo() throws CannotUndoException { + super.undo(); + updateUndoRedoState(); + } + + @Override + public synchronized void redo() throws CannotRedoException { + super.redo(); + updateUndoRedoState(); + } + + @Override + public void undoableEditHappened(UndoableEditEvent undoableEditEvent) { + super.undoableEditHappened(undoableEditEvent); + updateUndoRedoState(); + } + + public Action getUndoAction() { + return undoAction; + } + + public Action getRedoAction() { + return redoAction; + } + + protected void updateUndoRedoState() { + undoAction.setEnabled(canUndo()); + redoAction.setEnabled(canRedo()); + } + + private class UndoAction extends AbstractAction { + public UndoAction() { + super("Undo"); + } + + public void actionPerformed(ActionEvent ae) { + try { + undo(); + } catch (CannotUndoException e) { + Toolkit.getDefaultToolkit().beep(); + } + } + } + + + private class RedoAction extends AbstractAction { + public RedoAction() { + super("Redo"); + } + + public void actionPerformed(ActionEvent ae) { + try { + redo(); + } catch (CannotRedoException e) { + Toolkit.getDefaultToolkit().beep(); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ColorAndStyle.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ColorAndStyle.java new file mode 100644 index 0000000..bbdedc1 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ColorAndStyle.java @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JColorChooser; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.border.BevelBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import net.sf.robocode.ui.editor.FontStyle; + + +/** + * Class that is used for maintaining a text color and font style for an editor. + * + * @author Flemming N. Larsen (original) + * @since 1.8.3.0 + */ +public class ColorAndStyle { + private final JLabel label; + private final JButton coloredButton; + private final JComboBox fontStyleComboBox; + private final List listeners = new ArrayList(); + + private Color oldColor; + private FontStyle oldStyle; + + public ColorAndStyle(String label, final Color color, final FontStyle fontStyle) { + this.label = new JLabel(label); + + coloredButton = createColoredButton(color); + if (coloredButton != null) { + coloredButton.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + if (!coloredButton.getBackground().equals(color)) { + notifyColorChanged(coloredButton.getBackground()); + } + } + }); + } + + fontStyleComboBox = fontStyle == null ? null : ComboBoxUtil.createFontStyleComboBox(fontStyle); + if (fontStyleComboBox != null) { + fontStyleComboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + FontStyle newStyle = ComboBoxUtil.getSelectedStyle(fontStyleComboBox); + if (oldStyle != newStyle) { + notifyStyleChanged(newStyle); + oldStyle = newStyle; + } + } + }); + } + } + + public JLabel getLabel() { + return label; + } + + public JButton getColoredButton() { + return coloredButton; + } + + public JComboBox getFontStyleComboBox() { + return fontStyleComboBox; + } + + public void addListener(IColorAndStyleListener listener) { + listeners.add(listener); + } + + public void removeListener(IColorAndStyleListener listener) { + listeners.remove(listener); + } + + public Color getSelectedColor() { + return (coloredButton == null) ? null : coloredButton.getBackground(); + } + + public void setSelectedColor(Color newColor) { + if (coloredButton != null) { + coloredButton.setBackground(newColor); + } + notifyColorChanged(newColor); + } + + public FontStyle getSelectedStyle() { + return (fontStyleComboBox == null) ? null : ComboBoxUtil.getSelectedStyle(fontStyleComboBox); + } + + public void setSelectedStyle(FontStyle newStyle) { + if (fontStyleComboBox != null) { + ComboBoxUtil.setSelected(fontStyleComboBox, newStyle); + } + notifyStyleChanged(newStyle); + } + + private void notifyColorChanged(Color newColor) { + if (newColor == null || !newColor.equals(oldColor)) { + for (IColorAndStyleListener listener : listeners) { + listener.colorChanged(newColor); + } + oldColor = newColor; + } + } + + private void notifyStyleChanged(FontStyle newStyle) { + if (newStyle == null || !newStyle.equals(oldStyle)) { + for (IColorAndStyleListener listener : listeners) { + listener.styleChanged(newStyle); + } + oldStyle = newStyle; + } + } + + private static JButton createColoredButton(Color color) { + final JButton button = new JButton(); + button.setBackground(color); + button.setContentAreaFilled(false); + button.setOpaque(true); + Dimension size = new Dimension(24, 24); + button.setPreferredSize(size); + button.setSize(size); + button.setMaximumSize(size); + button.setMinimumSize(size); + button.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); + + button.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Color selectedColor = JColorChooser.showDialog(null, "Pick a color", button.getBackground()); + if (selectedColor != null) { + button.setBackground(selectedColor); + } + } + }); + + return button; + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ColorAndStyleAdapter.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ColorAndStyleAdapter.java new file mode 100644 index 0000000..270f58c --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ColorAndStyleAdapter.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import java.awt.Color; + +import net.sf.robocode.ui.editor.FontStyle; + + +/** + * Adapter class for the {@link IColorAndStyleListener} interface. + * + * @author Flemming N. Larsen (original) + * @since 1.8.3.0 + */ +public abstract class ColorAndStyleAdapter implements IColorAndStyleListener { + @Override + public void colorChanged(Color newColor) {} + + @Override + public void styleChanged(FontStyle newStyle) {} +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ComboBoxUtil.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ComboBoxUtil.java new file mode 100644 index 0000000..853df84 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/ComboBoxUtil.java @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import java.awt.Component; +import java.awt.Font; +import java.util.ArrayList; +import java.util.List; + +import javax.swing.ComboBoxModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; + +import net.sf.robocode.ui.editor.FontStyle; + + +/** + * Class for utilizing JComboBoxes. + * + * @author Flemming N. Larsen (original) + * @since 1.8.3.0 + */ +public class ComboBoxUtil { + + public static void setSelected(JComboBox comboBox, String name) { + ComboBoxModel model = comboBox.getModel(); + for (int i = 0; i < model.getSize(); i++) { + String itemName = (String) model.getElementAt(i); + if (itemName.equalsIgnoreCase(name)) { + model.setSelectedItem(itemName); + break; + } + } + } + + public static void setSelected(JComboBox comboBox, FontStyle fontStyle) { + ComboBoxModel model = comboBox.getModel(); + for (int i = 0; i < model.getSize(); i++) { + String name = (String) model.getElementAt(i); + FontStyle style = FontStyle.fromName(name); + if (style != null && style == fontStyle) { + model.setSelectedItem(name); + break; + } + } + } + + public static String getSelectedName(JComboBox comboBox) { + return (String) comboBox.getSelectedItem(); + } + + public static JComboBox createFontStyleComboBox(FontStyle fontStyle) { + List fontStyles = new ArrayList(); + for (FontStyle style : FontStyle.values()) { + fontStyles.add(style.getName()); + } + JComboBox comboBox = new JComboBox(fontStyles.toArray()); + comboBox.setRenderer(new FontStyleCellRenderer()); + + ComboBoxUtil.setSelected(comboBox, fontStyle); + + return comboBox; + } + + public static FontStyle getSelectedStyle(JComboBox comboBox) { + return FontStyle.fromName((String) comboBox.getSelectedItem()); + } + + private static class FontStyleCellRenderer extends DefaultListCellRenderer { + private static final long serialVersionUID = 1L; + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + FontStyle fontStyle = FontStyle.fromName((String) value); + int styleFlags = (fontStyle == null) ? Font.PLAIN : fontStyle.getFontStyleFlags(); + + Font font = new Font((String) value, styleFlags, 12); + label.setFont(font); + return label; + } + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorProperties.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorProperties.java new file mode 100644 index 0000000..8843551 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorProperties.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Properties; + +import net.sf.robocode.ui.editor.IEditorProperties; + + +/** + * Handles the editor properties. + * + * @author Flemming N. Larsen (original) + * + * @since 1.8.3.0 + */ +public class EditorProperties implements IEditorProperties { + + private static final String DEFAULT_THEME_NAME = "Robocode White Theme"; + + private static final String THEME_NAME = "editor.theme"; + + private String themeName; + + private final Properties props = new Properties(); + + @Override + public String getThemeName() { + String themeName = this.themeName; + if (themeName == null) { + themeName = props.getProperty(THEME_NAME); + } + if (themeName == null) { + themeName = DEFAULT_THEME_NAME; + } else { + File file = EditorThemePropertiesManager.getFilepath(themeName); + if (!file.exists()) { + themeName = DEFAULT_THEME_NAME; + } + } + this.themeName = themeName; + return themeName; + } + + public void setThemeName(String themeName) { + this.themeName = themeName; + } + + public void load(InputStream is) throws IOException { + props.load(is); + + themeName = props.getProperty(THEME_NAME); + } + + public void store(OutputStream os, String header) throws IOException { + props.setProperty(THEME_NAME, themeName); + + props.store(os, header); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorPropertiesManager.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorPropertiesManager.java new file mode 100644 index 0000000..0b5add2 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorPropertiesManager.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import static net.sf.robocode.io.Logger.logError; +import static net.sf.robocode.io.Logger.logMessage; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; + + +/** + * Manages the editor property file. + * + * @author Flemming N. Larsen (original) + * + * @since 1.8.3.0 + */ +public class EditorPropertiesManager { + + private static EditorProperties editorProperties; + + public static EditorProperties getEditorProperties() { + if (editorProperties == null) { + editorProperties = new EditorProperties(); + + FileInputStream in = null; + File file = null; + try { + in = new FileInputStream(FileUtil.getEditorConfigFile()); + getEditorProperties().load(in); + } catch (FileNotFoundException e) { + logMessage("Editor properties file was not found. A new one will be created."); + } catch (IOException e) { + logError("Error while reading file: " + file, e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) {} + } + } + } + return editorProperties; + } + + public static void saveEditorProperties() { + FileOutputStream out = null; + try { + out = new FileOutputStream(FileUtil.getEditorConfigFile()); + getEditorProperties().store(out, "Robocode Editor Properties"); + } catch (IOException e) { + Logger.logError(e); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException ignored) {} + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemeProperties.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemeProperties.java new file mode 100644 index 0000000..b1ac011 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemeProperties.java @@ -0,0 +1,541 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import java.awt.Color; +import java.awt.Font; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Properties; + +import net.sf.robocode.ui.editor.FontStyle; + + +/** + * Handles the editor theme properties. + * + * @author Flemming N. Larsen (original) + * + * @since 1.8.3.0 + */ +public class EditorThemeProperties implements IEditorThemeProperties { + + // ---- Default Colors and Styles ---- + + private static final String DEFAULT_THEME_NAME = EditorPropertiesManager.getEditorProperties().getThemeName(); + + private static final String DEFAULT_FONT_NAME = "Monospaced"; + private static final int DEFAULT_FONT_SIZE = 14; + + private static final Color DEFAULT_BACKGROUND_COLOR = Color.WHITE; + + private static final Color DEFAULT_LINE_NUMBER_BACKGROUND_COLOR = new Color(0xDD, 0xDD, 0xDD); + private static final Color DEFAULT_LINE_NUMBER_TEXT_COLOR = Color.BLACK; + + private static final Color DEFAULT_HIGHLIGHTED_LINE_COLOR = new Color(0xFF, 0xFF, 0x7F); + private static final Color DEFAULT_SELECTION_COLOR = new Color(0x33, 0x99, 0xFF); + private static final Color DEFAULT_SELECTED_TEXT_COLOR = Color.WHITE; + + private static final Color DEFAULT_NORMAL_TEXT_COLOR = Color.BLACK; + private static final FontStyle DEFAULT_NORMAL_TEXT_STYLE = FontStyle.PLAIN; + + private static final Color DEFAULT_COMMENT_TEXT_COLOR = new Color(0x00, 0xAF, 0x00); + private static final FontStyle DEFAULT_COMMENT_TEXT_STYLE = FontStyle.PLAIN; + + private static final Color DEFAULT_QUOTED_TEXT_COLOR = new Color(0x7f, 0x00, 0x00); + private static final FontStyle DEFAULT_QUOTED_TEXT_STYLE = FontStyle.PLAIN; + + private static final Color DEFAULT_KEYWORD_TEXT_COLOR = new Color(0x00, 0x00, 0xAF); + private static final FontStyle DEFAULT_KEYWORD_TEXT_STYLE = FontStyle.BOLD; + + private static final Color DEFAULT_LITERAL_TEXT_COLOR = new Color(0x00, 0x00, 0xAF); + private static final FontStyle DEFAULT_LITERAL_TEXT_STYLE = FontStyle.BOLD; + + private static final Color DEFAULT_ANNOTATION_TEXT_COLOR = new Color(0x7F, 0x7F, 0x7F); + private static final FontStyle DEFAULT_ANNOTATION_TEXT_STYLE = FontStyle.BOLD; + + // ---- Property Names ---- + + private static final String THEME_NAME = "editor.theme"; + + private static final String FONT_NAME = "editor.font.name"; + private static final String FONT_SIZE = "editor.font.size"; + + private static final String BACKGROUND_COLOR = "editor.background.color"; + + private static final String LINE_NUMBER_BACKGROUND_COLOR = "editor.lineNumber.background.color"; + private static final String LINE_NUMBER_TEXT_COLOR = "editor.lineNumber.text.color"; + + private static final String HIGHLIGHTED_LINE_COLOR = "editor.highlighted.line.color"; + + private static final String SELECTION_COLOR = "editor.selected.background.color"; + private static final String SELECTED_TEXT_COLOR = "editor.selected.text.color"; + + private static final String NORMAL_TEXT_COLOR = "editor.text.color.normal"; + private static final String NORMAL_TEXT_STYLE = "editor.text.style.normal"; + + private static final String COMMENT_TEXT_COLOR = "editor.text.color.comment"; + private static final String COMMENT_TEXT_STYLE = "editor.text.style.comment"; + + private static final String QUOTED_TEXT_COLOR = "editor.text.color.quoted"; + private static final String QUOTED_TEXT_STYLE = "editor.text.style.quoted"; + + private static final String KEYWORD_TEXT_COLOR = "editor.text.color.keyword"; + private static final String KEYWORD_TEXT_STYLE = "editor.text.style.keyword"; + + private static final String LITERAL_TEXT_COLOR = "editor.text.color.literal"; + private static final String LITERAL_TEXT_STYLE = "editor.text.style.literal"; + + private static final String ANNOTATION_TEXT_COLOR = "editor.text.color.annotation"; + private static final String ANNOTATION_TEXT_STYLE = "editor.text.style.annotation"; + + private String themeName; + + private String fontName; + private Integer fontSize; + + private ColorPropertyStrategy backgroundColor = new ColorPropertyStrategy(BACKGROUND_COLOR, DEFAULT_BACKGROUND_COLOR); + private ColorPropertyStrategy lineNumberBackgroundColor = new ColorPropertyStrategy(LINE_NUMBER_BACKGROUND_COLOR, + DEFAULT_LINE_NUMBER_BACKGROUND_COLOR); + private ColorPropertyStrategy lineNumberTextColor = new ColorPropertyStrategy(LINE_NUMBER_TEXT_COLOR, + DEFAULT_LINE_NUMBER_TEXT_COLOR); + private ColorPropertyStrategy highlightedLineColor = new ColorPropertyStrategy(HIGHLIGHTED_LINE_COLOR, + DEFAULT_HIGHLIGHTED_LINE_COLOR); + private ColorPropertyStrategy selectionColor = new ColorPropertyStrategy(SELECTION_COLOR, DEFAULT_SELECTION_COLOR); + private ColorPropertyStrategy selectedTextColor = new ColorPropertyStrategy(SELECTED_TEXT_COLOR, + DEFAULT_SELECTED_TEXT_COLOR); + private ColorPropertyStrategy normalTextColor = new ColorPropertyStrategy(NORMAL_TEXT_COLOR, + DEFAULT_NORMAL_TEXT_COLOR); + private FontStylePropertyStrategy normalTextStyle = new FontStylePropertyStrategy(NORMAL_TEXT_STYLE, + DEFAULT_NORMAL_TEXT_STYLE); + private ColorPropertyStrategy commentTextColor = new ColorPropertyStrategy(COMMENT_TEXT_COLOR, + DEFAULT_COMMENT_TEXT_COLOR); + private FontStylePropertyStrategy commentTextStyle = new FontStylePropertyStrategy(COMMENT_TEXT_STYLE, + DEFAULT_COMMENT_TEXT_STYLE); + private ColorPropertyStrategy quotedTextColor = new ColorPropertyStrategy(QUOTED_TEXT_COLOR, + DEFAULT_QUOTED_TEXT_COLOR); + private FontStylePropertyStrategy quotedTextStyle = new FontStylePropertyStrategy(QUOTED_TEXT_STYLE, + DEFAULT_QUOTED_TEXT_STYLE); + private ColorPropertyStrategy keywordTextColor = new ColorPropertyStrategy(KEYWORD_TEXT_COLOR, + DEFAULT_KEYWORD_TEXT_COLOR); + private FontStylePropertyStrategy keywordTextStyle = new FontStylePropertyStrategy(KEYWORD_TEXT_STYLE, + DEFAULT_KEYWORD_TEXT_STYLE); + private ColorPropertyStrategy literalTextColor = new ColorPropertyStrategy(LITERAL_TEXT_COLOR, + DEFAULT_LITERAL_TEXT_COLOR); + private FontStylePropertyStrategy literalTextStyle = new FontStylePropertyStrategy(LITERAL_TEXT_STYLE, + DEFAULT_LITERAL_TEXT_STYLE); + private ColorPropertyStrategy annotationTextColor = new ColorPropertyStrategy(ANNOTATION_TEXT_COLOR, + DEFAULT_ANNOTATION_TEXT_COLOR); + private FontStylePropertyStrategy annotationTextStyle = new FontStylePropertyStrategy(ANNOTATION_TEXT_STYLE, + DEFAULT_ANNOTATION_TEXT_STYLE); + + private IPropertyStrategy[] colorAndStyleProps = new IPropertyStrategy[] { + backgroundColor, lineNumberBackgroundColor, lineNumberTextColor, highlightedLineColor, selectionColor, + selectedTextColor, normalTextColor, normalTextStyle, commentTextColor, commentTextStyle, quotedTextColor, + quotedTextStyle, keywordTextColor, keywordTextStyle, literalTextColor, literalTextStyle, annotationTextColor, + annotationTextStyle + }; + + private final Properties props = new Properties(); + + private boolean isChanged; + + public String getThemeName() { + String themeName = this.themeName; + if (themeName == null) { + themeName = props.getProperty(THEME_NAME); + } + if (themeName == null) { + themeName = DEFAULT_THEME_NAME; + } + this.themeName = themeName; + return themeName; + } + + public void setThemeName(String newName) { + this.themeName = newName; + EditorThemePropertiesManager.notifyThemeNameChanged(newName); + } + + public Font getFont() { + return new Font(getFontName(), getNormalTextStyle().getFontStyleFlags(), getFontSize()); + } + + public void setFontName(String newName) { + this.fontName = newName; + EditorThemePropertiesManager.notifyFontNameChanged(newName); + isChanged = true; + } + + @Override + public String getFontName() { + String fontName = this.fontName; + if (fontName == null) { + fontName = props.getProperty(FONT_NAME); + } + if (fontName == null) { + fontName = DEFAULT_FONT_NAME; + } + this.fontName = fontName; + return fontName; + } + + public void setFontSize(int newSize) { + this.fontSize = newSize; + EditorThemePropertiesManager.notifyFontSizeChanged(newSize); + isChanged = true; + } + + @Override + public int getFontSize() { + Integer fontSize = this.fontSize; + if (fontSize == null) { + String value = props.getProperty(FONT_SIZE); + try { + fontSize = Integer.parseInt(value); + } catch (NumberFormatException ignore) {} + } + if (fontSize == null) { + fontSize = DEFAULT_FONT_SIZE; + } + this.fontSize = fontSize; + return fontSize; + } + + public void setBackgroundColor(Color newColor) { + backgroundColor.set(newColor); + EditorThemePropertiesManager.notifyBackgroundColorChanged(newColor); + } + + @Override + public Color getBackgroundColor() { + return backgroundColor.get(); + } + + public void setLineNumberBackgroundColor(Color newColor) { + lineNumberBackgroundColor.set(newColor); + EditorThemePropertiesManager.notifyLineNumberBackgroundColorChanged(newColor); + } + + @Override + public Color getLineNumberBackgroundColor() { + return lineNumberBackgroundColor.get(); + } + + public void setLineNumberTextColor(Color newColor) { + lineNumberTextColor.set(newColor); + EditorThemePropertiesManager.notifyLineNumberTextColorChanged(newColor); + } + + @Override + public Color getLineNumberTextColor() { + return lineNumberTextColor.get(); + } + + public void setHighlightedLineColor(Color newColor) { + highlightedLineColor.set(newColor); + EditorThemePropertiesManager.notifyHighlightedLineColorChanged(newColor); + } + + @Override + public Color getHighlightedLineColor() { + return highlightedLineColor.get(); + } + + public void setSelectionColor(Color newColor) { + selectionColor.set(newColor); + EditorThemePropertiesManager.notifySelectionColorChanged(newColor); + } + + @Override + public Color getSelectionColor() { + return selectionColor.get(); + } + + public void setSelectedTextColor(Color newColor) { + selectedTextColor.set(newColor); + EditorThemePropertiesManager.notifySelectedTextColorChanged(newColor); + } + + @Override + public Color getSelectedTextColor() { + return selectedTextColor.get(); + } + + public void setNormalTextColor(Color newColor) { + normalTextColor.set(newColor); + EditorThemePropertiesManager.notifyNormalTextColorChanged(newColor); + } + + @Override + public Color getNormalTextColor() { + return normalTextColor.get(); + } + + public void setNormalTextStyle(FontStyle newStyle) { + normalTextStyle.set(newStyle); + EditorThemePropertiesManager.notifyNormalTextStyleChanged(newStyle); + } + + @Override + public FontStyle getNormalTextStyle() { + return normalTextStyle.get(); + } + + public void setCommentTextColor(Color newColor) { + commentTextColor.set(newColor); + EditorThemePropertiesManager.notifyCommentTextColorChanged(newColor); + } + + @Override + public Color getCommentTextColor() { + return commentTextColor.get(); + } + + public void setCommentTextStyle(FontStyle newStyle) { + commentTextStyle.set(newStyle); + EditorThemePropertiesManager.notifyCommentTextStyleChanged(newStyle); + } + + @Override + public FontStyle getCommentTextStyle() { + return commentTextStyle.get(); + } + + public void setQuotedTextColor(Color newColor) { + quotedTextColor.set(newColor); + EditorThemePropertiesManager.notifyQuotedTextColorChanged(newColor); + } + + @Override + public Color getQuotedTextColor() { + return quotedTextColor.get(); + } + + public void setQuotedTextStyle(FontStyle newStyle) { + quotedTextStyle.set(newStyle); + EditorThemePropertiesManager.notifyQuotedTextStyleChanged(newStyle); + } + + @Override + public FontStyle getQuotedTextStyle() { + return quotedTextStyle.get(); + } + + public void setKeywordTextColor(Color newColor) { + keywordTextColor.set(newColor); + EditorThemePropertiesManager.notifyKeywordTextColorChanged(newColor); + } + + @Override + public Color getKeywordTextColor() { + return keywordTextColor.get(); + } + + public void setKeywordTextStyle(FontStyle newStyle) { + keywordTextStyle.set(newStyle); + EditorThemePropertiesManager.notifyKeywordTextStyleChanged(newStyle); + } + + @Override + public FontStyle getKeywordTextStyle() { + return keywordTextStyle.get(); + } + + public void setLiteralTextColor(Color newColor) { + literalTextColor.set(newColor); + EditorThemePropertiesManager.notifyLiteralTextColorChanged(newColor); + } + + @Override + public Color getLiteralTextColor() { + return literalTextColor.get(); + } + + public void setLiteralTextStyle(FontStyle newStyle) { + literalTextStyle.set(newStyle); + EditorThemePropertiesManager.notifyLiteralTextStyleChanged(newStyle); + } + + @Override + public FontStyle getLiteralTextStyle() { + return literalTextStyle.get(); + } + + public void setAnnotationTextColor(Color newColor) { + annotationTextColor.set(newColor); + EditorThemePropertiesManager.notifyAnnotationTextColorChanged(newColor); + } + + @Override + public Color getAnnotationTextColor() { + return annotationTextColor.get(); + } + + public void setAnnotationTextStyle(FontStyle newStyle) { + annotationTextStyle.set(newStyle); + EditorThemePropertiesManager.notifyAnnotationTextStyleChanged(newStyle); + } + + @Override + public FontStyle getAnnotationTextStyle() { + return annotationTextStyle.get(); + } + + public void load(InputStream is) throws IOException { + // Reset (clean) the property values before loading them + for (IPropertyStrategy propertyStrategy : colorAndStyleProps) { + propertyStrategy.set(null); // clean value + propertyStrategy.save(); // store cleaned value in property + } + + props.load(is); + + themeName = props.getProperty(THEME_NAME, DEFAULT_THEME_NAME); + fontName = props.getProperty(FONT_NAME, DEFAULT_FONT_NAME); + try { + fontSize = Integer.parseInt(props.getProperty(FONT_SIZE, "" + DEFAULT_FONT_SIZE)); + } catch (NumberFormatException e) { + fontSize = DEFAULT_FONT_SIZE; + } + + for (IPropertyStrategy propertyStrategy : colorAndStyleProps) { + propertyStrategy.load(); + } + + // Reset 'changed' flag + isChanged = false; + } + + public void store(OutputStream os, String header) throws IOException { + props.setProperty(THEME_NAME, themeName); + props.setProperty(FONT_NAME, fontName); + props.setProperty(FONT_SIZE, "" + fontSize); + + for (IPropertyStrategy propertyStrategy : colorAndStyleProps) { + propertyStrategy.save(); + } + + props.store(os, header); + + // Reset 'changed' flag + isChanged = false; + } + + public boolean isChanged() { + return isChanged; + } + + interface IPropertyStrategy { + V get(); + void set(V value); + void load(); + void save(); + } + + + class ColorPropertyStrategy implements IPropertyStrategy { + + final String propertyName; + final Color defaultColor; + Color color; + + ColorPropertyStrategy(String propertyName, Color defaultColor) { + this.propertyName = propertyName; + this.defaultColor = defaultColor; + this.color = defaultColor; + } + + @Override + public Color get() { + return color == null ? defaultColor : color; + } + + @Override + public void set(Color color) { + if ((color == null && this.color == null) || (color != null && color.equals(this.color))) { + return; + } + this.color = color; + isChanged = true; + } + + @Override + public void load() { + color = fromPropertyToColor(propertyName); + } + + @Override + public void save() { + props.setProperty(propertyName, toHexString(get())); + } + + private Color fromPropertyToColor(String propertyName) { + String hexValue = props.getProperty(propertyName); + if (hexValue != null) { + try { + // Yes, we need to use a Long instead of an Integer here + + // we mask out the alpha channel + int rgb = (int) Long.parseLong(hexValue, 16) & 0x00FFFFFF; + return new Color(rgb); + } catch (NumberFormatException ignore) {} + } + return null; + } + } + + + class FontStylePropertyStrategy implements IPropertyStrategy { + + final String propertyName; + final FontStyle defaultStyle; + FontStyle style; + + FontStylePropertyStrategy(String propertyName, FontStyle defaultStyle) { + this.propertyName = propertyName; + this.defaultStyle = defaultStyle; + this.style = defaultStyle; + } + + @Override + public FontStyle get() { + return style == null ? defaultStyle : style; + } + + @Override + public void set(FontStyle style) { + if ((style == null && this.style == null) || (style != null && style.equals(this.style))) { + return; + } + this.style = style; + isChanged = true; + } + + @Override + public void load() { + style = fromPropertyToFontStyle(propertyName); + } + + @Override + public void save() { + props.setProperty(propertyName, "" + get().getName()); + } + + private FontStyle fromPropertyToFontStyle(String propertyName) { + String styleName = props.getProperty(propertyName); + return (styleName == null) ? null : FontStyle.fromName(styleName); + } + } + + private static String toHexString(Color color) { + // We mask out the alpha channel and format as RRGGBB + return String.format("%06X", color.getRGB() & 0x00FFFFFF); + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemePropertiesManager.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemePropertiesManager.java new file mode 100644 index 0000000..d696438 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemePropertiesManager.java @@ -0,0 +1,248 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import static net.sf.robocode.io.Logger.logError; + +import java.awt.Color; +import java.awt.Font; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.ui.editor.FontStyle; + + +/** + * Manages the editor theme property files. + * + * @author Flemming N. Larsen (original) + * + * @since 1.8.3.0 + */ +public class EditorThemePropertiesManager { + + private static final String EDITOR_THEME_PROPERTIES_FILE_EXT = ".properties"; + + private static final List listeners = new ArrayList(); + + private static EditorThemeProperties editorThemeProperties; + + public static void addListener(IEditorThemePropertyChangeListener listener) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + + public static void removeListener(IEditorThemePropertyChangeListener listener) { + listeners.remove(listener); + } + + public static void notifyThemeNameChanged(String newThemeName) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onThemeNameChanged(newThemeName); + } + } + + public static void notifyFontChanged(Font newFont) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onFontChanged(newFont); + } + } + + public static void notifyFontNameChanged(String newFontName) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onFontNameChanged(newFontName); + } + } + + public static void notifyFontSizeChanged(int newFontSize) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onFontSizeChanged(newFontSize); + } + } + + public static void notifyBackgroundColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onBackgroundColorChanged(newColor); + } + } + + public static void notifyLineNumberBackgroundColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onLineNumberBackgroundColorChanged(newColor); + } + } + + public static void notifyLineNumberTextColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onLineNumberTextColorChanged(newColor); + } + } + + public static void notifyHighlightedLineColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onHighlightedLineColorChanged(newColor); + } + } + + public static void notifySelectionColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onSelectionColorChanged(newColor); + } + } + + public static void notifySelectedTextColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onSelectedTextColorChanged(newColor); + } + } + + public static void notifyNormalTextColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onNormalTextColorChanged(newColor); + } + } + + public static void notifyNormalTextStyleChanged(FontStyle newStyle) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onNormalTextStyleChanged(newStyle); + } + } + + public static void notifyQuotedTextColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onQuotedTextColorChanged(newColor); + } + } + + public static void notifyQuotedTextStyleChanged(FontStyle newStyle) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onQuotedTextStyleChanged(newStyle); + } + } + + public static void notifyKeywordTextColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onKeywordTextColorChanged(newColor); + } + } + + public static void notifyKeywordTextStyleChanged(FontStyle newStyle) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onKeywordTextStyleChanged(newStyle); + } + } + + public static void notifyLiteralTextColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onLiteralTextColorChanged(newColor); + } + } + + public static void notifyLiteralTextStyleChanged(FontStyle newStyle) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onLiteralTextStyleChanged(newStyle); + } + } + + public static void notifyAnnotationTextColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onAnnotationTextColorChanged(newColor); + } + } + + public static void notifyAnnotationTextStyleChanged(FontStyle newStyle) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onAnnotationTextStyleChanged(newStyle); + } + } + + public static void notifyCommentTextColorChanged(Color newColor) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onCommentTextColorChanged(newColor); + } + } + + public static void notifyCommentTextStyleChanged(FontStyle newStyle) { + for (IEditorThemePropertyChangeListener listener : listeners) { + listener.onCommentTextStyleChanged(newStyle); + } + } + + public static EditorThemeProperties getCurrentEditorThemeProperties() { + if (editorThemeProperties == null) { + editorThemeProperties = new EditorThemeProperties(); + + String themeName = EditorPropertiesManager.getEditorProperties().getThemeName(); + File filepath = EditorThemePropertiesManager.getFilepath(themeName); + + loadEditorThemeProperties(filepath); + } + return editorThemeProperties; + } + + public static void loadEditorThemeProperties(File filepath) { + if (filepath != null) { + FileInputStream in = null; + File file = null; + try { + in = new FileInputStream(filepath); + getCurrentEditorThemeProperties().load(in); + } catch (FileNotFoundException e) { + logError("Could not find file: " + file, e); + } catch (IOException e) { + logError("Error while reading file: " + file, e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) {} + } + } + } + } + + public static void saveEditorThemeProperties(File filepath) { + FileOutputStream out = null; + try { + out = new FileOutputStream(filepath); + getCurrentEditorThemeProperties().store(out, "Robocode Editor Theme Properties"); + } catch (IOException e) { + Logger.logError(e); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException ignored) {} + } + } + } + + public static File getFilepath(String themeName) { + if (themeName == null) { + return null; + } + File configDirPath = FileUtil.getEditorThemeConfigDir(); + + String themeFileName = themeName + EDITOR_THEME_PROPERTIES_FILE_EXT; + + return new File(configDirPath, themeFileName); + } + + public static String getFileExt() { + return EDITOR_THEME_PROPERTIES_FILE_EXT; + } +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemePropertyChangeAdapter.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemePropertyChangeAdapter.java new file mode 100644 index 0000000..fa8f21c --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/EditorThemePropertyChangeAdapter.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import java.awt.Color; +import java.awt.Font; + +import net.sf.robocode.ui.editor.FontStyle; + + +public class EditorThemePropertyChangeAdapter implements IEditorThemePropertyChangeListener { + + public void onThemeNameChanged(String newThemeName) {} + + public void onFontChanged(Font newFont) {} + + public void onFontNameChanged(String newFontName) {} + + public void onFontSizeChanged(int newFontSize) {} + + public void onBackgroundColorChanged(Color newColor) {} + + public void onLineNumberBackgroundColorChanged(Color newColor) {} + + public void onLineNumberTextColorChanged(Color newColor) {} + + public void onHighlightedLineColorChanged(Color newColor) {} + + public void onSelectionColorChanged(Color newColor) {} + + public void onSelectedTextColorChanged(Color newColor) {} + + public void onNormalTextColorChanged(Color newColor) {} + + public void onNormalTextStyleChanged(FontStyle newStyle) {} + + public void onQuotedTextColorChanged(Color newColor) {} + + public void onQuotedTextStyleChanged(FontStyle newStyle) {} + + public void onKeywordTextColorChanged(Color newColor) {} + + public void onKeywordTextStyleChanged(FontStyle newStyle) {} + + public void onLiteralTextColorChanged(Color newColor) {} + + public void onLiteralTextStyleChanged(FontStyle newStyle) {} + + public void onAnnotationTextColorChanged(Color newColor) {} + + public void onAnnotationTextStyleChanged(FontStyle newStyle) {} + + public void onCommentTextColorChanged(Color newColor) {} + + public void onCommentTextStyleChanged(FontStyle newStyle) {} +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IColorAndStyleListener.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IColorAndStyleListener.java new file mode 100644 index 0000000..21b7721 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IColorAndStyleListener.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import java.awt.Color; + +import net.sf.robocode.ui.editor.FontStyle; + + +/** + * Listener interface for the {@link ColorAndStyle} class. + * + * @author Flemming N. Larsen (original) + * @since 1.8.3.0 + */ +public interface IColorAndStyleListener { + void colorChanged(Color newColor); + void styleChanged(FontStyle newStyle); +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IEditorThemeProperties.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IEditorThemeProperties.java new file mode 100644 index 0000000..785ff89 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IEditorThemeProperties.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import java.awt.Color; +import java.awt.Font; + +import net.sf.robocode.ui.editor.FontStyle; + + +/** + * Interface for editor theme properties. + * + * @author Flemming N. Larsen (original) + * + * @since 1.8.3.0 + */ +public interface IEditorThemeProperties { + + String getThemeName(); + + Font getFont(); + String getFontName(); + int getFontSize(); + + Color getBackgroundColor(); + + Color getLineNumberBackgroundColor(); + Color getLineNumberTextColor(); + + Color getHighlightedLineColor(); + + Color getSelectionColor(); + Color getSelectedTextColor(); + + Color getNormalTextColor(); + FontStyle getNormalTextStyle(); + + Color getQuotedTextColor(); + FontStyle getQuotedTextStyle(); + + Color getKeywordTextColor(); + FontStyle getKeywordTextStyle(); + + Color getLiteralTextColor(); + FontStyle getLiteralTextStyle(); + + Color getAnnotationTextColor(); + FontStyle getAnnotationTextStyle(); + + Color getCommentTextColor(); + FontStyle getCommentTextStyle(); +} diff --git a/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IEditorThemePropertyChangeListener.java b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IEditorThemePropertyChangeListener.java new file mode 100644 index 0000000..fd650c3 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui.editor/src/main/java/net/sf/robocode/ui/editor/theme/IEditorThemePropertyChangeListener.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor.theme; + + +import java.awt.Color; +import java.awt.Font; + +import net.sf.robocode.ui.editor.FontStyle; + + +public interface IEditorThemePropertyChangeListener { + + void onThemeNameChanged(String newThemeName); + + void onFontChanged(Font newFont); + void onFontNameChanged(String newFontName); + void onFontSizeChanged(int newFontSize); + + void onBackgroundColorChanged(Color newColor); + + void onLineNumberBackgroundColorChanged(Color newColor); + void onLineNumberTextColorChanged(Color newColor); + + void onHighlightedLineColorChanged(Color newColor); + + void onSelectionColorChanged(Color newColor); + void onSelectedTextColorChanged(Color newColor); + + void onNormalTextColorChanged(Color newColor); + void onNormalTextStyleChanged(FontStyle newStyle); + + void onQuotedTextColorChanged(Color newColor); + void onQuotedTextStyleChanged(FontStyle newStyle); + + void onKeywordTextColorChanged(Color newColor); + void onKeywordTextStyleChanged(FontStyle newStyle); + + void onLiteralTextColorChanged(Color newColor); + void onLiteralTextStyleChanged(FontStyle newStyle); + + void onAnnotationTextColorChanged(Color newColor); + void onAnnotationTextStyleChanged(FontStyle newStyle); + + void onCommentTextColorChanged(Color newColor); + void onCommentTextStyleChanged(FontStyle newStyle); +} diff --git a/代码/workspace_robo4/robocode.ui/.classpath b/代码/workspace_robo4/robocode.ui/.classpath new file mode 100644 index 0000000..aab3303 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.ui/.project b/代码/workspace_robo4/robocode.ui/.project new file mode 100644 index 0000000..c5e1c83 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/.project @@ -0,0 +1,21 @@ + + + robocode.ui + NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + robocode.api + robocode.core + robocode.battle + robocode.host + robocode.repository + robocode.sound + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.ui/.settings/org.eclipse.jdt.core.prefs b/代码/workspace_robo4/robocode.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..b12a989 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Tue Nov 27 22:12:09 CET 2012 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=8859_1 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=8859_1 +encoding/src/main/resources=8859_1 +encoding/src/test/java=8859_1 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/代码/workspace_robo4/robocode.ui/pom.xml b/代码/workspace_robo4/robocode.ui/pom.xml new file mode 100644 index 0000000..3355ac3 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + robocode.ui + Robocode UI + + robocode + net.sf.robocode + ${robocode.version} + + + + net.sf.robocode + robocode.api + ${project.version} + + + net.sf.robocode + robocode.core + ${project.version} + + + net.sf.robocode + robocode.battle + ${project.version} + + + net.sf.robocode + robocode.sound + ${project.version} + runtime + + + diff --git a/代码/workspace_robo4/robocode.ui/robocode.ui.iml b/代码/workspace_robo4/robocode.ui/robocode.ui.iml new file mode 100644 index 0000000..1e3dce7 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/robocode.ui.iml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/BrowserManager.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/BrowserManager.java new file mode 100644 index 0000000..c5671dc --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/BrowserManager.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; + +import java.awt.Desktop; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (original) + */ +public class BrowserManager { + + public static void openURL(String url) throws IOException { + + // Plan A: try to open the URL using the Java 6 Desktop class + if (Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + if (desktop.isSupported(Desktop.Action.BROWSE)) { + try { + desktop.browse(new URI(url)); + return; // success + } catch (URISyntaxException e) { + Logger.logError(e); + } + } + // Fall thru to plan B + } + + // Plan B: try to open URL by calling a command-line tool for the specific OS + url = FileUtil.quoteFileName(url); + + Runtime rt = Runtime.getRuntime(); + String os = System.getProperty("os.name").toLowerCase(); + + if (os.startsWith("windows")) { + rt.exec("rundll32 url.dll, FileProtocolHandler " + url); + + } else if (os.startsWith("mac")) { + rt.exec("open " + url); + + } else if (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0) { + // Do a best guess on Unix until we get a platform independent way. + // Build a list of browsers to try, in this order. + final String[] browsers = { + "epiphany", "firefox", "mozilla", "konqueror", "galeon", "netscape", "opera", "links", "lynx" }; + + // Build a command string which looks like + // "browser1 "url" || browser2 "url" || ..." + StringBuffer cmd = new StringBuffer(); + + for (int i = 0; i < browsers.length; i++) { + cmd.append((i == 0 ? "" : " || ") + browsers[i] + " \"" + url + "\" "); + } + + rt.exec(new String[] { "sh", "-c", cmd.toString() }); + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/CheckList.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/CheckList.java new file mode 100644 index 0000000..114079b --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/CheckList.java @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import java.awt.Component; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; + +import javax.swing.DefaultListModel; +import javax.swing.JCheckBox; +import javax.swing.JList; +import javax.swing.ListCellRenderer; + +import net.sf.robocode.util.AlphanumericComparator; + + +/** + * A JList containing JCheckBox items. + * + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class CheckList extends JList { + + private DefaultListModel model; + + public CheckList() { + super(); + + initialize(); + } + + private void initialize() { + model = new DefaultListModel(); + setModel(model); + + // Use a CheckListRenderer (see below) to renderer list cells + setCellRenderer(new CheckListRenderer()); + + // Add a mouse listener to handle changing selection + addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent event) { + JList list = (JList) event.getSource(); + + // Get index of item clicked + int index = list.locationToIndex(event.getPoint()); + + if (index >= 0) { + if (event.getClickCount() == 2) { + CheckListItem item = (CheckListItem) model.getElementAt(index); + + // Toggle selected state + item.setSelected(!item.isSelected()); + + // Repaint cell + list.repaint(list.getCellBounds(index, index)); + } + } + } + }); + } + + public void clear() { + model.clear(); + } + + public int getLength() { + return model.getSize(); + } + + public String get(int index) { + return ((CheckListItem) model.getElementAt(index)).toString(); + } + + public void add(String label) { + model.addElement(new CheckListItem(label)); + } + + public void remove(int index) { + model.remove(index); + } + + public boolean contains(String label) { + if (label == null) { + return false; + } + for (int i = 0; i < model.getSize(); i++) { + CheckListItem item = (CheckListItem) model.getElementAt(i); + + if (label.equals(item.toString())) { + return true; + } + } + return false; + } + + public void sort() { + int size = model.getSize(); + + if (size > 0) { + CheckListItem[] items = new CheckListItem[size]; + + model.copyInto(items); + Arrays.sort(items); + + for (int i = 0; i < items.length; i++) { + model.setElementAt(items[i], i); + } + } + } + + public void setChecked(String label, boolean isChecked) { + if (label != null) { + for (int i = 0; i < model.getSize(); i++) { + CheckListItem item = (CheckListItem) model.getElementAt(i); + + if (label.equals(item.toString())) { + item.setSelected(isChecked); + break; + } + } + } + } + + public Collection getUnchecked() { + Collection unchecked = new HashSet(); + + for (int i = 0; i < model.getSize(); i++) { + CheckListItem item = (CheckListItem) model.getElementAt(i); + + if (!item.isSelected()) { + unchecked.add(item.toString()); + } + } + return unchecked; + } + + public Collection getAll() { + Collection all = new HashSet(); + + for (int i = 0; i < model.getSize(); i++) { + CheckListItem item = (CheckListItem) model.getElementAt(i); + + all.add(item.toString()); + } + return all; + } +} + + +/** + * Represents items in the list that can be selected. + */ +class CheckListItem implements Cloneable, Comparable { + private String label; + private boolean isSelected = true; + + public CheckListItem(String label) { + this.label = label; + } + + private CheckListItem(CheckListItem item) { + label = item.label; + isSelected = item.isSelected; + } + + public boolean isSelected() { + return isSelected; + } + + public void setSelected(boolean isSelected) { + this.isSelected = isSelected; + } + + // Must be here + public String toString() { + return label; + } + + // Must be here (for sorting) + public Object clone() { + return new CheckListItem(this); + } + + // Must be here (for sorting) + public int compareTo(CheckListItem item) { + return new AlphanumericComparator().compare(label, item.label); + } +} + + +/** + * CheckListRenderer handles rendering cells in the list using a check box. + */ +@SuppressWarnings("serial") +class CheckListRenderer extends JCheckBox implements ListCellRenderer { + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) { + setEnabled(list.isEnabled()); + setSelected(((CheckListItem) value).isSelected()); + setFont(list.getFont()); + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + setText(value.toString()); + return this; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IImageManager.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IImageManager.java new file mode 100644 index 0000000..9272c68 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IImageManager.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import net.sf.robocode.ui.gfx.RenderImage; + +import java.awt.*; + + +/** + * @author Pavel Savara (original) + */ +public interface IImageManager { + void initialize(); + + Image getGroundTileImage(int index); + + RenderImage getExplosionRenderImage(int which, int frame); + + RenderImage getExplosionDebriseRenderImage(); + + RenderImage getColoredBodyRenderImage(Integer color); + + RenderImage getColoredGunRenderImage(Integer color); + + RenderImage getColoredRadarRenderImage(Integer color); +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IRobotDialogManager.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IRobotDialogManager.java new file mode 100644 index 0000000..d028cce --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IRobotDialogManager.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import net.sf.robocode.ui.dialog.BattleButton; +import net.sf.robocode.ui.dialog.BattleDialog; +import net.sf.robocode.ui.dialog.RobotButton; +import net.sf.robocode.ui.dialog.RobotDialog; +import robocode.control.snapshot.IRobotSnapshot; + +import java.util.List; + + +/** + * @author Pavel Savara (original) + */ +public interface IRobotDialogManager { + void trim(List robots); + + void reset(); + + RobotDialog getRobotDialog(RobotButton robotButton, String name, boolean create); + BattleDialog getBattleDialog(BattleButton battleButton, boolean create); +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IWindowManagerExt.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IWindowManagerExt.java new file mode 100644 index 0000000..f42eb4a --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/IWindowManagerExt.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import net.sf.robocode.battle.BattleProperties; +import net.sf.robocode.battle.BattleResultsTableModel; +import robocode.control.events.BattleCompletedEvent; + +import javax.swing.*; + + +/** + * @author Pavel Savara (original) + */ +public interface IWindowManagerExt extends IWindowManager { + void showAboutBox(); + + String showBattleOpenDialog(String defExt, String name); + + String saveBattleDialog(String path, String defExt, String name); + + void showReadMe(); + + void showVersionsTxt(); + + void showHelpApi(); + + void showFaq(); + + void showOnlineHelp(); + + void showJavaDocumentation(); + + void showRobocodeHome(); + + void showRoboWiki(); + + void showGoogleGroupRobocode(); + + void showRobocodeRepository(); + + void showOptionsPreferences(); + + void showResultsDialog(BattleCompletedEvent event); + + void showRankingDialog(boolean visible); + + void showRobocodeEditor(); + + void showRobotPackager(); + + void showRobotExtractor(JFrame owner); + + void showNewBattleDialog(BattleProperties battleProperties); + + boolean closeRobocodeEditor(); + + void showCreateTeamDialog(); + + void showImportRobotDialog(); + + void showSaveResultsDialog(BattleResultsTableModel tableModel); + + int getFPS(); +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/ImageManager.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/ImageManager.java new file mode 100644 index 0000000..2482c80 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/ImageManager.java @@ -0,0 +1,236 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.gfx.ImageUtil; +import net.sf.robocode.ui.gfx.RenderImage; + +import java.awt.*; +import java.util.*; +import java.util.List; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Titus Chen (contributor) + */ +public class ImageManager implements IImageManager { + + private final ISettingsManager properties; + + private Image[] groundImages; + + private RenderImage[][] explosionRenderImages; + private RenderImage debriseRenderImage; + + private Image bodyImage; + private Image gunImage; + private Image radarImage; + + private static final int MAX_NUM_COLORS = 256; + + private HashMap robotBodyImageCache; + private HashMap robotGunImageCache; + private HashMap robotRadarImageCache; + + public ImageManager(ISettingsManager properties) { + this.properties = properties; + } + + public void initialize() { + // Note that initialize could be called in order to reset all images (image buffering) + + // Reset image cache + groundImages = new Image[5]; + explosionRenderImages = null; + debriseRenderImage = null; + bodyImage = null; + gunImage = null; + radarImage = null; + robotBodyImageCache = new RenderCache(); + robotGunImageCache = new RenderCache(); + robotRadarImageCache = new RenderCache(); + + // Read images into the cache + getBodyImage(); + getGunImage(); + getRadarImage(); + getExplosionRenderImage(0, 0); + } + + public Image getGroundTileImage(int index) { + if (groundImages[index] == null) { + groundImages[index] = getImage("/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_" + index + ".png"); + } + return groundImages[index]; + } + + public RenderImage getExplosionRenderImage(int which, int frame) { + if (explosionRenderImages == null) { + int numExplosion, numFrame; + String filename; + + List> explosions = new ArrayList>(); + + boolean done = false; + + for (numExplosion = 1; !done; numExplosion++) { + List frames = new ArrayList(); + + for (numFrame = 1;; numFrame++) { + filename = "/net/sf/robocode/ui/images/explosion/explosion" + numExplosion + '-' + numFrame + ".png"; + + if (ImageManager.class.getResource(filename) == null) { + if (numFrame == 1) { + done = true; + } else { + explosions.add(frames); + } + break; + } + + frames.add(new RenderImage(getImage(filename))); + } + } + + numExplosion = explosions.size(); + explosionRenderImages = new RenderImage[numExplosion][]; + + for (int i = numExplosion - 1; i >= 0; i--) { + explosionRenderImages[i] = explosions.get(i).toArray(new RenderImage[explosions.size()]); + } + } + return explosionRenderImages[which][frame]; + } + + public RenderImage getExplosionDebriseRenderImage() { + if (debriseRenderImage == null) { + debriseRenderImage = new RenderImage(getImage("/net/sf/robocode/ui/images/ground/explode_debris.png")); + } + return debriseRenderImage; + } + + private Image getImage(String filename) { + Image image = ImageUtil.getImage(filename); + + if (properties.getOptionsRenderingBufferImages()) { + image = ImageUtil.getBufferedImage(image); + } + return image; + } + + /** + * Gets the body image + * Loads from disk if necessary. + * + * @return the body image + */ + private Image getBodyImage() { + if (bodyImage == null) { + bodyImage = getImage("/net/sf/robocode/ui/images/body.png"); + } + return bodyImage; + } + + /** + * Gets the gun image + * Loads from disk if necessary. + * + * @return the gun image + */ + private Image getGunImage() { + if (gunImage == null) { + gunImage = getImage("/net/sf/robocode/ui/images/turret.png"); + } + return gunImage; + } + + /** + * Gets the radar image + * Loads from disk if necessary. + * + * @return the radar image + */ + private Image getRadarImage() { + if (radarImage == null) { + radarImage = getImage("/net/sf/robocode/ui/images/radar.png"); + } + return radarImage; + } + + public RenderImage getColoredBodyRenderImage(Integer color) { + RenderImage img = robotBodyImageCache.get(color); + + if (img == null) { + img = new RenderImage(ImageUtil.createColouredRobotImage(getBodyImage(), new Color(color, true))); + robotBodyImageCache.put(color, img); + } + return img; + } + + public RenderImage getColoredGunRenderImage(Integer color) { + RenderImage img = robotGunImageCache.get(color); + + if (img == null) { + img = new RenderImage(ImageUtil.createColouredRobotImage(getGunImage(), new Color(color, true))); + robotGunImageCache.put(color, img); + } + return img; + } + + public RenderImage getColoredRadarRenderImage(Integer color) { + RenderImage img = robotRadarImageCache.get(color); + + if (img == null) { + img = new RenderImage(ImageUtil.createColouredRobotImage(getRadarImage(), new Color(color, true))); + robotRadarImageCache.put(color, img); + } + return img; + } + + /** + * Class used for caching rendered robot parts in various colors. + * + * @author Titus Chen + */ + @SuppressWarnings("serial") + private static class RenderCache extends LinkedHashMap { + + /* Note about initial capacity: + * To avoid rehashing (inefficient though probably unavoidable), initial + * capacity must be at least 1 greater than the maximum capacity. + * However, initial capacities are set to the smallest power of 2 greater + * than or equal to the passed argument, resulting in 512 with this code. + * I was not aware of this before, but notice: the current implementation + * behaves similarly. The simple solution would be to set maximum capacity + * to 255, but the problem with doing so is that in a battle of 256 robots + * of different colors, the net result would end up being real-time + * rendering due to the nature of access ordering. However, 256 robot + * battles are rarely fought. + */ + private static final int INITIAL_CAPACITY = MAX_NUM_COLORS + 1; + + private static final float LOAD_FACTOR = 1; + + public RenderCache() { + + /* The "true" parameter needed for access-order: + * when cache fills, the least recently accessed entry is removed + */ + super(INITIAL_CAPACITY, LOAD_FACTOR, true); + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > MAX_NUM_COLORS; + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/Module.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/Module.java new file mode 100644 index 0000000..3d20542 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/Module.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import net.sf.robocode.core.BaseModule; +import net.sf.robocode.core.Container; +import net.sf.robocode.ui.battleview.BattleView; +import net.sf.robocode.ui.battleview.InteractiveHandler; +import net.sf.robocode.ui.dialog.*; +import net.sf.robocode.ui.packager.RobotPackager; + + +/** + * @author Pavel Savara (original) + */ +public class Module extends BaseModule { + static { + Container.cache.addComponent(AboutBox.class); + Container.cache.addComponent(BattleButton.class); + Container.cache.addComponent(BattleView.class); + Container.cache.addComponent(BattleDialog.class); + Container.cache.addComponent(IImageManager.class, ImageManager.class); + Container.cache.addComponent(IRobotDialogManager.class, RobotDialogManager.class); + Container.cache.addComponent(IWindowManagerExt.class, WindowManager.class); + Container.cache.addComponent(InteractiveHandler.class); + Container.cache.addComponent(PreferencesDialog.class); + Container.cache.addComponent(RankingDialog.class); + Container.cache.addComponent(RcSplashScreen.class); + Container.cache.addComponent(ResultsDialog.class); + Container.cache.addComponent(MenuBar.class); + Container.cache.addComponent(TeamCreator.class); + Container.cache.addComponent(RobocodeFrame.class); + + // new instance for every lookup + Container.factory.addComponent(RobotSelectionPanel.class); + Container.factory.addComponent(RobotDialog.class); + Container.factory.addComponent(RobotButton.class); + Container.factory.addComponent(RobotPackager.class); + Container.factory.addComponent(NewBattleDialog.class); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/RobotDialogManager.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/RobotDialogManager.java new file mode 100644 index 0000000..ad8ea5c --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/RobotDialogManager.java @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.ui.dialog.*; +import robocode.control.snapshot.IRobotSnapshot; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + + +/** + * @author Mathew A. Nelson (orinal) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +public class RobotDialogManager implements IRobotDialogManager { + + public static final int MAX_PRE_ATTACHED = 25; + + private final Map robotDialogMap = new ConcurrentHashMap(); + private BattleDialog battleDialog = null; + + public RobotDialogManager() { + super(); + } + + public void trim(List robots) { + + // new ArrayList in order to prevent ConcurrentModificationException + for (String name : new ArrayList(robotDialogMap.keySet())) { + boolean found = false; + + for (IRobotSnapshot robot : robots) { + if (robot.getName().equals(name)) { + found = true; + break; + } + } + if (!found) { + RobotDialog dialog = robotDialogMap.get(name); + + robotDialogMap.remove(name); + dialog.dispose(); + dialog.detach(); + } + } + } + + public void reset() { + for (String name : robotDialogMap.keySet()) { + RobotDialog dialog = robotDialogMap.get(name); + + if (!dialog.isVisible()) { + robotDialogMap.remove(name); + dialog.detach(); + dialog.dispose(); + } + } + } + + public RobotDialog getRobotDialog(RobotButton robotButton, String name, boolean create) { + RobotDialog robotDialog = robotDialogMap.get(name); + + if (create && robotDialog == null) { + if (robotDialogMap.size() > MAX_PRE_ATTACHED) { + reset(); + } + robotDialog = Container.createComponent(RobotDialog.class); + robotDialog.setup(robotButton); + robotDialog.pack(); + WindowUtil.place(robotDialog); + robotDialogMap.put(name, robotDialog); + } + return robotDialog; + } + + public BattleDialog getBattleDialog(BattleButton battleButton, boolean create) { + + if (create && battleDialog == null) { + battleDialog = Container.getComponent(BattleDialog.class); + battleDialog.pack(); + WindowUtil.place(battleDialog); + } + return battleDialog; + } + +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/BattleField.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/BattleField.java new file mode 100644 index 0000000..e9781f1 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/BattleField.java @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.battleview; + + +import net.sf.robocode.battle.BoundingRectangle; + +import java.io.Serializable; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (original) + */ +public class BattleField implements Serializable { + private static final long serialVersionUID = 1L; + + private final BoundingRectangle boundingBox; + + public BattleField(int width, int height) { + super(); + this.boundingBox = new BoundingRectangle(0, 0, width, height); + } + + public BoundingRectangle getBoundingBox() { + return boundingBox; + } + + public int getWidth() { + return (int) boundingBox.width; + } + + public void setWidth(int newWidth) { + boundingBox.width = newWidth; + } + + public int getHeight() { + return (int) boundingBox.height; + } + + public void setHeight(int newHeight) { + boundingBox.height = newHeight; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/BattleView.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/BattleView.java new file mode 100644 index 0000000..aebdf06 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/BattleView.java @@ -0,0 +1,698 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.battleview; + + +import net.sf.robocode.battle.snapshot.RobotSnapshot; +import net.sf.robocode.robotpaint.Graphics2DSerialized; +import net.sf.robocode.robotpaint.IGraphicsProxy; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.settings.ISettingsListener; +import net.sf.robocode.ui.IImageManager; +import net.sf.robocode.ui.IWindowManager; +import net.sf.robocode.ui.IWindowManagerExt; +import net.sf.robocode.ui.gfx.GraphicsState; +import net.sf.robocode.ui.gfx.RenderImage; +import net.sf.robocode.ui.gfx.RobocodeLogo; +import robocode.BattleRules; +import robocode.control.events.BattleAdaptor; +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.BattleStartedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IBulletSnapshot; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.geom.*; +import java.awt.image.BufferStrategy; +import java.awt.image.BufferedImage; +import static java.lang.Math.*; +import java.util.Random; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (original) + * @author Pavel Savara (contributor) + */ +@SuppressWarnings("serial") +public class BattleView extends Canvas { + + private final static String ROBOCODE_SLOGAN = "Build the best, destroy the rest!"; + + private final static Color CANVAS_BG_COLOR = SystemColor.controlDkShadow; + + private final static Area BULLET_AREA = new Area(new Ellipse2D.Double(-0.5, -0.5, 1, 1)); + + private final static int ROBOT_TEXT_Y_OFFSET = 24; + + private BattleRules battleRules; + + // The battle and battlefield, + private BattleField battleField; + + private boolean initialized; + private double scale = 1.0; + + // Ground + private int[][] groundTiles; + + private final int groundTileWidth = 64; + private final int groundTileHeight = 64; + + private Image groundImage; + + // Draw option related things + private boolean drawRobotName; + private boolean drawRobotEnergy; + private boolean drawScanArcs; + private boolean drawExplosions; + private boolean drawGround; + private boolean drawExplosionDebris; + + private int numBuffers = 2; // defaults to double buffering + + private RenderingHints renderingHints; + + // Fonts and the like + private Font smallFont; + private FontMetrics smallFontMetrics; + + private final IImageManager imageManager; + private final ISettingsManager properties; + private final IWindowManagerExt windowManager; + + private BufferStrategy bufferStrategy; + + private final GeneralPath robocodeTextPath = new RobocodeLogo().getRobocodeText(); + + private static final MirroredGraphics mirroredGraphics = new MirroredGraphics(); + + private final GraphicsState graphicsState = new GraphicsState(); + private IGraphicsProxy[] robotGraphics; + + public BattleView(ISettingsManager properties, IWindowManager windowManager, IImageManager imageManager) { + this.properties = properties; + this.windowManager = (IWindowManagerExt) windowManager; + this.imageManager = imageManager; + + battleField = new BattleField(800, 600); + + new BattleObserver(windowManager); + + properties.addPropertyListener(new ISettingsListener() { + public void settingChanged(String property) { + loadDisplayOptions(); + if (property.startsWith("robocode.options.rendering")) { + initialized = false; + reinitialize(); + } + } + }); + + addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent e) { + initialized = false; + reinitialize(); + } + }); + } + + @Override + public void update(Graphics g) { + paint(g); + } + + @Override + public void paint(Graphics g) { + final ITurnSnapshot lastSnapshot = windowManager.getLastSnapshot(); + if (lastSnapshot != null) { + update(lastSnapshot); + } else { + paintRobocodeLogo((Graphics2D) g); + } + } + + public BufferedImage getScreenshot() { + BufferedImage screenshot = getGraphicsConfiguration().createCompatibleImage(getWidth(), getHeight()); + + if (windowManager.getLastSnapshot() == null) { + paintRobocodeLogo((Graphics2D) screenshot.getGraphics()); + } else { + drawBattle((Graphics2D) screenshot.getGraphics(), windowManager.getLastSnapshot()); + } + return screenshot; + } + + private void update(ITurnSnapshot snapshot) { + if (!initialized) { + initialize(); + } + + if (windowManager.isIconified() || !isDisplayable() || (getWidth() <= 0) || (getHeight() <= 0)) { + return; + } + + if (bufferStrategy != null) { + try { + Graphics2D g2 = (Graphics2D) bufferStrategy.getDrawGraphics(); + + if (g2 != null) { + do { + try { + g2.setRenderingHints(renderingHints); + + drawBattle(g2, snapshot); + } finally { + g2.dispose(); + } + bufferStrategy.show(); + } while (bufferStrategy.contentsLost()); + + Toolkit.getDefaultToolkit().sync(); // Update like... now! + } + } catch (NullPointerException e) {} + } + } + + private void loadDisplayOptions() { + ISettingsManager props = properties; + + drawRobotName = props.getOptionsViewRobotNames(); + drawRobotEnergy = props.getOptionsViewRobotEnergy(); + drawScanArcs = props.getOptionsViewScanArcs(); + drawGround = props.getOptionsViewGround(); + drawExplosions = props.getOptionsViewExplosions(); + drawExplosionDebris = props.getOptionsViewExplosionDebris(); + + renderingHints = props.getRenderingHints(); + numBuffers = props.getOptionsRenderingNoBuffers(); + } + + private void reinitialize() { + initialized = false; + bufferStrategy = null; + } + + private void initialize() { + loadDisplayOptions(); + + if (bufferStrategy == null) { + createBufferStrategy(numBuffers); + bufferStrategy = getBufferStrategy(); + } + + // If we are scaled... + if (getWidth() < battleField.getWidth() || getHeight() < battleField.getHeight()) { + // Use the smaller scale. + // Actually we don't need this, since + // the RobocodeFrame keeps our aspect ratio intact. + + scale = min((double) getWidth() / battleField.getWidth(), (double) getHeight() / battleField.getHeight()); + } else { + scale = 1; + } + + // Scale font + smallFont = new Font("Dialog", Font.PLAIN, (int) (10 / scale)); + smallFontMetrics = bufferStrategy.getDrawGraphics().getFontMetrics(); + + // Initialize ground image + if (drawGround) { + createGroundImage(); + } else { + groundImage = null; + } + + initialized = true; + } + + private void createGroundImage() { + // Reinitialize ground tiles + + Random r = new Random(); // independent + + final int NUM_HORZ_TILES = battleField.getWidth() / groundTileWidth + 1; + final int NUM_VERT_TILES = battleField.getHeight() / groundTileHeight + 1; + + if ((groundTiles == null) || (groundTiles.length != NUM_VERT_TILES) || (groundTiles[0].length != NUM_HORZ_TILES)) { + + groundTiles = new int[NUM_VERT_TILES][NUM_HORZ_TILES]; + for (int y = NUM_VERT_TILES - 1; y >= 0; y--) { + for (int x = NUM_HORZ_TILES - 1; x >= 0; x--) { + groundTiles[y][x] = (int) round(r.nextDouble() * 4); + } + } + } + + // Create new buffered image with the ground pre-rendered + + int groundWidth = (int) (battleField.getWidth() * scale); + int groundHeight = (int) (battleField.getHeight() * scale); + + groundImage = new BufferedImage(groundWidth, groundHeight, BufferedImage.TYPE_INT_RGB); + + Graphics2D groundGfx = (Graphics2D) groundImage.getGraphics(); + + groundGfx.setRenderingHints(renderingHints); + + groundGfx.setTransform(AffineTransform.getScaleInstance(scale, scale)); + + for (int y = NUM_VERT_TILES - 1; y >= 0; y--) { + for (int x = NUM_HORZ_TILES - 1; x >= 0; x--) { + Image img = imageManager.getGroundTileImage(groundTiles[y][x]); + + if (img != null) { + groundGfx.drawImage(img, x * groundTileWidth, y * groundTileHeight, null); + } + } + } + } + + private void drawBattle(Graphics2D g, ITurnSnapshot snapShot) { + // Save the graphics state + graphicsState.save(g); + + // Reset transform + g.setTransform(new AffineTransform()); + + // Reset clip + g.setClip(null); + + // Clear canvas + g.setColor(CANVAS_BG_COLOR); + g.fillRect(0, 0, getWidth(), getHeight()); + + // Calculate border space + double dx = (getWidth() - scale * battleField.getWidth()) / 2; + double dy = (getHeight() - scale * battleField.getHeight()) / 2; + + // Scale and translate the graphics + AffineTransform at = AffineTransform.getTranslateInstance(dx, dy); + + at.concatenate(AffineTransform.getScaleInstance(scale, scale)); + g.setTransform(at); + + // Set the clip rectangle + g.setClip(0, 0, battleField.getWidth(), battleField.getHeight()); + + // Draw ground + drawGround(g); + + if (snapShot != null) { + // Draw scan arcs + drawScanArcs(g, snapShot); + + // Draw robots + drawRobots(g, snapShot); + + // Draw robot (debug) paintings + drawRobotPaint(g, snapShot); + } + + // Draw the border of the battlefield + drawBorderEdge(g); + + if (snapShot != null) { + // Draw all bullets + drawBullets(g, snapShot); + + // Draw all text + drawText(g, snapShot); + } + + // Restore the graphics state + graphicsState.restore(g); + } + + private void drawGround(Graphics2D g) { + if (drawGround) { + // Create pre-rendered ground image if it is not available + if (groundImage == null) { + createGroundImage(); + } + // Draw the pre-rendered ground if it is available + if (groundImage != null) { + int groundWidth = (int) (battleField.getWidth() * scale) + 1; + int groundHeight = (int) (battleField.getHeight() * scale) + 1; + + int dx = (getWidth() - groundWidth) / 2; + int dy = (getHeight() - groundHeight) / 2; + + final AffineTransform savedTx = g.getTransform(); + + g.setTransform(new AffineTransform()); + g.drawImage(groundImage, dx, dy, groundWidth, groundHeight, null); + + g.setTransform(savedTx); + } + } else { + // Ground should not be drawn + g.setColor(Color.BLACK); + g.fillRect(0, 0, battleField.getWidth(), battleField.getHeight()); + } + + // Draw Sentry Border if it is enabled visually + if (properties.getOptionsViewSentryBorder()) { + drawSentryBorder(g); + } + } + + private void drawSentryBorder(Graphics2D g) { + int borderSentrySize = battleRules.getSentryBorderSize(); + + g.setColor(new Color(0xff, 0x00, 0x00, 0x80)); + g.fillRect(0, 0, borderSentrySize, battleField.getHeight()); + g.fillRect(battleField.getWidth() - borderSentrySize, 0, borderSentrySize, battleField.getHeight()); + g.fillRect(borderSentrySize, 0, battleField.getWidth() - 2 * borderSentrySize, borderSentrySize); + g.fillRect(borderSentrySize, battleField.getHeight() - borderSentrySize, + battleField.getWidth() - 2 * borderSentrySize, borderSentrySize); + } + + private void drawBorderEdge(Graphics2D g) { + final Shape savedClip = g.getClip(); + + g.setClip(null); + + g.setColor(Color.RED); + g.drawRect(-1, -1, battleField.getWidth() + 2, battleField.getHeight() + 2); + + g.setClip(savedClip); + } + + private void drawScanArcs(Graphics2D g, ITurnSnapshot snapShot) { + if (drawScanArcs) { + for (IRobotSnapshot robotSnapshot : snapShot.getRobots()) { + if (robotSnapshot.getState().isAlive()) { + drawScanArc(g, robotSnapshot); + } + } + } + } + + private void drawRobots(Graphics2D g, ITurnSnapshot snapShot) { + double x, y; + AffineTransform at; + int battleFieldHeight = battleField.getHeight(); + + if (drawGround && drawExplosionDebris) { + RenderImage explodeDebrise = imageManager.getExplosionDebriseRenderImage(); + + for (IRobotSnapshot robotSnapshot : snapShot.getRobots()) { + if (robotSnapshot.getState().isDead()) { + x = robotSnapshot.getX(); + y = battleFieldHeight - robotSnapshot.getY(); + + at = AffineTransform.getTranslateInstance(x, y); + + explodeDebrise.setTransform(at); + explodeDebrise.paint(g); + } + } + } + + for (IRobotSnapshot robotSnapshot : snapShot.getRobots()) { + if (robotSnapshot.getState().isAlive()) { + x = robotSnapshot.getX(); + y = battleFieldHeight - robotSnapshot.getY(); + + at = AffineTransform.getTranslateInstance(x, y); + at.rotate(robotSnapshot.getBodyHeading()); + + RenderImage robotRenderImage = imageManager.getColoredBodyRenderImage(robotSnapshot.getBodyColor()); + + robotRenderImage.setTransform(at); + robotRenderImage.paint(g); + + at = AffineTransform.getTranslateInstance(x, y); + at.rotate(robotSnapshot.getGunHeading()); + + RenderImage gunRenderImage = imageManager.getColoredGunRenderImage(robotSnapshot.getGunColor()); + + gunRenderImage.setTransform(at); + gunRenderImage.paint(g); + + if (!robotSnapshot.isDroid()) { + at = AffineTransform.getTranslateInstance(x, y); + at.rotate(robotSnapshot.getRadarHeading()); + + RenderImage radarRenderImage = imageManager.getColoredRadarRenderImage(robotSnapshot.getRadarColor()); + + radarRenderImage.setTransform(at); + radarRenderImage.paint(g); + } + } + } + } + + private void drawText(Graphics2D g, ITurnSnapshot snapShot) { + final Shape savedClip = g.getClip(); + + g.setClip(null); + + for (IRobotSnapshot robotSnapshot : snapShot.getRobots()) { + if (robotSnapshot.getState().isDead()) { + continue; + } + int x = (int) robotSnapshot.getX(); + int y = battleField.getHeight() - (int) robotSnapshot.getY(); + + if (drawRobotEnergy) { + g.setColor(Color.white); + int ll = (int) robotSnapshot.getEnergy(); + int rl = (int) ((robotSnapshot.getEnergy() - ll + .001) * 10.0); + + if (rl == 10) { + rl = 9; + } + String energyString = ll + "." + rl; + + if (robotSnapshot.getEnergy() == 0 && robotSnapshot.getState().isAlive()) { + energyString = "Disabled"; + } + centerString(g, energyString, x, y - ROBOT_TEXT_Y_OFFSET - smallFontMetrics.getHeight() / 2, smallFont, + smallFontMetrics); + } + if (drawRobotName) { + g.setColor(Color.white); + centerString(g, robotSnapshot.getVeryShortName(), x, + y + ROBOT_TEXT_Y_OFFSET + smallFontMetrics.getHeight() / 2, smallFont, smallFontMetrics); + } + } + + g.setClip(savedClip); + } + + private void drawRobotPaint(Graphics2D g, ITurnSnapshot turnSnapshot) { + + int robotIndex = 0; + + for (IRobotSnapshot robotSnapshot : turnSnapshot.getRobots()) { + final Object graphicsCalls = ((RobotSnapshot) robotSnapshot).getGraphicsCalls(); + + if (graphicsCalls == null || !robotSnapshot.isPaintEnabled()) { + continue; + } + + // Save the graphics state + GraphicsState gfxState = new GraphicsState(); + + gfxState.save(g); + + g.setClip(null); + g.setComposite(AlphaComposite.SrcAtop); + + IGraphicsProxy gfxProxy = getRobotGraphics(robotIndex); + + if (robotSnapshot.isSGPaintEnabled()) { + gfxProxy.processTo(g, graphicsCalls); + } else { + mirroredGraphics.bind(g, battleField.getHeight()); + gfxProxy.processTo(mirroredGraphics, graphicsCalls); + mirroredGraphics.release(); + } + + // Restore the graphics state + gfxState.restore(g); + + robotIndex++; + } + } + + private IGraphicsProxy getRobotGraphics(int robotIndex) { + if (robotGraphics[robotIndex] == null) { + robotGraphics[robotIndex] = new Graphics2DSerialized(); + robotGraphics[robotIndex].setPaintingEnabled(true); + } + return robotGraphics[robotIndex]; + } + + private void drawBullets(Graphics2D g, ITurnSnapshot snapShot) { + final Shape savedClip = g.getClip(); + + g.setClip(null); + + double x, y; + + for (IBulletSnapshot bulletSnapshot : snapShot.getBullets()) { + x = bulletSnapshot.getPaintX(); + y = battleField.getHeight() - bulletSnapshot.getPaintY(); + + AffineTransform at = AffineTransform.getTranslateInstance(x, y); + + if (bulletSnapshot.getState().isActive()) { + + // radius = sqrt(x^2 / 0.1 * power), where x is the width of 1 pixel for a minimum 0.1 bullet + double scale = max(2 * sqrt(2.5 * bulletSnapshot.getPower()), 2 / this.scale); + + at.scale(scale, scale); + Area bulletArea = BULLET_AREA.createTransformedArea(at); + + Color bulletColor; + + if (properties.getOptionsRenderingForceBulletColor()) { + bulletColor = Color.WHITE; + } else { + bulletColor = new Color(bulletSnapshot.getColor()); + } + g.setColor(bulletColor); + g.fill(bulletArea); + + } else if (drawExplosions) { + int explosionIndex = bulletSnapshot.getExplosionImageIndex(); + int frame = bulletSnapshot.getFrame(); + + // Sanity check to avoid bug-354 - Replaying an XML record can cause an ArrayIndexOutOfBoundsException + if (explosionIndex >= 0 && frame >= 0) { + if (!bulletSnapshot.isExplosion()) { + double scale = sqrt(1000 * bulletSnapshot.getPower()) / 128; + at.scale(scale, scale); + } + RenderImage explosionRenderImage = imageManager.getExplosionRenderImage(explosionIndex, frame); + explosionRenderImage.setTransform(at); + explosionRenderImage.paint(g); + } + } + } + g.setClip(savedClip); + } + + private void centerString(Graphics2D g, String s, int x, int y, Font font, FontMetrics fm) { + g.setFont(font); + + int width = fm.stringWidth(s); + int height = fm.getHeight(); + int descent = fm.getDescent(); + + double left = x - width / 2; + double top = y - height / 2; + + double scaledViewWidth = getWidth() / scale; + double scaledViewHeight = getHeight() / scale; + + double borderWidth = (scaledViewWidth - battleField.getWidth()) / 2; + double borderHeight = (scaledViewHeight - battleField.getHeight()) / 2; + + if (left + width > scaledViewWidth) { + left = scaledViewWidth - width; + } + if (top + height > scaledViewHeight) { + top = scaledViewHeight - height; + } + if (left < -borderWidth) { + left = -borderWidth; + } + if (top < -borderHeight) { + top = -borderHeight; + } + g.drawString(s, (int) (left + 0.5), (int) (top + height - descent + 0.5)); + } + + private void drawScanArc(Graphics2D g, IRobotSnapshot robotSnapshot) { + Arc2D.Double scanArc = (Arc2D.Double) ((RobotSnapshot) robotSnapshot).getScanArc(); + + if (scanArc == null) { + return; + } + + final Composite savedComposite = g.getComposite(); + + g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f)); + + scanArc.setAngleStart((360 - scanArc.getAngleStart() - scanArc.getAngleExtent()) % 360); + scanArc.y = battleField.getHeight() - robotSnapshot.getY() - robocode.Rules.RADAR_SCAN_RADIUS; + + int scanColor = robotSnapshot.getScanColor(); + + g.setColor(new Color(scanColor, true)); + + if (abs(scanArc.getAngleExtent()) >= .5) { + g.fill(scanArc); + } else { + g.draw(scanArc); + } + + g.setComposite(savedComposite); + } + + private void paintRobocodeLogo(Graphics2D g) { + setBackground(Color.BLACK); + g.clearRect(0, 0, getWidth(), getHeight()); + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g.transform(AffineTransform.getTranslateInstance((getWidth() - 320) / 2.0, (getHeight() - 46) / 2.0)); + g.setColor(new Color(0, 0x40, 0)); + g.fill(robocodeTextPath); + + Font font = new Font("Dialog", Font.BOLD, 14); + int width = g.getFontMetrics(font).stringWidth(ROBOCODE_SLOGAN); + + g.setTransform(new AffineTransform()); + g.setFont(font); + g.setColor(new Color(0, 0x50, 0)); + g.drawString(ROBOCODE_SLOGAN, (float) ((getWidth() - width) / 2.0), (float) (getHeight() / 2.0 + 50)); + } + + private class BattleObserver extends BattleAdaptor { + public BattleObserver(IWindowManager windowManager) { + windowManager.addBattleListener(this); + } + + @Override + public void onBattleStarted(BattleStartedEvent event) { + battleRules = event.getBattleRules(); + + battleField = new BattleField(battleRules.getBattlefieldWidth(), battleRules.getBattlefieldHeight()); + + initialized = false; + setVisible(true); + + super.onBattleStarted(event); + + robotGraphics = new IGraphicsProxy[event.getRobotsCount()]; + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + super.onBattleFinished(event); + robotGraphics = null; + } + + public void onTurnEnded(final TurnEndedEvent event) { + if (event.getTurnSnapshot() == null) { + repaint(); + } else { + update(event.getTurnSnapshot()); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/InteractiveHandler.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/InteractiveHandler.java new file mode 100644 index 0000000..a10cc6f --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/InteractiveHandler.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.battleview; + + +import net.sf.robocode.battle.BattleProperties; +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.security.SafeComponent; +import robocode.*; + +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.*; +import static java.lang.Math.min; + + +/** + * This handler is used for observing keyboard and mouse events from the battle view, + * which must be process to the all robots interactive event handlers. + * The mouse events y coordinates are mirrored to comply to the coordinate system + * used in Robocode. + * + * @author Pavel Savara (original) + * @author Flemming N. Larsen (contributor) + */ +public final class InteractiveHandler implements KeyEventDispatcher, MouseListener, MouseMotionListener, MouseWheelListener { + private final IBattleManager battleManager; + private final BattleView battleView; + + public InteractiveHandler(IBattleManager battleManager, BattleView battleView) { + this.battleManager = battleManager; + this.battleView = battleView; + } + + public boolean dispatchKeyEvent(java.awt.event.KeyEvent e) { + switch (e.getID()) { + case KeyEvent.KEY_TYPED: + handleInteractiveEvent(new KeyTypedEvent(cloneKeyEvent(e))); + break; + + case KeyEvent.KEY_PRESSED: + handleInteractiveEvent(new KeyPressedEvent(cloneKeyEvent(e))); + break; + + case KeyEvent.KEY_RELEASED: + handleInteractiveEvent(new KeyReleasedEvent(cloneKeyEvent(e))); + break; + } + + // Allow KeyboardFocusManager to take further action with regard to the KeyEvent. + // This way the InteractiveHandler does not steal the event, but is only a keyboard observer. + return false; + } + + public void mouseClicked(MouseEvent e) { + handleInteractiveEvent(new MouseClickedEvent(mirroredMouseEvent(e))); + } + + public void mouseEntered(MouseEvent e) { + handleInteractiveEvent(new MouseEnteredEvent(mirroredMouseEvent(e))); + } + + public void mouseExited(MouseEvent e) { + handleInteractiveEvent(new MouseExitedEvent(mirroredMouseEvent(e))); + } + + public void mousePressed(MouseEvent e) { + handleInteractiveEvent(new MousePressedEvent(mirroredMouseEvent(e))); + } + + public void mouseReleased(MouseEvent e) { + handleInteractiveEvent(new MouseReleasedEvent(mirroredMouseEvent(e))); + } + + public void mouseMoved(MouseEvent e) { + handleInteractiveEvent(new MouseMovedEvent(mirroredMouseEvent(e))); + } + + public void mouseDragged(MouseEvent e) { + handleInteractiveEvent(new MouseDraggedEvent(mirroredMouseEvent(e))); + } + + public void mouseWheelMoved(MouseWheelEvent e) { + handleInteractiveEvent(new MouseWheelMovedEvent(mirroredMouseWheelEvent(e))); + } + + public static KeyEvent cloneKeyEvent(final KeyEvent e) { + return new KeyEvent(SafeComponent.getSafeEventComponent(), e.getID(), e.getWhen(), e.getModifiersEx(), + e.getKeyCode(), e.getKeyChar(), e.getKeyLocation()); + } + + private void handleInteractiveEvent(robocode.Event event) { + battleManager.sendInteractiveEvent(event); + } + + private MouseEvent mirroredMouseEvent(final MouseEvent e) { + + double scale; + BattleProperties battleProps = battleManager.getBattleProperties(); + + int vWidth = battleView.getWidth(); + int vHeight = battleView.getHeight(); + int fWidth = battleProps.getBattlefieldWidth(); + int fHeight = battleProps.getBattlefieldHeight(); + + if (vWidth < fWidth || vHeight < fHeight) { + scale = min((double) vWidth / fWidth, (double) fHeight / fHeight); + } else { + scale = 1; + } + + double dx = (vWidth - scale * fWidth) / 2; + double dy = (vHeight - scale * fHeight) / 2; + + int x = (int) ((e.getX() - dx) / scale + 0.5); + int y = (int) (fHeight - (e.getY() - dy) / scale + 0.5); + + return new MouseEvent(SafeComponent.getSafeEventComponent(), e.getID(), e.getWhen(), e.getModifiersEx(), x, y, + e.getClickCount(), e.isPopupTrigger(), e.getButton()); + } + + private MouseWheelEvent mirroredMouseWheelEvent(final MouseWheelEvent e) { + + double scale; + BattleProperties battleProps = battleManager.getBattleProperties(); + + int vWidth = battleView.getWidth(); + int vHeight = battleView.getHeight(); + int fWidth = battleProps.getBattlefieldWidth(); + int fHeight = battleProps.getBattlefieldHeight(); + + if (vWidth < fWidth || vHeight < fHeight) { + scale = min((double) vWidth / fWidth, (double) fHeight / fHeight); + } else { + scale = 1; + } + + double dx = (vWidth - scale * fWidth) / 2; + double dy = (vHeight - scale * fHeight) / 2; + + int x = (int) ((e.getX() - dx) / scale + 0.5); + int y = (int) (fHeight - (e.getY() - dy) / scale + 0.5); + + return new MouseWheelEvent(SafeComponent.getSafeEventComponent(), e.getID(), e.getWhen(), e.getModifiersEx(), x, + y, e.getClickCount(), e.isPopupTrigger(), e.getScrollType(), e.getScrollAmount(), e.getWheelRotation()); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/MirroredGraphics.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/MirroredGraphics.java new file mode 100644 index 0000000..2264a3c --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/MirroredGraphics.java @@ -0,0 +1,567 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.battleview; + + +import net.sf.robocode.ui.gfx.GraphicsState; + +import java.awt.*; +import java.awt.RenderingHints.Key; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.text.AttributedCharacterIterator; +import java.util.Map; + + +/** + * This class is a Graphics2D wrapper class used for mirroring graphics on + * the Y-axis. This class ensures that strings that are painted using the + * drawBytes(), drawChars(), and drawString() methods are painted on the + * right location but that the text itself is not mirrored when painted. + * + * @author Flemming N. Larsen (original) + */ +public class MirroredGraphics extends Graphics2D { + + // The wrapped Graphics object + private Graphics2D g; + + // Save/restore of Graphics object + private final GraphicsState graphicsState = new GraphicsState(); + + // The original transform mirrored + private final AffineTransform origTxMirrored = new AffineTransform(); + + // A transform used for temporary transform operations (is reused) + private final AffineTransform tmpTx = new AffineTransform(); + + /** + * Binds a Graphics2D object to this wrapper object. + * When painting using this wrapper has finished the + * {@link #release() } method must be called. + * + * @param g the Graphics2D object to wrap + * @param height the height of the battlefield to mirror + * @see #release() + */ + public void bind(Graphics2D g, int height) { + this.g = g; + + graphicsState.save(g); + + origTxMirrored.setTransform(g.getTransform()); + origTxMirrored.translate(0, height); + origTxMirrored.scale(1, -1); + + g.setTransform(origTxMirrored); + } + + /** + * Releases the bounded Graphics2D object from this wrapper. + * + * @see #bind(Graphics2D, int) + */ + public void release() { + graphicsState.restore(g); + } + + // -------------------------------------------------------------------------- + // Overriding all methods from the extended Graphics class + // -------------------------------------------------------------------------- + + // Methods that should not be overridden or implemented: + // - finalize() + // - toString() + + @Override + public Graphics create() { + return g.create(); + } + + @Override + public Graphics create(int x, int y, int width, int height) { + return g.create(x, y, width, height); + } + + @Override + public void translate(int x, int y) { + g.translate(x, y); + } + + @Override + public Color getColor() { + return g.getColor(); + } + + @Override + public void setColor(Color c) { + g.setColor(c); + } + + @Override + public void setPaintMode() { + g.setPaintMode(); + } + + @Override + public void setXORMode(Color c1) { + g.setXORMode(c1); + } + + @Override + public Font getFont() { + return g.getFont(); + } + + @Override + public void setFont(Font font) { + g.setFont(font); + } + + @Override + public FontMetrics getFontMetrics(Font f) { + return g.getFontMetrics(f); + } + + @Override + public Rectangle getClipBounds() { + return g.getClipBounds(); + } + + @Override + public void clipRect(int x, int y, int width, int height) { + g.clipRect(x, y, width, height); + } + + @Override + public void setClip(int x, int y, int width, int height) { + g.setClip(x, y, width, height); + } + + @Override + public Shape getClip() { + return g.getClip(); + } + + @Override + public void setClip(Shape clip) { + g.setClip(clip); + } + + @Override + public void copyArea(int x, int y, int width, int height, int dx, int dy) { + g.copyArea(x, y, width, height, dx, dy); + } + + @Override + public void drawLine(int x1, int y1, int x2, int y2) { + g.drawLine(x1, y1, x2, y2); + } + + @Override + public void fillRect(int x, int y, int width, int height) { + g.fillRect(x, y, width, height); + } + + @Override + public void drawRect(int x, int y, int width, int height) { + g.drawRect(x, y, width, height); + } + + @Override + public void clearRect(int x, int y, int width, int height) { + g.clearRect(x, y, width, height); + } + + @Override + public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + g.drawRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + @Override + public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) { + g.fillRoundRect(x, y, width, height, arcWidth, arcHeight); + } + + @Override + public void draw3DRect(int x, int y, int width, int height, boolean raised) { + g.draw3DRect(x, y, width, height, raised); + } + + @Override + public void fill3DRect(int x, int y, int width, int height, boolean raised) { + g.fill3DRect(x, y, width, height, raised); + } + + @Override + public void drawOval(int x, int y, int width, int height) { + g.drawOval(x, y, width, height); + } + + @Override + public void fillOval(int x, int y, int width, int height) { + g.fillOval(x, y, width, height); + } + + @Override + public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + g.drawArc(x, y, width, height, startAngle - 90, arcAngle); // Translated into the Robocode coordinate system + } + + @Override + public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) { + g.fillArc(x, y, width, height, startAngle - 90, arcAngle); // Translated into the Robocode coordinate system + } + + @Override + public void drawPolyline(int[] xPoints, int[] yPoints, int npoints) { + g.drawPolyline(xPoints, yPoints, npoints); + } + + @Override + public void drawPolygon(int[] xPoints, int[] yPoints, int npoints) { + g.drawPolyline(xPoints, yPoints, npoints); + } + + @Override + public void drawPolygon(Polygon p) { + g.drawPolygon(p); + } + + @Override + public void fillPolygon(int[] xPoints, int[] yPoints, int npoints) { + g.fillPolygon(xPoints, yPoints, npoints); + } + + @Override + public void fillPolygon(Polygon p) { + g.fillPolygon(p); + } + + // Modified so that the y-axis is mirrored + @Override + public void drawString(String str, int x, int y) { + // Change the transform to use the mirrored transform and save the current one + AffineTransform saveTx = setToMirroredTransform(); + + g.drawString(str, x, -y); + + // Restore the transform + g.setTransform(saveTx); + } + + // Modified so that the y-axis is mirrored + @Override + public void drawString(AttributedCharacterIterator iterator, int x, int y) { + // Change the transform to use the mirrored transform and save the current one + AffineTransform saveTx = setToMirroredTransform(); + + g.drawString(iterator, x, -y); + + // Restore the transform + g.setTransform(saveTx); + } + + // Modified so that the y-axis is mirrored + @Override + public void drawChars(char[] data, int offset, int length, int x, int y) { + // Change the transform to use the mirrored transform and save the current one + AffineTransform saveTx = setToMirroredTransform(); + + g.drawChars(data, offset, length, x, -y); + + // Restore the transform + g.setTransform(saveTx); + } + + // Modified so that the y-axis is mirrored + @Override + public void drawBytes(byte[] data, int offset, int length, int x, int y) { + // Change the transform to use the mirrored transform and save the current one + AffineTransform saveTx = setToMirroredTransform(); + + g.drawBytes(data, offset, length, x, -y); + + // Restore the transform + g.setTransform(saveTx); + } + + @Override + public boolean drawImage(Image img, int x, int y, ImageObserver observer) { + return g.drawImage(img, x, y, observer); + } + + @Override + public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { + return g.drawImage(img, x, y, width, height, observer); + } + + @Override + public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) { + return g.drawImage(img, x, y, bgcolor, observer); + } + + @Override + public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { + return g.drawImage(img, x, y, width, height, bgcolor, observer); + } + + @Override + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, + ImageObserver observer) { + return g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); + } + + @Override + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, + Color bgcolor, ImageObserver observer) { + return g.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer); + } + + @Override + public void dispose() { + g.dispose(); + } + + @Override + @Deprecated + public Rectangle getClipRect() { + return g.getClipBounds(); // Must use getClipBounds() instead of the deprecated getClipRect() method + } + + @Override + public boolean hitClip(int x, int y, int width, int height) { + return g.hitClip(x, y, width, height); + } + + @Override + public Rectangle getClipBounds(Rectangle r) { + return g.getClipBounds(r); + } + + // -------------------------------------------------------------------------- + // Overriding all methods from the extended Graphics2D class + // -------------------------------------------------------------------------- + + @Override + public void draw(Shape s) { + g.draw(s); + } + + @Override + public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { + return g.drawImage(img, xform, obs); + } + + @Override + public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { + g.drawImage(img, op, x, y); + } + + @Override + public void drawRenderedImage(RenderedImage img, AffineTransform xform) { + g.drawRenderedImage(img, xform); + } + + @Override + public void drawRenderableImage(RenderableImage img, AffineTransform xform) { + g.drawRenderableImage(img, xform); + } + + // Modified so that the y-axis is mirrored + @Override + public void drawString(String str, float x, float y) { + // Change the transform to use the mirrored transform and save the current one + AffineTransform saveTx = setToMirroredTransform(); + + g.drawString(str, x, -y); + + // Restore the transform + g.setTransform(saveTx); + } + + // Modified so that the y-axis is mirrored + @Override + public void drawString(AttributedCharacterIterator iterator, float x, float y) { + // Change the transform to use the mirrored transform and save the current one + AffineTransform saveTx = setToMirroredTransform(); + + g.drawString(iterator, x, -y); + + // Restore the transform + g.setTransform(saveTx); + } + + @Override + public void drawGlyphVector(GlyphVector gv, float x, float y) { + g.drawGlyphVector(gv, x, y); + } + + @Override + public void fill(Shape s) { + g.fill(s); + } + + @Override + public boolean hit(Rectangle rect, Shape s, boolean onStroke) { + return g.hit(rect, s, onStroke); + } + + @Override + public GraphicsConfiguration getDeviceConfiguration() { + return g.getDeviceConfiguration(); + } + + @Override + public void setComposite(Composite comp) { + g.setComposite(comp); + } + + @Override + public void setPaint(Paint paint) { + g.setPaint(paint); + } + + @Override + public void setStroke(Stroke s) { + g.setStroke(s); + } + + @Override + public void setRenderingHint(Key hintKey, Object hintValue) { + g.setRenderingHint(hintKey, hintValue); + } + + @Override + public Object getRenderingHint(Key hintKey) { + return g.getRenderingHint(hintKey); + } + + @Override + public void setRenderingHints(Map hints) { + g.setRenderingHints(hints); + } + + @Override + public void addRenderingHints(Map hints) { + g.addRenderingHints(hints); + } + + @Override + public RenderingHints getRenderingHints() { + return g.getRenderingHints(); + } + + @Override + public void translate(double tx, double ty) { + g.translate(tx, ty); + } + + @Override + public void rotate(double theta) { + g.rotate(theta); + } + + @Override + public void rotate(double theta, double x, double y) { + g.rotate(theta, x, y); + } + + @Override + public void scale(double sx, double sy) { + g.scale(sx, sy); + } + + @Override + public void shear(double shx, double shy) { + g.shear(shx, shy); + } + + @Override + public void transform(AffineTransform Tx) { + g.transform(Tx); + } + + // Transforming is handled on the y-axis mirrored transform + @Override + public void setTransform(AffineTransform Tx) { + // Set the current transform to by the original mirrored transform + // concatenated with the input transform. This way the new transform + // will automatically be mirrored around the y-axis + tmpTx.setTransform(origTxMirrored); + tmpTx.concatenate(Tx); + g.setTransform(tmpTx); + } + + @Override + public AffineTransform getTransform() { + return g.getTransform(); + } + + @Override + public Paint getPaint() { + return g.getPaint(); + } + + @Override + public Composite getComposite() { + return g.getComposite(); + } + + @Override + public void setBackground(Color color) { + g.setBackground(color); + } + + @Override + public Color getBackground() { + return g.getBackground(); + } + + @Override + public Stroke getStroke() { + return g.getStroke(); + } + + @Override + public void clip(Shape s) { + g.clip(s); + } + + @Override + public FontRenderContext getFontRenderContext() { + return g.getFontRenderContext(); + } + + // -------------------------------------------------------------------------- + // Private worker methods + // -------------------------------------------------------------------------- + + /** + * This methods translates the current transform on the internal Graphics2D + * object into a transform that is mirrored around the y-axis. + * + * @return the AffineTransform before calling this method, which must be + * used for restoring the AffineTransform later. + */ + private AffineTransform setToMirroredTransform() { + AffineTransform saveTx = g.getTransform(); + + tmpTx.setTransform(saveTx); + tmpTx.scale(1, -1); + g.setTransform(tmpTx); + + return saveTx; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/ScreenshotUtil.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/ScreenshotUtil.java new file mode 100644 index 0000000..62cbefd --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/battleview/ScreenshotUtil.java @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.battleview; + + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Iterator; + +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.stream.FileImageOutputStream; + +import net.sf.robocode.io.FileUtil; + + +/** + * This utility class for saving screenshots of the battle view. + * + * @author Flemming N. Larsen (original) + * + * @since 1.7.2 + */ +public class ScreenshotUtil { + + private final static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH.mm.ss.SSS"); + + public static void saveScreenshot(BufferedImage screenshot, String format, float compressionQuality) { + FileImageOutputStream output = null; + ImageWriter writer = null; + + File screenshotDir = FileUtil.getScreenshotsDir(); + + FileUtil.createDir(screenshotDir); + + File file = new File(screenshotDir, DATE_FORMAT.format(new Date()) + '.' + format.toLowerCase()); + + try { + // Instantiate an ImageWriteParam object with default compression options + Iterator it = ImageIO.getImageWritersByFormatName(format); + + writer = (ImageWriter) it.next(); + ImageWriteParam iwp = writer.getDefaultWriteParam(); + + // If compression is supported, then set the compression mode + if (iwp.canWriteCompressed()) { + // Use explicit compression mode + iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + + // Set compression quality, where 1 specifies minimum compression and maximum quality + iwp.setCompressionQuality(compressionQuality); // float between 0 and 1 + } + // Write the screen shot to file + output = new FileImageOutputStream(file); + writer.setOutput(output); + IIOImage image = new IIOImage(screenshot, null, null); + + writer.write(null, image, iwp); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (writer != null) { + writer.dispose(); + } + if (output != null) { + try { + output.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/AboutBox.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/AboutBox.java new file mode 100644 index 0000000..4ac7bad --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/AboutBox.java @@ -0,0 +1,225 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.ui.BrowserManager; +import net.sf.robocode.version.IVersionManager; + +import javax.swing.*; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.net.URL; +import java.net.URLConnection; + + +/** + * The About box. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public final class AboutBox extends JDialog { + // Tag used for background color replacement + private final static Color BG_COLOR = new Color(0xF0, 0xF0, 0xF0); + // Tag used for Robocode version replacement + private final static String TAG_ROBOCODE_VERSION = "\\Q{$robocode-version}\\E"; + // Tag used for Robocode icon source replacement + private final static String TAG_ROBOCODE_ICON_SRC = "\\Q{$robocode-icon-url}\\E"; + // Tag used for background color replacement + private final static String TAG_BG_COLOR = "\\Q{$background-color}\\E"; + // Tag used for Java version replacement + private final static String TAG_JAVA_VERSION = "\\Q{$java-version}\\E"; + // Tag used for Java vendor replacement + private final static String TAG_JAVA_VENDOR = "\\Q{$java-vendor}\\E"; + // Tag used for transparent.png 1x1 px url replacement + private final static String TAG_TRANSPARENT = "\\Q{$transparent}\\E"; + + // Robocode version + private final String robocodeVersion; + // Robocode icon URL + private final java.net.URL iconURL; + // Transparent URL + private final java.net.URL transparentURL; + + // Content pane + private JPanel aboutBoxContentPane; + // Main panel + private JEditorPane mainPanel; + // Button panel + private JPanel buttonPanel; + // OK button + private JButton okButton; + // HTML text after tag replacements + private String html; + + private static String getHtmlTemplate() { + URL url = AboutBox.class.getResource("/net/sf/robocode/ui/html/about.html"); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + try { + URLConnection connection = url.openConnection(); + int contentLength = connection.getContentLength(); + InputStream in = url.openStream(); + byte[] buf = new byte[contentLength]; + int len; + + while (true) { + len = in.read(buf); + if (len == -1) { + break; + } + baos.write(buf, 0, len); + } + baos.close(); + } catch (IOException ignore) {} + return baos.toString(); + } + + // General event handler + private final transient ActionListener eventHandler = new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (e.getSource() == AboutBox.this.getOkButton()) { + AboutBox.this.dispose(); + } + } + }; + + // Hyperlink event handler + private final transient HyperlinkListener hyperlinkHandler = new HyperlinkListener() { + public void hyperlinkUpdate(HyperlinkEvent event) { + if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + try { + BrowserManager.openURL(event.getURL().toExternalForm()); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + }; + + public AboutBox(RobocodeFrame owner, IVersionManager versionManager) { + super(owner, true); + + robocodeVersion = versionManager.getVersion(); + + iconURL = AboutBox.class.getResource("/net/sf/robocode/ui/icons/robocode-icon.png"); + transparentURL = AboutBox.class.getResource("/net/sf/robocode/ui/html/transparent.png"); + + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setTitle("About Robocode"); + setContentPane(getAboutBoxContentPane()); + setResizable(false); + } + + private JPanel getAboutBoxContentPane() { + if (aboutBoxContentPane == null) { + aboutBoxContentPane = new JPanel(); + aboutBoxContentPane.setLayout(new BorderLayout()); + aboutBoxContentPane.add(getButtonPanel(), BorderLayout.SOUTH); + aboutBoxContentPane.add(getMainPanel(), BorderLayout.CENTER); + } + return aboutBoxContentPane; + } + + private JEditorPane getMainPanel() { + if (mainPanel == null) { + String aaFontSettings = System.getProperty("awt.useSystemAAFontSettings"); + + if (aaFontSettings != null) { + mainPanel = new JEditorPane("text/html; charset=ISO-8859-1", getHtmlText()); + System.out.println(aaFontSettings); + } else { + mainPanel = new JEditorPane("text/html; charset=ISO-8859-1", getHtmlText()) { + @Override + public void paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + super.paintComponent(g); + } + }; + } + mainPanel.setBackground(BG_COLOR); + mainPanel.setEditable(false); + mainPanel.addHyperlinkListener(hyperlinkHandler); + } + return mainPanel; + } + + private JPanel getButtonPanel() { + if (buttonPanel == null) { + buttonPanel = new JPanel(); + buttonPanel.setBackground(BG_COLOR); + buttonPanel.setLayout(new FlowLayout()); + buttonPanel.add(getOkButton()); + } + return buttonPanel; + } + + private JButton getOkButton() { + if (okButton == null) { + okButton = new JButton(); + okButton.setText("OK"); + okButton.addActionListener(eventHandler); + } + return okButton; + } + + private String getHtmlText() { + if (html == null) { + html = getHtmlTemplate(); + html = html.replaceAll(TAG_ROBOCODE_VERSION, robocodeVersion); + html = html.replaceAll(TAG_ROBOCODE_ICON_SRC, iconURL.toString()); + html = html.replaceAll(TAG_BG_COLOR, toHtmlColor(BG_COLOR)); + html = html.replaceAll(TAG_JAVA_VERSION, getJavaVersion()); + html = html.replaceAll(TAG_JAVA_VENDOR, System.getProperty("java.vendor")); + html = html.replaceAll(TAG_TRANSPARENT, transparentURL.toString()); + } + return html; + } + + private static String toHtmlColor(Color color) { + return "#" + toHexDigits(color.getRed()) + toHexDigits(color.getGreen()) + toHexDigits(color.getBlue()); + } + + private static String toHexDigits(int value) { + return "" + toHexDigit(value >> 4) + toHexDigit(value & 0x0f); + } + + private static char toHexDigit(int value) { + int v = (value & 0xf); + + if (v < 10) { + return (char) ('0' + v); + } + return (char) ('A' + (v - 10)); + } + + private static String getJavaVersion() { + String javaVersion = System.getProperty("java.version"); + String javaArchModel = System.getProperty("sun.arch.data.model"); + + if (javaArchModel != null) { + try { + int numBits = Integer.parseInt(javaArchModel); + + javaVersion += " (" + numBits + "-bit)"; + } catch (NumberFormatException ignore) {} + } + return javaVersion; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/AvailableRobotsPanel.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/AvailableRobotsPanel.java new file mode 100644 index 0000000..5d97c2b --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/AvailableRobotsPanel.java @@ -0,0 +1,421 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.ui.util.ShortcutUtil; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +@SuppressWarnings("serial") +public class AvailableRobotsPanel extends JPanel { + + private final List availableRobots = new CopyOnWriteArrayList(); + private List robotList = new CopyOnWriteArrayList(); + private final List availablePackages = new CopyOnWriteArrayList(); + + private JScrollPane availableRobotsScrollPane; + private JList availableRobotsList; + + private final JButton actionButton; + + private final JList actionList; + private JList availablePackagesList; + + private JScrollPane availablePackagesScrollPane; + + private RobotNameCellRenderer robotNameCellRenderer; + + private final RobotSelectionPanel robotSelectionPanel; + + private final String title; + + private final EventHandler eventHandler = new EventHandler(); + + public AvailableRobotsPanel(JButton actionButton, String title, JList actionList, + RobotSelectionPanel robotSelectionPanel) { + super(); + this.title = title; + this.actionButton = actionButton; + this.actionList = actionList; + this.robotSelectionPanel = robotSelectionPanel; + initialize(); + } + + private void initialize() { + setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title)); + setLayout(new BorderLayout()); + + JPanel top = new JPanel(); + + top.setLayout(new GridLayout(1, 2)); + + JPanel a = new JPanel(); + + a.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Packages")); + a.setLayout(new BorderLayout()); + a.add(getAvailablePackagesScrollPane()); + a.setPreferredSize(new Dimension(120, 100)); + top.add(a); + + JPanel b = new JPanel(); + + b.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), "Robots")); + b.setLayout(new BorderLayout()); + b.add(getAvailableRobotsScrollPane()); + b.setPreferredSize(new Dimension(120, 100)); + top.add(b); + + add(top, BorderLayout.CENTER); + + JLabel refreshLabel = new JLabel("Press " + ShortcutUtil.getModifierKeyText() + "+R to refresh"); + + refreshLabel.setHorizontalAlignment(SwingConstants.CENTER); + add(refreshLabel, BorderLayout.SOUTH); + } + + public List getAvailableRobots() { + return availableRobots; + } + + public List getRobotList() { + return robotList; + } + + public List getSelectedRobots() { + List selected = new ArrayList(); + + for (int i : getAvailableRobotsList().getSelectedIndices()) { + selected.add(availableRobots.get(i)); + } + return selected; + } + + /** + * Return the availableRobotsList. + * + * @return JList + */ + public JList getAvailableRobotsList() { + if (availableRobotsList == null) { + availableRobotsList = new JList(); + availableRobotsList.setModel(new AvailableRobotsModel()); + availableRobotsList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + + availableRobotsList.setCellRenderer(getRobotNameCellRenderer()); + + MouseListener mouseListener = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + // This does not work in Linux under IBM JRE 1.3.0... + if (e.getClickCount() >= 2) { + if (e.getClickCount() % 2 == 0) { + if (actionButton != null) { + actionButton.doClick(); + } + } + } + } + }; + + availableRobotsList.addMouseListener(mouseListener); + availableRobotsList.addListSelectionListener(eventHandler); + } + return availableRobotsList; + } + + /** + * Return the JScrollPane1 property value. + * + * @return JScrollPane + */ + private JScrollPane getAvailableRobotsScrollPane() { + if (availableRobotsScrollPane == null) { + availableRobotsScrollPane = new JScrollPane(); + availableRobotsScrollPane.setViewportView(getAvailableRobotsList()); + + // Bug fix [2975871] - Minor visual bug - Currently selected robot gets covered + availableRobotsScrollPane.addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent e) { + getAvailableRobotsList().ensureIndexIsVisible(getAvailableRobotsList().getSelectedIndex()); + } + }); + } + return availableRobotsScrollPane; + } + + public void setRobotList(List robotListList) { + robotList = robotListList; + SwingUtilities.invokeLater(new Runnable() { + public void run() { + availablePackages.clear(); + availableRobots.clear(); + + if (robotList == null) { + robotList = new CopyOnWriteArrayList(); + availablePackages.add("One moment please..."); + ((AvailablePackagesModel) getAvailablePackagesList().getModel()).changed(); + getAvailablePackagesList().clearSelection(); + ((AvailableRobotsModel) getAvailableRobotsList().getModel()).changed(); + } else { + availablePackages.add("(All)"); + String packageName; + + for (IRobotSpecItem robotSpec : robotList) { + packageName = robotSpec.getFullPackage(); + if (packageName == null) { + continue; + } + if (!availablePackages.contains(packageName)) { + availablePackages.add(packageName); + } + } + availablePackages.add("(No package)"); + + for (IRobotSpecItem robotSpec : robotList) { + availableRobots.add(new ItemWrapper(robotSpec)); + } + ((AvailablePackagesModel) getAvailablePackagesList().getModel()).changed(); + getAvailablePackagesList().setSelectedIndex(0); + ((AvailableRobotsModel) getAvailableRobotsList().getModel()).changed(); + getAvailablePackagesList().requestFocus(); + } + } + }); + } + + private void availablePackagesListSelectionChanged() { + int sel[] = getAvailablePackagesList().getSelectedIndices(); + + boolean useShortName = false; + + availableRobots.clear(); + if (sel.length == 1) { + useShortName = true; + getAvailablePackagesList().scrollRectToVisible(getAvailablePackagesList().getCellBounds(sel[0], sel[0])); + } + + for (int element : sel) { + String selectedPackage = availablePackages.get(element); + + if (selectedPackage.equals("(All)")) { + useShortName = false; + availableRobots.clear(); + for (IRobotSpecItem robotItem : robotList) { + getRobotNameCellRenderer().setUseShortName(useShortName); + availableRobots.add(new ItemWrapper(robotItem)); + } + break; + } + // Single package. + for (IRobotSpecItem robotItem : robotList) { + getRobotNameCellRenderer().setUseShortName(useShortName); + + if ((robotItem.getFullPackage() == null && selectedPackage.equals("(No package)")) + || selectedPackage.equals(robotItem.getFullPackage())) { + availableRobots.add(new ItemWrapper(robotItem)); + } + } + } + ((AvailableRobotsModel) getAvailableRobotsList().getModel()).changed(); + if (availableRobots.size() > 0) { + availableRobotsList.setSelectedIndex(0); + availableRobotsListSelectionChanged(); + } + } + + private void availableRobotsListSelectionChanged() { + int sel[] = getAvailableRobotsList().getSelectedIndices(); + + if (sel.length == 1) { + if (actionList != null) { + actionList.clearSelection(); + } + IRobotSpecItem robotSpecification = ((ItemWrapper) getAvailableRobotsList().getModel().getElementAt(sel[0])).getItem(); + + if (robotSelectionPanel != null) { + robotSelectionPanel.showDescription(robotSpecification); + } + } else { + if (robotSelectionPanel != null) { + robotSelectionPanel.showDescription(null); + } + } + } + + public void clearSelection() { + getAvailableRobotsList().clearSelection(); + ((AvailableRobotsModel) getAvailableRobotsList().getModel()).changed(); + } + + /** + * Return the availableRobotsList. + * + * @return JList + */ + private JList getAvailablePackagesList() { + if (availablePackagesList == null) { + availablePackagesList = new JList(); + availablePackagesList.setModel(new AvailablePackagesModel()); + availablePackagesList.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + availablePackagesList.addListSelectionListener(eventHandler); + } + return availablePackagesList; + } + + /** + * Return the availablePackagesScrollPane + * + * @return JScrollPane + */ + private JScrollPane getAvailablePackagesScrollPane() { + if (availablePackagesScrollPane == null) { + availablePackagesScrollPane = new JScrollPane(); + availablePackagesScrollPane.setViewportView(getAvailablePackagesList()); + } + return availablePackagesScrollPane; + } + + private RobotNameCellRenderer getRobotNameCellRenderer() { + if (robotNameCellRenderer == null) { + robotNameCellRenderer = new RobotNameCellRenderer(); + } + return robotNameCellRenderer; + } + + private class EventHandler implements ListSelectionListener { + public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting()) { + return; + } + if (e.getSource() == getAvailableRobotsList()) { + availableRobotsListSelectionChanged(); + } else if (e.getSource() == getAvailablePackagesList()) { + availablePackagesListSelectionChanged(); + } + } + } + + + private class AvailablePackagesModel extends AbstractListModel { + public void changed() { + fireContentsChanged(this, 0, getSize()); + } + + public int getSize() { + return availablePackages.size(); + } + + public String getElementAt(int which) { + return availablePackages.get(which); + } + } + + + private class AvailableRobotsModel extends AbstractListModel { + public void changed() { + fireContentsChanged(this, 0, getSize()); + } + + public int getSize() { + return availableRobots.size(); + } + + public ItemWrapper getElementAt(int which) { + return availableRobots.get(which); + } + } + + + /** + * Is there because of keyboard navigation is tied to toString() method + */ + public static class ItemWrapper { + private final IRobotSpecItem item; + + public ItemWrapper(IRobotSpecItem item) { + this.item = item; + } + + public IRobotSpecItem getItem() { + return item; + } + + // Used writing the robot name in JList. Is used for keyboard typing in JList to find robot. Bugfix for [2658090] + public String toString() { + return item.getUniqueShortClassNameWithVersion(); + } + } + + + /** + * RobotNameCellRender, which renders the list cells with "Team: " prefix, and with or without package names. + * This is cheating, as the ItemWrapper.toString() delivers the string used for keyboard navigation etc. + */ + private static class RobotNameCellRenderer extends JLabel implements ListCellRenderer { + private boolean useShortName = false; + + public RobotNameCellRenderer() { + setOpaque(true); + } + + public void setUseShortName(boolean useShortNames) { + this.useShortName = useShortNames; + } + + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + + setComponentOrientation(list.getComponentOrientation()); + + if (isSelected) { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } else { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + + String text; + + if (value instanceof ItemWrapper) { + IRobotSpecItem item = ((ItemWrapper) value).getItem(); + + text = (item.isTeam() ? "Team: " : ""); + text += useShortName + ? item.getUniqueShortClassNameWithVersion() + : item.getUniqueFullClassNameWithVersion(); + } else { + text = value.toString(); + } + setText(text); + + setEnabled(list.isEnabled()); + setFont(list.getFont()); + + return this; + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BaseScoreDialog.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BaseScoreDialog.java new file mode 100644 index 0000000..a451d95 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BaseScoreDialog.java @@ -0,0 +1,179 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.ui.IWindowManager; +import net.sf.robocode.ui.IWindowManagerExt; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableColumn; +import java.awt.*; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; + + +/** + * @author Pavel Savara (original) + */ +@SuppressWarnings("serial") +public abstract class BaseScoreDialog extends JDialog { + protected final IWindowManagerExt windowManager; + + private final EventHandler eventHandler = new EventHandler(); + protected JPanel contentPane; + protected JScrollPane scrollPane; + protected JTable table; + protected Dimension tableSize; + + public BaseScoreDialog(IWindowManager windowManager, boolean modal) { + // In order to prevent the dialog from hiding, null must be given as 'owner' parameter + super(windowManager != null ? windowManager.getRobocodeFrame() : null, modal); + this.windowManager = (IWindowManagerExt) windowManager; + } + + protected void initialize() { + addComponentListener(eventHandler); + setContentPane(getDialogContentPane()); + } + + /** + * Return the content pane. + * + * @return JPanel + */ + protected JPanel getDialogContentPane() { + if (contentPane == null) { + contentPane = new JPanel(); + contentPane.setLayout(new BorderLayout()); + contentPane.add(getScrollPane(), "Center"); + } + return contentPane; + } + + /** + * Return the scroll pane + * + * @return JScrollPane + */ + protected JScrollPane getScrollPane() { + if (scrollPane == null) { + scrollPane = new JScrollPane(); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED); + scrollPane.getViewport().setScrollMode(JViewport.BLIT_SCROLL_MODE); + scrollPane.setViewportView(getTable()); + scrollPane.setColumnHeaderView(table.getTableHeader()); + scrollPane.addComponentListener(eventHandler); + + tableSize = new Dimension(getTable().getColumnModel().getTotalColumnWidth(), + getTable().getModel().getRowCount() * (getTable().getRowHeight())); + table.setPreferredScrollableViewportSize(tableSize); + table.setPreferredSize(tableSize); + table.setMinimumSize(tableSize); + } + return scrollPane; + } + + /** + * Return the table. + * + * @return JTable + */ + protected JTable getTable() { + if (table == null) { + table = new JTable(); + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + table.setColumnSelectionAllowed(true); + table.setRowSelectionAllowed(true); + table.getTableHeader().setReorderingAllowed(false); + } + return table; + } + + private class EventHandler implements ComponentListener { + public void componentShown(ComponentEvent e) { + onDialogShown(); + } + + public void componentHidden(ComponentEvent e) { + onDialogHidden(); + } + + public void componentResized(ComponentEvent e) { + if (e.getSource() == BaseScoreDialog.this.getScrollPane()) { + scrollPaneComponentResized(); + } + } + + public void componentMoved(ComponentEvent e) {} + } + + protected abstract AbstractTableModel getTableModel(); + + protected void onDialogShown() {} + + protected void onDialogHidden() { + dispose(); + } + + protected void scrollPaneComponentResized() { + // This code is not working... + Dimension scrollPaneExtent = getScrollPane().getViewport().getExtentSize(); + + if (tableSize != null && (tableSize.width < scrollPaneExtent.width)) { + getTable().setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS); + getTable().setSize(scrollPaneExtent); + getTable().sizeColumnsToFit(-1); + } else { + if (tableSize != null) { + getTable().setSize(tableSize); + getTable().sizeColumnsToFit(-1); + } + table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + } + validate(); + repaint(); + } + + protected void setResultsData() { + getTable().setModel(getTableModel()); + int maxScoreColWidth = 0; + + for (int x = 0; x < getTableModel().getColumnCount(); x++) { + if (x != 1) { + getTable().getColumnModel().getColumn(x).setCellRenderer(new ResultsTableCellRenderer(false)); + } + TableColumn column = getTable().getColumnModel().getColumn(x); + Component comp; + + column.setHeaderRenderer(new ResultsTableCellRenderer(true)); + comp = column.getHeaderRenderer().getTableCellRendererComponent(null, column.getHeaderValue(), false, false, + 0, 0); + int width = comp.getPreferredSize().width; + + for (int y = 0; y < getTableModel().getRowCount(); y++) { + comp = getTable().getDefaultRenderer(getTableModel().getColumnClass(x)).getTableCellRendererComponent( + getTable(), getTableModel().getValueAt(y, x), false, false, 0, x); + if (comp.getPreferredSize().width > width) { + width = comp.getPreferredSize().width; + } + } + TableColumn col = getTable().getColumnModel().getColumn(x); + + col.setPreferredWidth(width); + col.setMinWidth(width); + col.setWidth(width); + + if (x >= 3 && width > maxScoreColWidth) { + maxScoreColWidth = width; + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BattleButton.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BattleButton.java new file mode 100644 index 0000000..0e506b8 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BattleButton.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * @author Pavel Savara (original) + */ +public class BattleButton extends JButton implements ActionListener { + private static final long serialVersionUID = 1L; + + private final BattleDialog battleDialog; + + public BattleButton(BattleDialog battleDialog) { + this.battleDialog = battleDialog; + + initialize(); + } + + public void actionPerformed(ActionEvent e) { + attach(); + if (!battleDialog.isVisible() || battleDialog.getState() != Frame.NORMAL) { + WindowUtil.packPlaceShow(battleDialog); + } else { + battleDialog.setVisible(true); + } + } + + /** + * Initialize the class. + */ + private void initialize() { + addActionListener(this); + setPreferredSize(new Dimension(110, 25)); + setMinimumSize(new Dimension(110, 25)); + setMaximumSize(new Dimension(110, 25)); + setHorizontalAlignment(SwingConstants.CENTER); + setMargin(new Insets(0, 0, 0, 0)); + setText("Main battle log"); + setToolTipText("Main battle log"); + } + + public void attach() { + battleDialog.attach(); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BattleDialog.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BattleDialog.java new file mode 100644 index 0000000..7f5b58f --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/BattleDialog.java @@ -0,0 +1,244 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.serialization.IXmlSerializable; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.serialization.XmlWriter; +import net.sf.robocode.ui.IWindowManager; +import robocode.control.events.*; +import robocode.control.snapshot.ITurnSnapshot; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.io.StringWriter; + + +/** + * @author Pavel Savara (original) + */ +public class BattleDialog extends JFrame { + private static final long serialVersionUID = 1L; + + private final BattleObserver battleObserver = new BattleObserver(); + + private ConsoleScrollPane consoleScrollPane; + private ConsoleScrollPane turnSnapshotScrollPane; + private JTabbedPane tabbedPane; + private JButton okButton; + private JButton clearButton; + private JPanel battleDialogContentPane; + private JPanel buttonPanel; + + private final IWindowManager windowManager; + private boolean isListening; + private ITurnSnapshot lastSnapshot; + private boolean paintSnapshot; + + public BattleDialog(IWindowManager windowManager) { + this.windowManager = windowManager; + initialize(); + } + + private void initialize() { + this.setTitle("Main battle log"); + this.add(getBattleDialogContentPane()); + pack(); + } + + public void detach() { + if (isListening) { + windowManager.removeBattleListener(battleObserver); + isListening = false; + } + } + + public void reset() { + getConsoleScrollPane().setText(null); + getTurnSnapshotScrollPane().setText(null); + lastSnapshot = null; + } + + public void attach() { + if (!isListening) { + isListening = true; + windowManager.addBattleListener(battleObserver); + } + } + + /** + * When robotDialog is packed, we want to set a reasonable size. However, + * after that, we need a null preferred size so the scroll pane will scroll. + * (preferred size should be based on the text inside) + */ + @Override + public void pack() { + getConsoleScrollPane().setPreferredSize(new Dimension(426, 200)); + super.pack(); + getTabbedPane().setPreferredSize(null); + } + + private JPanel getBattleDialogContentPane() { + if (battleDialogContentPane == null) { + battleDialogContentPane = new JPanel(); + battleDialogContentPane.setLayout(new BorderLayout()); + battleDialogContentPane.add(getTabbedPane()); + battleDialogContentPane.add(getButtonPanel(), BorderLayout.SOUTH); + } + return battleDialogContentPane; + } + + private JPanel getButtonPanel() { + if (buttonPanel == null) { + buttonPanel = new JPanel(); + buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); + buttonPanel.add(getOkButton()); + buttonPanel.add(getClearButton()); + } + return buttonPanel; + } + + private JButton getOkButton() { + if (okButton == null) { + okButton = getNewButton("OK"); + } + return okButton; + } + + private JButton getClearButton() { + if (clearButton == null) { + clearButton = getNewButton("Clear"); + } + return clearButton; + } + + private JButton getNewButton(String text) { + JButton button = new JButton(text); + + button.addActionListener(eventHandler); + return button; + } + + private final transient ActionListener eventHandler = new ActionListener() { + public void actionPerformed(ActionEvent e) { + Object src = e.getSource(); + + if (src == BattleDialog.this.getOkButton()) { + okButtonActionPerformed(); + } else if (src == BattleDialog.this.getClearButton()) { + clearButtonActionPerformed(); + } + } + }; + + private JTabbedPane getTabbedPane() { + if (tabbedPane == null) { + tabbedPane = new JTabbedPane(); + tabbedPane.setLayout(new BorderLayout()); + tabbedPane.addTab("Console", getConsoleScrollPane()); + tabbedPane.addTab("Turn Snapshot", getTurnSnapshotScrollPane()); + tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + + tabbedPane.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + paintSnapshot = (tabbedPane.getSelectedIndex() == 1); + paintSnapshot(); + } + }); + } + return tabbedPane; + } + + private ConsoleScrollPane getConsoleScrollPane() { + if (consoleScrollPane == null) { + consoleScrollPane = new ConsoleScrollPane(); + } + return consoleScrollPane; + } + + private ConsoleScrollPane getTurnSnapshotScrollPane() { + if (turnSnapshotScrollPane == null) { + turnSnapshotScrollPane = new ConsoleScrollPane(); + } + return turnSnapshotScrollPane; + } + + private void okButtonActionPerformed() { + dispose(); + } + + private void clearButtonActionPerformed() { + reset(); + } + + private void paintSnapshot() { + if (paintSnapshot) { + String text = null; + + if (lastSnapshot != null) { + final StringWriter writer = new StringWriter(); + final XmlWriter xmlWriter = new XmlWriter(writer, true); + + try { + ((IXmlSerializable) lastSnapshot).writeXml(xmlWriter, new SerializableOptions(false)); + writer.close(); + } catch (IOException e) { + Logger.logError(e); + } + text = writer.toString(); + } + getTurnSnapshotScrollPane().setText(text); + } + } + + private class BattleObserver extends BattleAdaptor { + + @Override + public void onBattleMessage(BattleMessageEvent event) { + final String text = event.getMessage(); + + if (text != null && text.length() > 0) { + getConsoleScrollPane().append(text + "\n"); + getConsoleScrollPane().scrollToBottom(); + } + } + + @Override + public void onBattleError(BattleErrorEvent event) { + final String text = event.getError(); + + if (text != null && text.length() > 0) { + getConsoleScrollPane().append(text + "\n"); + getConsoleScrollPane().scrollToBottom(); + } + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + lastSnapshot = event.getTurnSnapshot(); + paintSnapshot(); + } + + public void onBattleStarted(final BattleStartedEvent event) { + reset(); + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + lastSnapshot = null; + paintSnapshot(); + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ConsoleDialog.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ConsoleDialog.java new file mode 100644 index 0000000..c72fb18 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ConsoleDialog.java @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.*; +import java.awt.*; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class ConsoleDialog extends JDialog { + private JPanel consoleDialogContentPane; + private JPanel buttonsPanel; + private ConsoleScrollPane scrollPane; + private JButton okButton; + private JMenu editMenu; + private JMenuItem editCopyMenuItem; + private JMenuBar consoleDialogMenuBar; + private final EventHandler eventHandler = new EventHandler(); + + private class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (e.getSource() == ConsoleDialog.this.getOkButton() || e.getSource() == getConsoleDialogContentPane()) { + okButtonActionPerformed(); + } + if (e.getSource() == getEditCopyMenuItem()) { + editCopyActionPerformed(); + } + } + } + + public ConsoleDialog() { + super(); + initialize(); + } + + public ConsoleDialog(Frame owner, String title, boolean modal) { + super(owner, title, modal); + initialize(); + } + + public void append(String text) { + getScrollPane().append(text); + } + + public void editCopyActionPerformed() { + StringSelection ss; + String s = getScrollPane().getSelectedText(); + + if (s == null) { + s = getScrollPane().getText(); + } + ss = new StringSelection(s); + Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null); + } + + private JPanel getButtonsPanel() { + if (buttonsPanel == null) { + buttonsPanel = new JPanel(); + buttonsPanel.setPreferredSize(new Dimension(100, 30)); + buttonsPanel.setLayout(new GridBagLayout()); + buttonsPanel.setMinimumSize(new Dimension(20, 20)); + buttonsPanel.setMaximumSize(new Dimension(1000, 30)); + + GridBagConstraints constraintsOKButton = new GridBagConstraints(); + + constraintsOKButton.gridx = 1; + constraintsOKButton.gridy = 1; + constraintsOKButton.ipadx = 34; + constraintsOKButton.insets = new Insets(2, 173, 3, 168); + getButtonsPanel().add(getOkButton(), constraintsOKButton); + } + return buttonsPanel; + } + + private JPanel getConsoleDialogContentPane() { + if (consoleDialogContentPane == null) { + consoleDialogContentPane = new JPanel(); + consoleDialogContentPane.setLayout(new BorderLayout()); + consoleDialogContentPane.add(getButtonsPanel(), "South"); + consoleDialogContentPane.add(getScrollPane(), "Center"); + consoleDialogContentPane.registerKeyboardAction(eventHandler, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), + JComponent.WHEN_FOCUSED); + } + return consoleDialogContentPane; + } + + public JMenuBar getConsoleDialogMenuBar() { + if (consoleDialogMenuBar == null) { + consoleDialogMenuBar = new JMenuBar(); + consoleDialogMenuBar.add(getEditMenu()); + } + return consoleDialogMenuBar; + } + + public JMenuItem getEditCopyMenuItem() { + if (editCopyMenuItem == null) { + editCopyMenuItem = new JMenuItem("Copy"); + editCopyMenuItem.addActionListener(eventHandler); + } + return editCopyMenuItem; + } + + public JMenu getEditMenu() { + if (editMenu == null) { + editMenu = new JMenu("Edit"); + editMenu.add(getEditCopyMenuItem()); + } + return editMenu; + } + + public JButton getOkButton() { + if (okButton == null) { + okButton = new JButton(); + okButton.setText("OK"); + okButton.addActionListener(eventHandler); + } + return okButton; + } + + private ConsoleScrollPane getScrollPane() { + if (scrollPane == null) { + scrollPane = new ConsoleScrollPane(); + } + return scrollPane; + } + + private void initialize() { + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setSize(500, 400); + setContentPane(getConsoleDialogContentPane()); + setJMenuBar(getConsoleDialogMenuBar()); + } + + public void okButtonActionPerformed() { + dispose(); + } + + public void processStream(java.io.InputStream in) { + scrollPane.processStream(in); + } + + public void scrollToBottom() { + getScrollPane().scrollToBottom(); + } + + public void setText(String text) { + getScrollPane().setText(text); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ConsoleScrollPane.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ConsoleScrollPane.java new file mode 100644 index 0000000..267d4dd --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ConsoleScrollPane.java @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.*; +import javax.swing.text.DefaultCaret; + +import java.awt.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Pavel Savara (contributor) + */ +@SuppressWarnings("serial") +public class ConsoleScrollPane extends JScrollPane { + + private static final int MAX_ROWS = 500; + private static final String TEXT_TRUNCATED_MSG = "^^^ TEXT TRUNCATED ^^^"; + + private JTextArea textArea; + private int lines; + private int maxRows; + + public ConsoleScrollPane() { + super(); + setViewportView(getTextPane()); + } + + public JTextArea getTextPane() { + if (textArea == null) { + textArea = new JTextArea(); + + textArea.setEditable(false); + textArea.setTabSize(4); + textArea.setBackground(Color.DARK_GRAY); + textArea.setForeground(Color.WHITE); + textArea.setBounds(0, 0, 1000, 1000); + textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); + + // Make sure the caret is not reset every time text is updated, meaning that + // the view will not reset it's position until we want it to. + ((DefaultCaret) textArea.getCaret()).setUpdatePolicy(DefaultCaret.NEVER_UPDATE); + } + return textArea; + } + + public void append(String str) { + // Return if the string is null or empty + if (str == null || str.length() == 0) { + return; + } + // Append the new string to the text pane + getTextPane().append(str); + + // Count number of new lines, i.e. lines ended with '\n' + int numNewLines = str.replaceAll("[^\\n]", "").length(); + + // Increment the current number of lines with the new lines + lines += numNewLines; + + // Calculate number lines exceeded compared to the max. number of lines + int linesExceeded = lines - MAX_ROWS; + + // Check if we exceeded the number of max. lines + if (linesExceeded > 0) { + // We use a rolling buffer so that the oldest lines are removed first. + // Remove the number of lines we are exceeding in the beginning of the contained text. + + // Cut down the number of lines to max. number of lines + lines = MAX_ROWS; + + // Find the index where to cut the number of exceeding lines in the beginning of the text + String text = getText(); + int cutIndex = -1; + + for (int c = 0; c < linesExceeded; c++) { + cutIndex = text.indexOf('\n', cutIndex + 1); + } + // Replace the first lines of the contained text till the cut index + textArea.replaceRange(null, 0, cutIndex + 1); + + // Replace first line with a message that text has been truncated + textArea.replaceRange(TEXT_TRUNCATED_MSG, 0, getText().indexOf('\n')); + } + + // Set the max. number of lines text pane + maxRows = Math.max(maxRows, lines); + textArea.setRows(maxRows); + } + + public String getSelectedText() { + return getTextPane().getSelectedText(); + } + + public String getText() { + return getTextPane().getText(); + } + + public void setText(String t) { + // Return if the string is null or empty + if (t == null || t.length() == 0) { + t = null; + lines = 0; + maxRows = 0; + } else { + // Calculate and set the new number of lines for the text pane + lines = t.replaceAll("[^\\n]", "").length(); + + // Calculate number lines exceeded compared to the max. number of lines + int linesExceeded = lines - MAX_ROWS; + + // Check if we exceeded the number of max. lines + if (linesExceeded > 0) { + // We use a rolling buffer so that the oldest lines are removed first. + // Remove the number of lines we are exceeding in the beginning of the contained text. + + // Cut down the number of lines to max. number of lines + lines = MAX_ROWS; + + // Find the index where to cut the number of exceeding lines in the beginning of the text + int index = -1; + + for (int c = 0; c < linesExceeded; c++) { + index = t.indexOf('\n', index + 1); + } + // Replace the first lines of the contained text till the cut index + t = t.substring(index + 1); + + // Replace first line with a message that text has been truncated + t = TEXT_TRUNCATED_MSG + t.substring(t.indexOf('\n') + 1); + } + } + // Set the text on the text pane + textArea.setText(t); + + // Set the max. number of lines text pane + maxRows = Math.max(maxRows, lines); + textArea.setRows(maxRows); + } + + public void processStream(InputStream input) { + BufferedReader br = new BufferedReader(new InputStreamReader(input)); + String line; + + try { + while ((line = br.readLine()) != null) { + append(line + "\n"); + } + } catch (IOException e) { + append("SYSTEM: IOException: " + e); + } + scrollToBottom(); + } + + public void scrollToBottom() { + textArea.setCaretPosition(textArea.getDocument().getLength()); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/MenuBar.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/MenuBar.java new file mode 100644 index 0000000..ea9e7ab --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/MenuBar.java @@ -0,0 +1,939 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.host.ICpuManager; +import net.sf.robocode.recording.BattleRecordFormat; +import net.sf.robocode.recording.IRecordManager; +import net.sf.robocode.serialization.SerializableOptions; +import net.sf.robocode.settings.ISettingsListener; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.IWindowManagerExt; +import net.sf.robocode.ui.editor.IRobocodeEditor; +import static net.sf.robocode.ui.util.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; + +import javax.swing.*; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + + +/** + * Handles menu display and interaction for Robocode. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Matthew Reeder (contributor) + * @author Luis Crespo (contributor) + */ +@SuppressWarnings("serial") +public class MenuBar extends JMenuBar { + + // Battle menu + private JMenu battleMenu; + private JMenuItem battleNewMenuItem; + private JMenuItem battleOpenMenuItem; + private JMenuItem battleSaveMenuItem; + private JMenuItem battleSaveAsMenuItem; + private JMenuItem battleExitMenuItem; + private JMenuItem battleOpenRecordMenuItem; + private JMenuItem battleSaveRecordAsMenuItem; + private JMenuItem battleExportRecordMenuItem; + private JMenuItem battleImportRecordMenuItem; + private JMenuItem battleTakeScreenshotMenuItem; + + // Robot menu + private JMenu robotMenu; + private JMenuItem robotEditorMenuItem; + private JMenuItem robotImportMenuItem; + private JMenuItem robotPackagerMenuItem; + private JMenuItem robotCreateTeamMenuItem; + + // Options menu + private JMenu optionsMenu; + private JMenuItem optionsPreferencesMenuItem; + private JMenuItem optionsFitWindowMenuItem; + private JCheckBoxMenuItem optionsShowRankingCheckBoxMenuItem; + private JMenuItem optionsRecalculateCpuConstantMenuItem; + private JMenuItem optionsCleanRobotCacheMenuItem; + + // Help Menu + private JMenu helpMenu; + private JMenuItem helpReadMeMenuItem; + private JMenuItem helpOnlineHelpMenuItem; + private JMenuItem helpCheckForNewVersionMenuItem; + private JMenuItem helpVersionsTxtMenuItem; + private JMenuItem helpRobocodeApiMenuItem; + private JMenuItem helpJavaDocumentationMenuItem; + private JMenuItem helpFaqMenuItem; + private JMenuItem helpAboutMenuItem; + private JMenuItem helpRobocodeMenuItem; + private JMenuItem helpRoboWikiMenuItem; + private JMenuItem helpGoogleGroupRobocodeMenuItem; + private JMenuItem helpRobocodeRepositoryMenuItem; + + private class EventHandler implements ActionListener, MenuListener { + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + MenuBar mb = MenuBar.this; + + // Battle menu + if (source == mb.getBattleNewMenuItem()) { + battleNewActionPerformed(); + } else if (source == mb.getBattleOpenMenuItem()) { + battleOpenActionPerformed(); + } else if (source == mb.getBattleSaveMenuItem()) { + battleSaveActionPerformed(); + } else if (source == mb.getBattleSaveAsMenuItem()) { + battleSaveAsActionPerformed(); + } else if (source == mb.getBattleOpenRecordMenuItem()) { + battleOpenRecordActionPerformed(); + } else if (source == mb.getBattleImportRecordMenuItem()) { + battleImportRecordActionPerformed(); + } else if (source == mb.getBattleSaveRecordAsMenuItem()) { + battleSaveRecordAsActionPerformed(); + } else if (source == mb.getBattleExportRecordMenuItem()) { + battleExportRecordActionPerformed(); + } else if (source == mb.getBattleTakeScreenshotMenuItem()) { + battleTakeScreenshotActionPerformed(); + } else if (source == mb.getBattleExitMenuItem()) { + battleExitActionPerformed(); + + // Robot Editor menu + } else if (source == mb.getRobotEditorMenuItem()) { + robotEditorActionPerformed(); + } else if (source == mb.getRobotImportMenuItem()) { + robotImportActionPerformed(); + } else if (source == mb.getRobotPackagerMenuItem()) { + robotPackagerActionPerformed(); + + // Team / Create Team menu + } else if (source == mb.getRobotCreateTeamMenuItem()) { + teamCreateTeamActionPerformed(); + + // Options / Preferences menu + } else if (source == mb.getOptionsPreferencesMenuItem()) { + optionsPreferencesActionPerformed(); + } else if (source == mb.getOptionsFitWindowMenuItem()) { + optionsFitWindowActionPerformed(); + } else if (source == mb.getOptionsShowRankingCheckBoxMenuItem()) { + optionsShowRankingActionPerformed(); + } else if (source == mb.getOptionsRecalculateCpuConstantMenuItem()) { + optionsRecalculateCpuConstantPerformed(); + } else if (source == mb.getOptionsCleanRobotCacheMenuItem()) { + optionsCleanRobotCachePerformed(); + + // Help menu + } else if (source == mb.getReadMeMenuItem()) { + helpReadMeActionPerformed(); + } else if (source == mb.getHelpOnlineHelpMenuItem()) { + helpOnlineHelpActionPerformed(); + } else if (source == mb.getHelpRobocodeApiMenuItem()) { + helpRobocodeApiActionPerformed(); + } else if (source == mb.getHelpJavaDocumentationMenuItem()) { + helpJavaDocumentationActionPerformed(); + } else if (source == mb.getHelpFaqMenuItem()) { + helpFaqActionPerformed(); + } else if (source == mb.getHelpRobocodeMenuItem()) { + helpRobocodeHomeMenuItemActionPerformed(); + } else if (source == mb.getHelpRoboWikiMenuItem()) { + helpRoboWikiMenuItemActionPerformed(); + } else if (source == mb.getHelpGoogleGroupRobocodeMenuItem()) { + helpGoogleGroupRobocodeActionPerformed(); + } else if (source == mb.getHelpRobocodeRepositoryMenuItem()) { + helpRobocodeRepositoryActionPerformed(); + } else if (source == mb.getHelpCheckForNewVersionMenuItem()) { + helpCheckForNewVersionActionPerformed(); + } else if (source == mb.getHelpVersionsTxtMenuItem()) { + helpVersionsTxtActionPerformed(); + } else if (source == mb.getHelpAboutMenuItem()) { + helpAboutActionPerformed(); + } + } + + public void menuDeselected(MenuEvent e) { + battleManager.resumeBattle(); + } + + public void menuSelected(MenuEvent e) { + battleManager.pauseBattle(); + } + + public void menuCanceled(MenuEvent e) {} + } + + public final MenuBar.EventHandler eventHandler = new EventHandler(); + + private RobocodeFrame robocodeFrame; + private final ISettingsManager properties; + private final IWindowManagerExt windowManager; + private final IBattleManager battleManager; + private final IRecordManager recordManager; + private final ICpuManager cpuManager; + + public MenuBar(ISettingsManager properties, + IWindowManagerExt windowManager, + IBattleManager battleManager, + IRecordManager recordManager, + ICpuManager cpuManager) { + this.properties = properties; + this.windowManager = windowManager; + this.battleManager = battleManager; + this.recordManager = recordManager; + this.cpuManager = cpuManager; + + // FNL: Make sure that menus are heavy-weight components so that the menus are not painted + // behind the BattleView which is a heavy-weight component. This must be done before + // adding any menu to the menubar. + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + + add(getBattleMenu()); + add(getRobotMenu()); + add(getOptionsMenu()); + add(getHelpMenu()); + } + + public void setup(RobocodeFrame robocodeFrame) { + this.robocodeFrame = robocodeFrame; + } + + private void battleExitActionPerformed() { + robocodeFrame.dispose(); + } + + /** + * Handle battleNew menu item action + */ + private void battleNewActionPerformed() { + windowManager.showNewBattleDialog(battleManager.getBattleProperties()); + } + + private void battleOpenActionPerformed() { + try { + battleManager.pauseBattle(); + + String path = windowManager.showBattleOpenDialog(".battle", "Battles"); + if (path != null) { + battleManager.setBattleFilename(path); + windowManager.showNewBattleDialog(battleManager.loadBattleProperties()); + } + } finally { + battleManager.resumeBattle(); + } + } + + private void battleSaveActionPerformed() { + try { + battleManager.pauseBattle(); + String path = battleManager.getBattleFilename(); + + if (path == null) { + path = windowManager.saveBattleDialog(battleManager.getBattlePath(), ".battle", "Battles"); + } + if (path != null) { + battleManager.setBattleFilename(path); + battleManager.saveBattleProperties(); + } + } finally { + battleManager.resumeBattle(); + } + } + + private void battleSaveAsActionPerformed() { + try { + battleManager.pauseBattle(); + + String path = windowManager.saveBattleDialog(battleManager.getBattlePath(), ".battle", "Battles"); + + if (path != null) { + battleManager.setBattleFilename(path); + battleManager.saveBattleProperties(); + } + } finally { + battleManager.resumeBattle(); + } + } + + private void battleOpenRecordActionPerformed() { + try { + battleManager.pauseBattle(); + + String path = windowManager.showBattleOpenDialog(".br", "Records"); + + if (path != null) { + battleManager.stop(true); + + robocodeFrame.getReplayButton().setVisible(true); + robocodeFrame.getReplayButton().setEnabled(true); + + getBattleSaveRecordAsMenuItem().setEnabled(true); + getBattleExportRecordMenuItem().setEnabled(true); + + try { + robocodeFrame.setBusyPointer(true); + recordManager.loadRecord(path, BattleRecordFormat.BINARY_ZIP); + } finally { + robocodeFrame.setBusyPointer(false); + } + battleManager.replay(); + } + } finally { + battleManager.resumeBattle(); + } + } + + private void battleImportRecordActionPerformed() { + try { + battleManager.pauseBattle(); + + String path = windowManager.showBattleOpenDialog(".br.xml", "XML Records"); + + if (path != null) { + battleManager.stop(true); + + robocodeFrame.getReplayButton().setVisible(true); + robocodeFrame.getReplayButton().setEnabled(true); + + getBattleSaveRecordAsMenuItem().setEnabled(true); + getBattleExportRecordMenuItem().setEnabled(true); + + try { + robocodeFrame.setBusyPointer(true); + recordManager.loadRecord(path, BattleRecordFormat.XML); + } finally { + robocodeFrame.setBusyPointer(false); + } + battleManager.replay(); + } + } finally { + battleManager.resumeBattle(); + } + } + + private void battleSaveRecordAsActionPerformed() { + if (recordManager.hasRecord()) { + try { + battleManager.pauseBattle(); + + String path = windowManager.saveBattleDialog(battleManager.getBattlePath(), ".br", "Records"); + + if (path != null) { + try { + robocodeFrame.setBusyPointer(true); + recordManager.saveRecord(path, BattleRecordFormat.BINARY_ZIP, new SerializableOptions(false)); + } finally { + robocodeFrame.setBusyPointer(false); + } + } + } finally { + battleManager.resumeBattle(); + } + } + } + + private void battleExportRecordActionPerformed() { + if (recordManager.hasRecord()) { + try { + battleManager.pauseBattle(); + + String path = windowManager.saveBattleDialog(battleManager.getBattlePath(), ".br.xml", "XML Records"); + + if (path != null) { + try { + robocodeFrame.setBusyPointer(true); + recordManager.saveRecord(path, BattleRecordFormat.XML, new SerializableOptions(false)); + } finally { + robocodeFrame.setBusyPointer(false); + } + } + } finally { + battleManager.resumeBattle(); + } + } + } + + private void battleTakeScreenshotActionPerformed() { + robocodeFrame.takeScreenshot(); + } + + private JMenuItem getBattleExitMenuItem() { + if (battleExitMenuItem == null) { + battleExitMenuItem = new JMenuItem(); + battleExitMenuItem.setText("Exit"); + battleExitMenuItem.setMnemonic('x'); + battleExitMenuItem.setDisplayedMnemonicIndex(1); + battleExitMenuItem.addActionListener(eventHandler); + } + return battleExitMenuItem; + } + + public JMenu getBattleMenu() { + if (battleMenu == null) { + battleMenu = new JMenu(); + battleMenu.setText("Battle"); + battleMenu.setMnemonic('B'); + battleMenu.add(getBattleNewMenuItem()); + battleMenu.add(getBattleOpenMenuItem()); + battleMenu.add(new JSeparator()); + battleMenu.add(getBattleSaveMenuItem()); + battleMenu.add(getBattleSaveAsMenuItem()); + battleMenu.add(new JSeparator()); + battleMenu.add(getBattleOpenRecordMenuItem()); + battleMenu.add(getBattleSaveRecordAsMenuItem()); + battleMenu.add(getBattleImportRecordMenuItem()); + battleMenu.add(getBattleExportRecordMenuItem()); + battleMenu.add(new JSeparator()); + battleMenu.add(getBattleTakeScreenshotMenuItem()); + battleMenu.add(new JSeparator()); + battleMenu.add(getBattleExitMenuItem()); + battleMenu.addMenuListener(eventHandler); + } + return battleMenu; + } + + private JMenuItem getBattleNewMenuItem() { + if (battleNewMenuItem == null) { + battleNewMenuItem = new JMenuItem(); + battleNewMenuItem.setText("New"); + battleNewMenuItem.setMnemonic('N'); + battleNewMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, MENU_SHORTCUT_KEY_MASK, false)); + battleNewMenuItem.addActionListener(eventHandler); + } + return battleNewMenuItem; + } + + private JMenuItem getBattleOpenMenuItem() { + if (battleOpenMenuItem == null) { + battleOpenMenuItem = new JMenuItem(); + battleOpenMenuItem.setText("Open"); + battleOpenMenuItem.setMnemonic('O'); + battleOpenMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, MENU_SHORTCUT_KEY_MASK, false)); + battleOpenMenuItem.addActionListener(eventHandler); + } + return battleOpenMenuItem; + } + + public JMenuItem getBattleSaveAsMenuItem() { + if (battleSaveAsMenuItem == null) { + battleSaveAsMenuItem = new JMenuItem(); + battleSaveAsMenuItem.setText("Save As"); + battleSaveAsMenuItem.setMnemonic('A'); + battleSaveAsMenuItem.setDisplayedMnemonicIndex(5); + battleSaveAsMenuItem.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_SHORTCUT_KEY_MASK | InputEvent.SHIFT_MASK, false)); + battleSaveAsMenuItem.setEnabled(false); + battleSaveAsMenuItem.addActionListener(eventHandler); + } + return battleSaveAsMenuItem; + } + + public JMenuItem getBattleSaveMenuItem() { + if (battleSaveMenuItem == null) { + battleSaveMenuItem = new JMenuItem(); + battleSaveMenuItem.setText("Save"); + battleSaveMenuItem.setMnemonic('S'); + battleSaveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, MENU_SHORTCUT_KEY_MASK, false)); + battleSaveMenuItem.setEnabled(false); + battleSaveMenuItem.addActionListener(eventHandler); + } + return battleSaveMenuItem; + } + + private JMenuItem getBattleOpenRecordMenuItem() { + if (battleOpenRecordMenuItem == null) { + battleOpenRecordMenuItem = new JMenuItem(); + battleOpenRecordMenuItem.setText("Open Record"); + battleOpenRecordMenuItem.setMnemonic('d'); + battleOpenRecordMenuItem.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_O, MENU_SHORTCUT_KEY_MASK | InputEvent.SHIFT_MASK, false)); + battleOpenRecordMenuItem.addActionListener(eventHandler); + } + return battleOpenRecordMenuItem; + } + + private JMenuItem getBattleImportRecordMenuItem() { + if (battleImportRecordMenuItem == null) { + battleImportRecordMenuItem = new JMenuItem(); + battleImportRecordMenuItem.setText("Import XML Record"); + battleImportRecordMenuItem.setMnemonic('I'); + battleImportRecordMenuItem.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_I, MENU_SHORTCUT_KEY_MASK, false)); + battleImportRecordMenuItem.addActionListener(eventHandler); + } + return battleImportRecordMenuItem; + } + + public JMenuItem getBattleSaveRecordAsMenuItem() { + if (battleSaveRecordAsMenuItem == null) { + battleSaveRecordAsMenuItem = new JMenuItem(); + battleSaveRecordAsMenuItem.setText("Save Record"); + battleSaveRecordAsMenuItem.setMnemonic('R'); + battleSaveRecordAsMenuItem.setDisplayedMnemonicIndex(5); + battleSaveRecordAsMenuItem.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK, false)); + battleSaveRecordAsMenuItem.setEnabled(false); + battleSaveRecordAsMenuItem.addActionListener(eventHandler); + + ISettingsManager props = properties; + + props.addPropertyListener( + new ISettingsListener() { + public void settingChanged(String property) { + if (property.equals(ISettingsManager.OPTIONS_COMMON_ENABLE_REPLAY_RECORDING)) { + final boolean canReplayRecord = recordManager.hasRecord(); + final boolean enableSaveRecord = properties.getOptionsCommonEnableReplayRecording() + & canReplayRecord; + + battleSaveRecordAsMenuItem.setEnabled(enableSaveRecord); + } + } + }); + } + return battleSaveRecordAsMenuItem; + } + + public JMenuItem getBattleExportRecordMenuItem() { + if (battleExportRecordMenuItem == null) { + battleExportRecordMenuItem = new JMenuItem(); + battleExportRecordMenuItem.setText("Export XML Record"); + battleExportRecordMenuItem.setMnemonic('E'); + battleExportRecordMenuItem.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_X, MENU_SHORTCUT_KEY_MASK, false)); + battleExportRecordMenuItem.setEnabled(false); + battleExportRecordMenuItem.addActionListener(eventHandler); + + ISettingsManager props = properties; + + props.addPropertyListener( + new ISettingsListener() { + public void settingChanged(String property) { + if (property.equals(ISettingsManager.OPTIONS_COMMON_ENABLE_REPLAY_RECORDING)) { + final boolean canReplayRecord = recordManager.hasRecord(); + final boolean enableSaveRecord = properties.getOptionsCommonEnableReplayRecording() + & canReplayRecord; + + battleExportRecordMenuItem.setEnabled(enableSaveRecord); + } + } + }); + } + return battleExportRecordMenuItem; + } + + private JMenuItem getBattleTakeScreenshotMenuItem() { + if (battleTakeScreenshotMenuItem == null) { + battleTakeScreenshotMenuItem = new JMenuItem(); + battleTakeScreenshotMenuItem.setText("Take Screenshot"); + battleTakeScreenshotMenuItem.setMnemonic('T'); + battleTakeScreenshotMenuItem.setAccelerator( + KeyStroke.getKeyStroke(KeyEvent.VK_T, MENU_SHORTCUT_KEY_MASK, false)); + battleTakeScreenshotMenuItem.addActionListener(eventHandler); + } + return battleTakeScreenshotMenuItem; + } + + private JMenuItem getHelpAboutMenuItem() { + if (helpAboutMenuItem == null) { + helpAboutMenuItem = new JMenuItem(); + helpAboutMenuItem.setText("About"); + helpAboutMenuItem.setMnemonic('A'); + helpAboutMenuItem.addActionListener(eventHandler); + } + return helpAboutMenuItem; + } + + private JMenuItem getHelpCheckForNewVersionMenuItem() { + if (helpCheckForNewVersionMenuItem == null) { + helpCheckForNewVersionMenuItem = new JMenuItem(); + helpCheckForNewVersionMenuItem.setText("Check for new version"); + helpCheckForNewVersionMenuItem.setMnemonic('C'); + helpCheckForNewVersionMenuItem.addActionListener(eventHandler); + } + return helpCheckForNewVersionMenuItem; + } + + @Override + public JMenu getHelpMenu() { + if (helpMenu == null) { + helpMenu = new JMenu(); + helpMenu.setText("Help"); + helpMenu.setMnemonic('H'); + helpMenu.add(getReadMeMenuItem()); + helpMenu.add(getHelpRobocodeApiMenuItem()); + helpMenu.add(getHelpJavaDocumentationMenuItem()); + helpMenu.add(new JSeparator()); + helpMenu.add(getHelpOnlineHelpMenuItem()); + helpMenu.add(getHelpRoboWikiMenuItem()); + helpMenu.add(getHelpGoogleGroupRobocodeMenuItem()); + helpMenu.add(getHelpFaqMenuItem()); + helpMenu.add(new JSeparator()); + helpMenu.add(getHelpRobocodeMenuItem()); + helpMenu.add(getHelpRobocodeRepositoryMenuItem()); + helpMenu.add(new JSeparator()); + helpMenu.add(getHelpCheckForNewVersionMenuItem()); + helpMenu.add(getHelpVersionsTxtMenuItem()); + helpMenu.add(new JSeparator()); + helpMenu.add(getHelpAboutMenuItem()); + helpMenu.addMenuListener(eventHandler); + } + return helpMenu; + } + + private JMenuItem getHelpFaqMenuItem() { + if (helpFaqMenuItem == null) { + helpFaqMenuItem = new JMenuItem(); + helpFaqMenuItem.setText("Robocode FAQ"); + helpFaqMenuItem.setMnemonic('F'); + helpFaqMenuItem.setDisplayedMnemonicIndex(9); + helpFaqMenuItem.addActionListener(eventHandler); + } + return helpFaqMenuItem; + } + + private JMenuItem getReadMeMenuItem() { + if (helpReadMeMenuItem == null) { + helpReadMeMenuItem = new JMenuItem(); + helpReadMeMenuItem.setText("ReadMe"); + helpReadMeMenuItem.setMnemonic('M'); + helpReadMeMenuItem.setDisplayedMnemonicIndex(4); + helpReadMeMenuItem.addActionListener(eventHandler); + } + return helpReadMeMenuItem; + } + + private JMenuItem getHelpOnlineHelpMenuItem() { + if (helpOnlineHelpMenuItem == null) { + helpOnlineHelpMenuItem = new JMenuItem(); + helpOnlineHelpMenuItem.setText("Online help"); + helpOnlineHelpMenuItem.setMnemonic('O'); + helpOnlineHelpMenuItem.addActionListener(eventHandler); + } + return helpOnlineHelpMenuItem; + } + + private JMenuItem getHelpVersionsTxtMenuItem() { + if (helpVersionsTxtMenuItem == null) { + helpVersionsTxtMenuItem = new JMenuItem(); + helpVersionsTxtMenuItem.setText("Version info"); + helpVersionsTxtMenuItem.setMnemonic('V'); + helpVersionsTxtMenuItem.addActionListener(eventHandler); + } + return helpVersionsTxtMenuItem; + } + + private JMenuItem getHelpRobocodeApiMenuItem() { + if (helpRobocodeApiMenuItem == null) { + helpRobocodeApiMenuItem = new JMenuItem(); + helpRobocodeApiMenuItem.setText("Robocode API"); + helpRobocodeApiMenuItem.setMnemonic('I'); + helpRobocodeApiMenuItem.setDisplayedMnemonicIndex(11); + helpRobocodeApiMenuItem.addActionListener(eventHandler); + } + return helpRobocodeApiMenuItem; + } + + private JMenuItem getHelpRobocodeMenuItem() { + if (helpRobocodeMenuItem == null) { + helpRobocodeMenuItem = new JMenuItem(); + helpRobocodeMenuItem.setText("Robocode home page"); + helpRobocodeMenuItem.setMnemonic('H'); + helpRobocodeMenuItem.setDisplayedMnemonicIndex(9); + helpRobocodeMenuItem.addActionListener(eventHandler); + } + return helpRobocodeMenuItem; + } + + private JMenuItem getHelpJavaDocumentationMenuItem() { + if (helpJavaDocumentationMenuItem == null) { + helpJavaDocumentationMenuItem = new JMenuItem(); + helpJavaDocumentationMenuItem.setText("Java 6 documentation"); + helpJavaDocumentationMenuItem.setMnemonic('J'); + helpJavaDocumentationMenuItem.addActionListener(eventHandler); + } + return helpJavaDocumentationMenuItem; + } + + private JMenuItem getHelpRoboWikiMenuItem() { + if (helpRoboWikiMenuItem == null) { + helpRoboWikiMenuItem = new JMenuItem(); + helpRoboWikiMenuItem.setText("RoboWiki site"); + helpRoboWikiMenuItem.setMnemonic('W'); + helpRoboWikiMenuItem.setDisplayedMnemonicIndex(4); + helpRoboWikiMenuItem.addActionListener(eventHandler); + } + return helpRoboWikiMenuItem; + } + + private JMenuItem getHelpGoogleGroupRobocodeMenuItem() { + if (helpGoogleGroupRobocodeMenuItem == null) { + helpGoogleGroupRobocodeMenuItem = new JMenuItem(); + helpGoogleGroupRobocodeMenuItem.setText("Google Group for Robocode"); + helpGoogleGroupRobocodeMenuItem.setMnemonic('Y'); + helpGoogleGroupRobocodeMenuItem.addActionListener(eventHandler); + } + return helpGoogleGroupRobocodeMenuItem; + } + + private JMenuItem getHelpRobocodeRepositoryMenuItem() { + if (helpRobocodeRepositoryMenuItem == null) { + helpRobocodeRepositoryMenuItem = new JMenuItem(); + helpRobocodeRepositoryMenuItem.setText("Robocode Repository"); + helpRobocodeRepositoryMenuItem.setMnemonic('R'); + helpRobocodeRepositoryMenuItem.setDisplayedMnemonicIndex(9); + helpRobocodeRepositoryMenuItem.addActionListener(eventHandler); + } + return helpRobocodeRepositoryMenuItem; + } + + private JMenuItem getOptionsFitWindowMenuItem() { + if (optionsFitWindowMenuItem == null) { + optionsFitWindowMenuItem = new JMenuItem(); + optionsFitWindowMenuItem.setText("Default window size"); + optionsFitWindowMenuItem.setMnemonic('D'); + optionsFitWindowMenuItem.addActionListener(eventHandler); + } + return optionsFitWindowMenuItem; + } + + public JCheckBoxMenuItem getOptionsShowRankingCheckBoxMenuItem() { + if (optionsShowRankingCheckBoxMenuItem == null) { + optionsShowRankingCheckBoxMenuItem = new JCheckBoxMenuItem(); + optionsShowRankingCheckBoxMenuItem.setText("Show current rankings"); + optionsShowRankingCheckBoxMenuItem.setMnemonic('r'); + optionsShowRankingCheckBoxMenuItem.setDisplayedMnemonicIndex(13); + optionsShowRankingCheckBoxMenuItem.addActionListener(eventHandler); + optionsShowRankingCheckBoxMenuItem.setEnabled(false); + } + return optionsShowRankingCheckBoxMenuItem; + } + + private JMenuItem getOptionsRecalculateCpuConstantMenuItem() { + if (optionsRecalculateCpuConstantMenuItem == null) { + optionsRecalculateCpuConstantMenuItem = new JMenuItem(); + optionsRecalculateCpuConstantMenuItem.setText("Recalculate CPU constant"); + optionsRecalculateCpuConstantMenuItem.setMnemonic('e'); + optionsRecalculateCpuConstantMenuItem.setDisplayedMnemonicIndex(1); + optionsRecalculateCpuConstantMenuItem.addActionListener(eventHandler); + } + return optionsRecalculateCpuConstantMenuItem; + } + + private JMenuItem getOptionsCleanRobotCacheMenuItem() { + if (optionsCleanRobotCacheMenuItem == null) { + optionsCleanRobotCacheMenuItem = new JMenuItem(); + optionsCleanRobotCacheMenuItem.setText("Clean robot cache"); + optionsCleanRobotCacheMenuItem.setMnemonic('C'); + optionsCleanRobotCacheMenuItem.addActionListener(eventHandler); + } + return optionsCleanRobotCacheMenuItem; + } + + private JMenu getOptionsMenu() { + if (optionsMenu == null) { + optionsMenu = new JMenu(); + optionsMenu.setText("Options"); + optionsMenu.setMnemonic('O'); + optionsMenu.add(getOptionsPreferencesMenuItem()); + optionsMenu.add(getOptionsFitWindowMenuItem()); + optionsMenu.add(new JSeparator()); + optionsMenu.add(getOptionsShowRankingCheckBoxMenuItem()); + optionsMenu.add(new JSeparator()); + optionsMenu.add(getOptionsRecalculateCpuConstantMenuItem()); + optionsMenu.add(getOptionsCleanRobotCacheMenuItem()); + optionsMenu.addMenuListener(eventHandler); + } + return optionsMenu; + } + + private JMenuItem getOptionsPreferencesMenuItem() { + if (optionsPreferencesMenuItem == null) { + optionsPreferencesMenuItem = new JMenuItem(); + optionsPreferencesMenuItem.setText("Preferences"); + optionsPreferencesMenuItem.setMnemonic('P'); + optionsPreferencesMenuItem.addActionListener(eventHandler); + } + return optionsPreferencesMenuItem; + } + + private JMenuItem getRobotEditorMenuItem() { + if (robotEditorMenuItem == null) { + robotEditorMenuItem = new JMenuItem(); + robotEditorMenuItem.setText("Source Editor"); + robotEditorMenuItem.setMnemonic('E'); + robotEditorMenuItem.setVisible(net.sf.robocode.core.Container.getComponent(IRobocodeEditor.class) != null); + robotEditorMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, MENU_SHORTCUT_KEY_MASK, false)); + robotEditorMenuItem.addActionListener(eventHandler); + } + return robotEditorMenuItem; + } + + private JMenuItem getRobotImportMenuItem() { + if (robotImportMenuItem == null) { + robotImportMenuItem = new JMenuItem(); + robotImportMenuItem.setText("Import robot or team"); + robotImportMenuItem.setMnemonic('I'); + robotImportMenuItem.addActionListener(eventHandler); + } + return robotImportMenuItem; + } + + public JMenu getRobotMenu() { + if (robotMenu == null) { + robotMenu = new JMenu(); + robotMenu.setText("Robot"); + robotMenu.setMnemonic('R'); + robotMenu.add(getRobotEditorMenuItem()); + robotMenu.add(new JSeparator()); + robotMenu.add(getRobotImportMenuItem()); + robotMenu.add(getRobotPackagerMenuItem()); + robotMenu.add(new JSeparator()); + robotMenu.add(getRobotCreateTeamMenuItem()); + robotMenu.addMenuListener(eventHandler); + } + return robotMenu; + } + + private JMenuItem getRobotPackagerMenuItem() { + if (robotPackagerMenuItem == null) { + robotPackagerMenuItem = new JMenuItem(); + robotPackagerMenuItem.setText("Package robot or team"); + robotPackagerMenuItem.setMnemonic('P'); + robotPackagerMenuItem.addActionListener(eventHandler); + } + return robotPackagerMenuItem; + } + + private JMenuItem getRobotCreateTeamMenuItem() { + if (robotCreateTeamMenuItem == null) { + robotCreateTeamMenuItem = new JMenuItem(); + robotCreateTeamMenuItem.setText("Create a robot team"); + robotCreateTeamMenuItem.setMnemonic('C'); + robotCreateTeamMenuItem.addActionListener(eventHandler); + } + return robotCreateTeamMenuItem; + } + + private void teamCreateTeamActionPerformed() { + windowManager.showCreateTeamDialog(); + } + + private void helpAboutActionPerformed() { + windowManager.showAboutBox(); + } + + private void helpCheckForNewVersionActionPerformed() { + if (!robocodeFrame.checkForNewVersion(true)) { + WindowUtil.messageError("Unable to check for new version "); + } + } + + private void helpFaqActionPerformed() { + windowManager.showFaq(); + } + + private void helpReadMeActionPerformed() { + windowManager.showReadMe(); + } + + private void helpOnlineHelpActionPerformed() { + windowManager.showOnlineHelp(); + } + + private void helpVersionsTxtActionPerformed() { + windowManager.showVersionsTxt(); + } + + private void helpRobocodeApiActionPerformed() { + windowManager.showHelpApi(); + } + + private void helpRobocodeHomeMenuItemActionPerformed() { + windowManager.showRobocodeHome(); + } + + private void helpJavaDocumentationActionPerformed() { + windowManager.showJavaDocumentation(); + } + + private void helpRoboWikiMenuItemActionPerformed() { + windowManager.showRoboWiki(); + } + + private void helpGoogleGroupRobocodeActionPerformed() { + windowManager.showGoogleGroupRobocode(); + } + + private void helpRobocodeRepositoryActionPerformed() { + windowManager.showRobocodeRepository(); + } + + private void optionsFitWindowActionPerformed() { + JFrame robocodeFrame = windowManager.getRobocodeFrame(); + + robocodeFrame.setSize(robocodeFrame.getPreferredSize()); + WindowUtil.fitWindow(robocodeFrame); + } + + private void optionsShowRankingActionPerformed() { + windowManager.showRankingDialog(getOptionsShowRankingCheckBoxMenuItem().getState()); + } + + private void optionsRecalculateCpuConstantPerformed() { + int ok = JOptionPane.showConfirmDialog(this, "Do you want to recalculate the CPU constant?", + "Recalculate CPU constant", JOptionPane.YES_NO_OPTION); + + if (ok == JOptionPane.YES_OPTION) { + try { + robocodeFrame.setBusyPointer(true); + cpuManager.calculateCpuConstant(); + } finally { + robocodeFrame.setBusyPointer(false); + } + + long cpuConstant = cpuManager.getCpuConstant(); + + JOptionPane.showMessageDialog(this, "CPU constant: " + cpuConstant + " nanoseconds per turn", + "New CPU constant", JOptionPane.INFORMATION_MESSAGE); + } + } + + private void optionsCleanRobotCachePerformed() { + int ok = JOptionPane.showConfirmDialog(this, "Do you want to clean the robot cache?", "Clean Robot Cache", + JOptionPane.YES_NO_OPTION); + + if (ok == JOptionPane.YES_OPTION) { + try { + robocodeFrame.setBusyPointer(true); + net.sf.robocode.cachecleaner.CacheCleaner.clean(); + } finally { + robocodeFrame.setBusyPointer(false); + } + } + } + + private void optionsPreferencesActionPerformed() { + windowManager.showOptionsPreferences(); + } + + private void robotEditorActionPerformed() { + windowManager.showRobocodeEditor(); + } + + private void robotImportActionPerformed() { + windowManager.showImportRobotDialog(); + } + + private void robotPackagerActionPerformed() { + windowManager.showRobotPackager(); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/NewBattleDialog.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/NewBattleDialog.java new file mode 100644 index 0000000..b76dbd8 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/NewBattleDialog.java @@ -0,0 +1,204 @@ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.battle.BattleProperties; +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.core.Container; +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.IWindowManager; +import static net.sf.robocode.ui.util.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; + +import javax.swing.*; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.util.List; + + +@SuppressWarnings("serial") +public class NewBattleDialog extends JDialog implements WizardListener { + + private final static int MAX_ROBOTS = 256; // 64; + private final static int MIN_ROBOTS = 1; + + private final EventHandler eventHandler = new EventHandler(); + + private ISettingsManager settingsManager; + private BattleProperties battleProperties; + + private WizardTabbedPane tabbedPane; + private NewBattleRulesTab battleFieldTab; + + private WizardController wizardController; + + private RobotSelectionPanel robotSelectionPanel; + + private final IBattleManager battleManager; + + public NewBattleDialog(IWindowManager windowManager, IBattleManager battleManager) { + super(windowManager.getRobocodeFrame(), true); + this.battleManager = battleManager; + } + + public void setup(ISettingsManager settingsManager, BattleProperties battleProperties) { // XXX + this.settingsManager = settingsManager; + this.battleProperties = battleProperties; + + robotSelectionPanel = null; + + setTitle("New Battle"); + setPreferredSize(new Dimension(850, 650)); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + + addCancelByEscapeKey(); + + add(createNewBattleDialogPanel()); + } + + + public void cancelButtonActionPerformed() { + dispose(); + } + public void finishButtonActionPerformed() { + if (robotSelectionPanel.getSelectedRobotsCount() > 24) { + if (JOptionPane.showConfirmDialog(this, + "Warning: The battle you are about to start (" + robotSelectionPanel.getSelectedRobotsCount() + + " robots) " + " is very large and will consume a lot of CPU and memory. Do you wish to proceed?", + "Large Battle Warning", + JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE) + == JOptionPane.NO_OPTION) { + return; + } + } + if (robotSelectionPanel.getSelectedRobotsCount() == 1) { + if (JOptionPane.showConfirmDialog(this, + "You have only selected one robot. For normal battles you should select at least 2.\nDo you wish to proceed anyway?", + "Just one robot?", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) + == JOptionPane.NO_OPTION) { + return; + } + } + // Dispose this dialog before starting the battle due to pause/resume battle state + dispose(); + + // Start new battle after the dialog has been disposed and hence has called resumeBattle() + battleManager.startNewBattle(battleProperties, false, false); + } + + private NewBattleRulesTab getBattleFieldTab() { + if (battleFieldTab == null) { + battleFieldTab = new NewBattleRulesTab(); + battleFieldTab.setup(settingsManager, battleProperties); + } + return battleFieldTab; + } + + private JPanel createNewBattleDialogPanel() { + JPanel panel = new JPanel(); + + panel.setLayout(new BorderLayout()); + panel.add(getWizardController(), BorderLayout.SOUTH); + panel.add(getTabbedPane(), BorderLayout.CENTER); + panel.registerKeyboardAction(eventHandler, "Refresh", + KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + return panel; + } + + public List getSelectedRobots() { + return getRobotSelectionPanel().getSelectedRobots(); + } + + private void addCancelByEscapeKey() { + String CANCEL_ACTION_KEY = "CANCEL_ACTION_KEY"; + int noModifiers = 0; + KeyStroke escapeKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, noModifiers, false); + InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + inputMap.put(escapeKey, CANCEL_ACTION_KEY); + AbstractAction cancelAction = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + cancelButtonActionPerformed(); + } + }; + + getRootPane().getActionMap().put(CANCEL_ACTION_KEY, cancelAction); + } + + /** + * Return the wizardController + * + * @return JButton + */ + private WizardController getWizardController() { + if (wizardController == null) { + wizardController = getTabbedPane().getWizardController(); + wizardController.setFinishButtonTextAndMnemonic("Start Battle", 'S', 0); + wizardController.setFocusOnEnabled(true); + } + return wizardController; + } + + /** + * Return the Page property value. + * + * @return JPanel + */ + private RobotSelectionPanel getRobotSelectionPanel() { + if (robotSelectionPanel == null) { + robotSelectionPanel = Container.createComponent(RobotSelectionPanel.class); + robotSelectionPanel.addAncestorListener(eventHandler); + + final boolean ignoreTeamRobots = false; // TODO do we really want to have this !properties.getOptionsTeamShowTeamRobots(); + String selectedRobots = (battleProperties == null) ? "" : battleProperties.getSelectedRobots(); + + robotSelectionPanel.setup(MIN_ROBOTS, MAX_ROBOTS, true, "Select robots for the battle", false, false, false, + false, false, ignoreTeamRobots, selectedRobots); + } + return robotSelectionPanel; + } + + /** + * Return the tabbedPane. + * + * @return JTabbedPane + */ + private WizardTabbedPane getTabbedPane() { + if (tabbedPane == null) { + tabbedPane = new WizardTabbedPane(this); + tabbedPane.insertTab("Robots", null, getRobotSelectionPanel(), null, 0); + tabbedPane.setMnemonicAt(0, KeyEvent.VK_R); + tabbedPane.setDisplayedMnemonicIndexAt(0, 0); + tabbedPane.insertTab("Rules", null, getBattleFieldTab(), null, 1); + tabbedPane.setMnemonicAt(1, KeyEvent.VK_U); + tabbedPane.setDisplayedMnemonicIndexAt(1, 1); + } + return tabbedPane; + } + + private class EventHandler implements AncestorListener, ActionListener { + @Override + public void ancestorAdded(AncestorEvent event) {} + + @Override + public void ancestorRemoved(AncestorEvent event) { + battleProperties.setSelectedRobots(getRobotSelectionPanel().getSelectedRobotsAsString()); + } + + @Override + public void ancestorMoved(AncestorEvent event) {} + + @Override + public void actionPerformed(ActionEvent event) { + if (event.getActionCommand().equals("Refresh")) { + getRobotSelectionPanel().refreshRobotList(true); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/NewBattleRulesTab.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/NewBattleRulesTab.java new file mode 100644 index 0000000..45ee473 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/NewBattleRulesTab.java @@ -0,0 +1,492 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.*; +import javax.swing.GroupLayout.Alignment; +import javax.swing.border.Border; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +import net.sf.robocode.battle.BattleProperties; +import net.sf.robocode.settings.ISettingsManager; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class NewBattleRulesTab extends JPanel { + + private final static int MIN_BATTLEFIELD_SIZE = 400; + private final static int MAX_BATTLEFIELD_SIZE = 5000; + private final static int BATTLEFIELD_STEP_SIZE = 100; + + private ISettingsManager settingsManager; + private BattleProperties battleProperties; + + private final EventHandler eventHandler = new EventHandler(); + + private SizeButton[] predefinedSizeButtons = { + new SizeButton(400, 400), new SizeButton(600, 400), new SizeButton(600, 600), new SizeButton(800, 600), + new SizeButton(800, 800), new SizeButton(1000, 800), new SizeButton(1000, 1000), new SizeButton(1200, 1200), + new SizeButton(2000, 2000), new SizeButton(5000, 5000) + }; + + private final JLabel numberOfRoundsLabel = new JLabel("Number of Rounds:"); + private final JLabel gunCoolingRateLabel = new JLabel("Gun Cooling Rate:"); + private final JLabel inactivityTimeLabel = new JLabel("Inactivity Time:"); + private final JLabel sentryBorderSizeLabel = new JLabel("Sentry Border Size"); + private final JLabel hideEnemyNamesLabel = new JLabel("Hide Enemy Names:"); + + private final JButton restoreDefaultsButton = new JButton("Restore Defaults"); + + private JTextField numberOfRoundsTextField; + private JTextField gunCoolingRateTextField; + private JTextField inactivityTimeTextField; + private JTextField sentryBorderSizeTextField; + private final JCheckBox hideEnemyNamesCheckBox = new JCheckBox(); + + private JSlider battlefieldWidthSlider; + private JSlider battlefieldHeightSlider; + private JLabel battlefieldSizeLabel; + + public NewBattleRulesTab() { + super(); + } + + public void setup(ISettingsManager settingsManager, BattleProperties battleProperties) { + this.settingsManager = settingsManager; + this.battleProperties = battleProperties; + + EventHandler eventHandler = new EventHandler(); + + battlefieldWidthSlider = createBattlefieldSizeSlider(); + battlefieldWidthSlider.setOrientation(SwingConstants.HORIZONTAL); + + battlefieldHeightSlider = createBattlefieldSizeSlider(); + battlefieldHeightSlider.setOrientation(SwingConstants.VERTICAL); + battlefieldHeightSlider.setInverted(true); + + battlefieldSizeLabel = new BattlefieldSizeLabel(); + battlefieldSizeLabel.setHorizontalAlignment(SwingConstants.CENTER); + battlefieldSizeLabel.setMinimumSize(new Dimension(50, 50)); + battlefieldSizeLabel.setMaximumSize(new Dimension(500, 500)); + + battlefieldWidthSlider.addChangeListener(eventHandler); + battlefieldHeightSlider.addChangeListener(eventHandler); + + JPanel rulesPanel = createRulesPanel(); + rulesPanel.addAncestorListener(eventHandler); + + restoreDefaultsButton.addActionListener(eventHandler); + + setLayout(new BorderLayout()); + + add(rulesPanel, BorderLayout.WEST); + add(restoreDefaultsButton, BorderLayout.SOUTH); + add(createBattlefieldSizePanel(), BorderLayout.CENTER); + } + + private JPanel createBattlefieldSizePanel() { + JPanel panel = new JPanel(); + panel.addAncestorListener(eventHandler); + + Border border = BorderFactory.createCompoundBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Battlefield Size"), + BorderFactory.createEmptyBorder(10, 10, 10, 10)); + panel.setBorder(border); + + panel.setLayout(new BorderLayout()); + + JPanel sliderPanel = createBattlefieldSlidersPanel(); + panel.add(sliderPanel, BorderLayout.CENTER); + + JPanel buttonsPanel = createPredefinedSizesPanel(); + panel.add(buttonsPanel, BorderLayout.EAST); + + return panel; + } + + private JPanel createBattlefieldSlidersPanel() { + JPanel panel = new JPanel(); + + GroupLayout layout = new GroupLayout(panel); + panel.setLayout(layout); + + GroupLayout.SequentialGroup leftToRight = layout.createSequentialGroup(); + + GroupLayout.ParallelGroup left = layout.createParallelGroup(); + left.addComponent(battlefieldSizeLabel); + left.addComponent(battlefieldWidthSlider); + leftToRight.addGroup(left); + + GroupLayout.ParallelGroup right = layout.createParallelGroup(); + right.addComponent(battlefieldHeightSlider); + leftToRight.addGroup(right); + + GroupLayout.SequentialGroup topToBottom = layout.createSequentialGroup(); + + GroupLayout.ParallelGroup top = layout.createParallelGroup(); + top.addComponent(battlefieldSizeLabel); + top.addComponent(battlefieldHeightSlider); + topToBottom.addGroup(top); + + GroupLayout.ParallelGroup bottom = layout.createParallelGroup(); + bottom.addComponent(battlefieldWidthSlider); + topToBottom.addGroup(bottom); + + layout.setHorizontalGroup(leftToRight); + layout.setVerticalGroup(topToBottom); + + return panel; + } + + private JPanel createPredefinedSizesPanel() { + JPanel panel = new JPanel(); + + Border border = BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0), + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Predefined Sizes")); + panel.setBorder(border); + + panel.setLayout(new GridLayout(predefinedSizeButtons.length, 1)); + + for (SizeButton button : predefinedSizeButtons) { + panel.add(button); + } + return panel; + } + + private JPanel createRulesPanel() { + JPanel panel = new JPanel(); + + panel.addAncestorListener(new EventHandler()); + panel.setBorder(BorderFactory.createEtchedBorder()); + + GroupLayout layout = new GroupLayout(panel); + layout.setAutoCreateContainerGaps(true); + layout.setAutoCreateGaps(true); + panel.setLayout(layout); + + GroupLayout.SequentialGroup leftToRight = layout.createSequentialGroup(); + + GroupLayout.ParallelGroup left = layout.createParallelGroup(); + left.addComponent(numberOfRoundsLabel); + left.addComponent(gunCoolingRateLabel); + left.addComponent(inactivityTimeLabel); + left.addComponent(sentryBorderSizeLabel); + left.addComponent(hideEnemyNamesLabel); + leftToRight.addGroup(left); + + GroupLayout.ParallelGroup right = layout.createParallelGroup(); + right.addComponent(getNumberOfRoundsTextField()); + right.addComponent(getGunCoolingRateTextField()); + right.addComponent(getInactivityTimeTextField()); + right.addComponent(getSentryBorderSizeTextField()); + right.addComponent(hideEnemyNamesCheckBox); + leftToRight.addGroup(right); + + GroupLayout.SequentialGroup topToBottom = layout.createSequentialGroup(); + + GroupLayout.ParallelGroup row0 = layout.createParallelGroup(Alignment.BASELINE); + row0.addComponent(numberOfRoundsLabel); + row0.addComponent(numberOfRoundsTextField); + topToBottom.addGroup(row0); + + GroupLayout.ParallelGroup row1 = layout.createParallelGroup(Alignment.BASELINE); + row1.addComponent(gunCoolingRateLabel); + row1.addComponent(getGunCoolingRateTextField()); + topToBottom.addGroup(row1); + + GroupLayout.ParallelGroup row2 = layout.createParallelGroup(Alignment.BASELINE); + row2.addComponent(inactivityTimeLabel); + row2.addComponent(inactivityTimeTextField); + topToBottom.addGroup(row2); + + GroupLayout.ParallelGroup row3 = layout.createParallelGroup(Alignment.BASELINE); + row3.addComponent(sentryBorderSizeLabel); + row3.addComponent(sentryBorderSizeTextField); + topToBottom.addGroup(row3); + + GroupLayout.ParallelGroup row4 = layout.createParallelGroup(Alignment.CENTER); + row4.addComponent(hideEnemyNamesLabel); + row4.addComponent(hideEnemyNamesCheckBox); + topToBottom.addGroup(row4); + + layout.setHorizontalGroup(leftToRight); + layout.setVerticalGroup(topToBottom); + + return panel; + } + + private JTextField getNumberOfRoundsTextField() { + if (numberOfRoundsTextField == null) { + numberOfRoundsTextField = new JTextField(5); + numberOfRoundsTextField.setText("" + battleProperties.getNumRounds()); + numberOfRoundsTextField.setInputVerifier( + new InputVerifier() { + @Override + public boolean verify(JComponent input) { + boolean isValid = false; + + String text = ((JTextField) input).getText(); + if (text != null && text.matches("\\d+")) { + int numRounds = Integer.parseInt(text); + isValid = (numRounds > 0); + } + if (!isValid) { + WindowUtil.messageError( + "'Number of Rounds' must be an integer value > 0.\n" + "Default value is 10."); + numberOfRoundsTextField.setText("" + battleProperties.getNumRounds()); + } + return isValid; + } + }); + } + return numberOfRoundsTextField; + } + + private JTextField getGunCoolingRateTextField() { + if (gunCoolingRateTextField == null) { + gunCoolingRateTextField = new JTextField(5); + gunCoolingRateTextField.setText("" + battleProperties.getGunCoolingRate()); + gunCoolingRateTextField.setInputVerifier( + new InputVerifier() { + @Override + public boolean verify(JComponent input) { + boolean isValid = false; + + String text = ((JTextField) input).getText(); + if (text != null && text.matches("\\d*(\\.\\d+)?")) { + double gunCoolingRate = Double.parseDouble(text); + isValid = (gunCoolingRate > 0 && gunCoolingRate <= 0.7); + } + if (!isValid) { + WindowUtil.messageError( + "'Gun Cooling Rate' must be a floating point number > 0 and <= 0.7.\n" + + "Default value is 0.1."); + gunCoolingRateTextField.setText("" + battleProperties.getGunCoolingRate()); + } + return isValid; + } + }); + } + return gunCoolingRateTextField; + } + + private JTextField getInactivityTimeTextField() { + if (inactivityTimeTextField == null) { + inactivityTimeTextField = new JTextField(5); + inactivityTimeTextField.setText("" + battleProperties.getInactivityTime()); + inactivityTimeTextField.setInputVerifier( + new InputVerifier() { + @Override + public boolean verify(JComponent input) { + boolean isValid = false; + + String text = ((JTextField) input).getText(); + if (text != null && text.matches("\\d+")) { + int inactivityTime = Integer.parseInt(text); + isValid = (inactivityTime >= 0); + } + if (!isValid) { + WindowUtil.messageError( + "'Inactivity Time' must be an integer value >= 0.\n" + "Default value is 450."); + inactivityTimeTextField.setText("" + battleProperties.getInactivityTime()); + } + return isValid; + } + }); + } + return inactivityTimeTextField; + } + + private JTextField getSentryBorderSizeTextField() { + if (sentryBorderSizeTextField == null) { + sentryBorderSizeTextField = new JTextField(5); + sentryBorderSizeTextField.setText("" + battleProperties.getSentryBorderSize()); + sentryBorderSizeTextField.setInputVerifier( + new InputVerifier() { + @Override + public boolean verify(JComponent input) { + boolean isValid = false; + + String text = ((JTextField) input).getText(); + if (text != null && text.matches("\\d+")) { + int borderSize = Integer.parseInt(text); + isValid = (borderSize >= 50); + } + if (!isValid) { + WindowUtil.messageError( + "'Sentry Border Size' must be an integer value >= 50.\n" + "Default value is 100."); + sentryBorderSizeTextField.setText("" + battleProperties.getSentryBorderSize()); + } + return isValid; + } + }); + } + return sentryBorderSizeTextField; + } + + private JSlider createBattlefieldSizeSlider() { + JSlider slider = new JSlider(); + slider.setMinimum(MIN_BATTLEFIELD_SIZE); + slider.setMaximum(MAX_BATTLEFIELD_SIZE); + slider.setMajorTickSpacing(BATTLEFIELD_STEP_SIZE); + slider.setSnapToTicks(true); + slider.setPaintTicks(true); + return slider; + } + + private void updateBattlefieldSizeLabel() { + int w = battlefieldWidthSlider.getValue(); + int h = battlefieldHeightSlider.getValue(); + battlefieldSizeLabel.setText(w + " x " + h); + } + + private class SizeButton extends JButton { + final int width; + final int height; + + public SizeButton(int width, int height) { + super(width + "x" + height); + this.width = width; + this.height = height; + addActionListener(eventHandler); + } + } + + + private class EventHandler implements AncestorListener, ActionListener, ChangeListener { + @Override + public void ancestorAdded(AncestorEvent event) { + pushBattlePropertiesToUIComponents(); + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + Integer numberOfRounds; + try { + numberOfRounds = Integer.parseInt(getNumberOfRoundsTextField().getText()); + } catch (NumberFormatException e) { + numberOfRounds = null; + } + if (numberOfRounds != null) { + settingsManager.setBattleDefaultNumberOfRounds(numberOfRounds); + battleProperties.setNumRounds(numberOfRounds); + } + Double gunCoolingRate; + try { + gunCoolingRate = Double.parseDouble(getGunCoolingRateTextField().getText()); + } catch (NumberFormatException e) { + gunCoolingRate = null; + } + if (gunCoolingRate != null) { + settingsManager.setBattleDefaultGunCoolingRate(gunCoolingRate); + battleProperties.setGunCoolingRate(gunCoolingRate); + } + Integer inactivityTime; + try { + inactivityTime = Integer.parseInt(getInactivityTimeTextField().getText()); + } catch (NumberFormatException e) { + inactivityTime = null; + } + if (inactivityTime != null) { + settingsManager.setBattleDefaultInactivityTime(inactivityTime); + battleProperties.setInactivityTime(inactivityTime); + } + Integer sentryBorderSize; + try { + sentryBorderSize = Integer.parseInt(getSentryBorderSizeTextField().getText()); + } catch (NumberFormatException e) { + sentryBorderSize = null; + } + if (sentryBorderSize != null) { + settingsManager.setBattleDefaultSentryBorderSize(sentryBorderSize); + battleProperties.setSentryBorderSize(sentryBorderSize); + } + boolean hideEnemyNames = hideEnemyNamesCheckBox.isSelected(); + settingsManager.setBattleDefaultHideEnemyNames(hideEnemyNames); + battleProperties.setHideEnemyNames(hideEnemyNames); + + int weight = battlefieldWidthSlider.getValue(); + int height = battlefieldHeightSlider.getValue(); + + settingsManager.setBattleDefaultBattlefieldWidth(weight); + settingsManager.setBattleDefaultBattlefieldHeight(height); + + battleProperties.setBattlefieldWidth(weight); + battleProperties.setBattlefieldHeight(height); + } + + @Override + public void ancestorMoved(AncestorEvent event) {} + + @Override + public void actionPerformed(ActionEvent event) { + if (event.getSource() instanceof SizeButton) { + SizeButton button = (SizeButton) event.getSource(); + battlefieldWidthSlider.setValue(button.width); + battlefieldHeightSlider.setValue(button.height); + updateBattlefieldSizeLabel(); + + } else if (event.getSource() == restoreDefaultsButton) { + battleProperties.setBattlefieldWidth(800); + battleProperties.setBattlefieldHeight(600); + battleProperties.setNumRounds(10); + battleProperties.setGunCoolingRate(0.1); + battleProperties.setInactivityTime(450); + battleProperties.setHideEnemyNames(false); + battleProperties.setSentryBorderSize(100); + + pushBattlePropertiesToUIComponents(); + } + } + + @Override + public void stateChanged(ChangeEvent event) { + if ((event.getSource() == battlefieldWidthSlider) || (event.getSource() == battlefieldHeightSlider)) { + updateBattlefieldSizeLabel(); + } + } + + private void pushBattlePropertiesToUIComponents() { + battlefieldWidthSlider.setValue(battleProperties.getBattlefieldWidth()); + battlefieldHeightSlider.setValue(battleProperties.getBattlefieldHeight()); + updateBattlefieldSizeLabel(); + + getNumberOfRoundsTextField().setText("" + battleProperties.getNumRounds()); + getGunCoolingRateTextField().setText("" + battleProperties.getGunCoolingRate()); + getInactivityTimeTextField().setText("" + battleProperties.getInactivityTime()); + getSentryBorderSizeTextField().setText("" + battleProperties.getSentryBorderSize()); + hideEnemyNamesCheckBox.setSelected(battleProperties.getHideEnemyNames()); + } + } + + + private class BattlefieldSizeLabel extends JLabel { + @Override + public void paintComponent(Graphics g) { + g.setColor(SystemColor.activeCaption); + + int width = getWidth() * battlefieldWidthSlider.getValue() / MAX_BATTLEFIELD_SIZE; + int height = getHeight() * battlefieldHeightSlider.getValue() / MAX_BATTLEFIELD_SIZE; + + g.fillRect(0, 0, width, height); + super.paintComponent(g); + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesCommonOptionsTab.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesCommonOptionsTab.java new file mode 100644 index 0000000..3bc8795 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesCommonOptionsTab.java @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.settings.ISettingsManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class PreferencesCommonOptionsTab extends WizardPanel { + + private JPanel optionsPanel; + + private JCheckBox notifyAboutBetaVersionsCheckBox; + private JCheckBox showResultsCheckBox; + private JCheckBox dontHideRankingsCheckBox; + private JCheckBox appendWhenSavingResultsCheckBox; + private JCheckBox enableReplayRecordingCheckBox; + private JCheckBox enableAutoRecordingCheckBox; + + private final ISettingsManager properties; + + public PreferencesCommonOptionsTab(ISettingsManager properties) { + super(); + this.properties = properties; + initialize(); + } + + private void initialize() { + setLayout(new GridLayout(1, 2)); + add(getOptionsPanel()); + loadPreferences(properties); + } + + private JPanel getOptionsPanel() { + if (optionsPanel == null) { + optionsPanel = new JPanel(); + optionsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Common")); + optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS)); + optionsPanel.add(getNotifyAboutBetaVersionsCheckBox()); + optionsPanel.add(new JLabel(" ")); + optionsPanel.add(getShowResultsCheckBox()); + optionsPanel.add(getDontHideRankingsCheckBox()); + optionsPanel.add(getAppendWhenSavingResultsCheckBox()); + optionsPanel.add(new JLabel(" ")); + optionsPanel.add(getEnableReplayRecordingCheckBox()); + optionsPanel.add(getEnableAutoRecordingCheckBox()); + } + return optionsPanel; + } + + private JCheckBox getNotifyAboutBetaVersionsCheckBox() { + if (notifyAboutBetaVersionsCheckBox == null) { + notifyAboutBetaVersionsCheckBox = new JCheckBox("Notify about new Beta versions of Robocode"); + notifyAboutBetaVersionsCheckBox.setMnemonic('B'); + notifyAboutBetaVersionsCheckBox.setDisplayedMnemonicIndex(17); + } + return notifyAboutBetaVersionsCheckBox; + } + + private JCheckBox getShowResultsCheckBox() { + if (showResultsCheckBox == null) { + showResultsCheckBox = new JCheckBox("Show results when battle(s) ends"); + showResultsCheckBox.setMnemonic('h'); + showResultsCheckBox.setDisplayedMnemonicIndex(1); + } + return showResultsCheckBox; + } + + private JCheckBox getDontHideRankingsCheckBox() { + if (dontHideRankingsCheckBox == null) { + dontHideRankingsCheckBox = new JCheckBox("Don't hide current rankings when main window is minimized"); + dontHideRankingsCheckBox.setMnemonic('t'); + dontHideRankingsCheckBox.setDisplayedMnemonicIndex(4); + } + return dontHideRankingsCheckBox; + } + + private JCheckBox getAppendWhenSavingResultsCheckBox() { + if (appendWhenSavingResultsCheckBox == null) { + appendWhenSavingResultsCheckBox = new JCheckBox("Append when saving results"); + appendWhenSavingResultsCheckBox.setMnemonic('A'); + } + return appendWhenSavingResultsCheckBox; + } + + private JCheckBox getEnableReplayRecordingCheckBox() { + if (enableReplayRecordingCheckBox == null) { + enableReplayRecordingCheckBox = new JCheckBox("Enable replay recording (uses memory and disk space)"); + enableReplayRecordingCheckBox.setMnemonic('E'); + } + return enableReplayRecordingCheckBox; + } + + private JCheckBox getEnableAutoRecordingCheckBox() { + if (enableAutoRecordingCheckBox == null) { + enableAutoRecordingCheckBox = new JCheckBox( + "Enable auto recording (every finished battle is automatically saved into battles folder)"); + enableAutoRecordingCheckBox.setMnemonic('u'); + enableAutoRecordingCheckBox.setDisplayedMnemonicIndex(8); + + enableAutoRecordingCheckBox.addActionListener( + new ActionListener() { + public void actionPerformed(ActionEvent e) { + boolean isSelected = enableAutoRecordingCheckBox.isSelected(); + + enableReplayRecordingCheckBox.setEnabled(!isSelected); + enableReplayRecordingCheckBox.setSelected( + isSelected ? true : properties.getOptionsCommonEnableReplayRecording()); + } + }); + } + return enableAutoRecordingCheckBox; + } + + private void loadPreferences(ISettingsManager props) { + getNotifyAboutBetaVersionsCheckBox().setSelected(props.getOptionsCommonNotifyAboutNewBetaVersions()); + getShowResultsCheckBox().setSelected(props.getOptionsCommonShowResults()); + getDontHideRankingsCheckBox().setSelected(props.getOptionsCommonDontHideRankings()); + getAppendWhenSavingResultsCheckBox().setSelected(props.getOptionsCommonAppendWhenSavingResults()); + getEnableReplayRecordingCheckBox().setSelected(props.getOptionsCommonEnableReplayRecording()); + getEnableAutoRecordingCheckBox().setSelected(props.getOptionsCommonEnableAutoRecording()); + } + + public void storePreferences() { + ISettingsManager props = properties; + + props.setOptionsCommonNotifyAboutNewBetaVersions(getNotifyAboutBetaVersionsCheckBox().isSelected()); + props.setOptionsCommonShowResults(getShowResultsCheckBox().isSelected()); + props.setOptionsCommonDontHideRankings(getDontHideRankingsCheckBox().isSelected()); + props.setOptionsCommonAppendWhenSavingResults(getAppendWhenSavingResultsCheckBox().isSelected()); + props.setOptionsCommonEnableReplayRecording(getEnableReplayRecordingCheckBox().isSelected()); + props.setOptionsCommonEnableAutoRecording(getEnableAutoRecordingCheckBox().isSelected()); + + properties.saveProperties(); + } + + @Override + public boolean isReady() { + return true; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesDevelopmentOptionsTab.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesDevelopmentOptionsTab.java new file mode 100644 index 0000000..29ac579 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesDevelopmentOptionsTab.java @@ -0,0 +1,198 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.CheckList; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Ruben Moreno Montoliu (contributor) + */ +@SuppressWarnings("serial") +public class PreferencesDevelopmentOptionsTab extends WizardPanel { + + private JPanel optionsPanel; + + private JButton addButton; + private JButton removeButton; + private CheckList pathList; + + public final ISettingsManager properties; + + private final EventHandler eventHandler = new EventHandler(); + + private class EventHandler implements ActionListener, ListSelectionListener { + public void actionPerformed(ActionEvent e) { + if (e.getSource() == getAddButton()) { + handleAddAction(); + } else if (e.getSource() == getRemoveButton()) { + handleRemoveAction(); + } + } + + public void valueChanged(ListSelectionEvent e) { + updateRemoveButton(); + } + } + + public PreferencesDevelopmentOptionsTab(ISettingsManager properties) { + super(); + this.properties = properties; + initialize(); + } + + private void initialize() { + setLayout(new GridLayout(1, 2)); + add(getOptionsPanel()); + loadPreferences(properties); + } + + private JPanel getOptionsPanel() { + if (optionsPanel == null) { + optionsPanel = new JPanel(); + optionsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Development")); + + GridBagLayout layout = new GridBagLayout(); + + optionsPanel.setLayout(layout); + GridBagConstraints c = new GridBagConstraints(); + + c.insets = new Insets(0, 5, 5, 5); + c.anchor = GridBagConstraints.NORTHWEST; + + c.fill = GridBagConstraints.HORIZONTAL; + c.gridwidth = 2; + c.weightx = 0; + c.gridy = 1; + + optionsPanel.add( + new JLabel( + "If you are using an external IDE to develop robots, you may enter the classpath(s) to those robots here."), + c); + c.gridy++; + optionsPanel.add( + new JLabel( + "If you are using Eclipse, you can enter the root dir of robot projects inside a workspace as well (recommended)"), + c); + c.gridy++; + optionsPanel.add(new JLabel("Double-click the path(s) the enable or disable it (checked means enabled)"), c); + + c.gridwidth = 1; + c.gridy++; + c.insets = new Insets(3, 3, 3, 3); + optionsPanel.add(getAddButton(), c); + + c.gridy++; + optionsPanel.add(getRemoveButton(), c); + + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + c.gridx = 1; + c.gridy--; + c.gridheight = 3; + c.insets = new Insets(5, 5, 5, 5); + JScrollPane pathListScroller = new JScrollPane(getPathList()); + + optionsPanel.add(pathListScroller, c); + } + return optionsPanel; + } + + private JButton getAddButton() { + if (addButton == null) { + addButton = new JButton("Add"); + addButton.setDisplayedMnemonicIndex(2); + addButton.addActionListener(eventHandler); + } + return addButton; + } + + private JButton getRemoveButton() { + if (removeButton == null) { + removeButton = new JButton("Remove"); + removeButton.setDisplayedMnemonicIndex(3); + removeButton.addActionListener(eventHandler); + } + return removeButton; + } + + private CheckList getPathList() { + if (pathList == null) { + pathList = new CheckList(); + pathList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + pathList.setLayoutOrientation(JList.VERTICAL); + pathList.setVisibleRowCount(-1); + pathList.addListSelectionListener(eventHandler); + } + return pathList; + } + + private void loadPreferences(ISettingsManager robocodeProperties) { + getPathList().clear(); + + for (String path : robocodeProperties.getOptionsDevelopmentPaths()) { + getPathList().add(path); + } + for (String excludedPath : robocodeProperties.getOptionsExcludedDevelopmentPaths()) { + getPathList().setChecked(excludedPath, false); + } + updateRemoveButton(); + } + + public void storePreferences() { + properties.setOptionsDevelopmentPaths(getPathList().getAll()); + properties.setOptionsExcludedDevelopmentPaths(getPathList().getUnchecked()); + properties.saveProperties(); + } + + @Override + public boolean isReady() { + return true; + } + + private void handleAddAction() { + JFileChooser chooser = new JFileChooser(); + + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + if (chooser.showOpenDialog(optionsPanel) == JFileChooser.APPROVE_OPTION) { + String path = chooser.getSelectedFile().getAbsolutePath(); + + if (!getPathList().contains(path)) { + getPathList().add(path); + getPathList().sort(); + } + } + updateRemoveButton(); + } + + private void handleRemoveAction() { + int[] indices = getPathList().getSelectedIndices(); + + for (int i = indices.length - 1; i >= 0; i--) { + getPathList().remove(indices[i]); + } + updateRemoveButton(); + } + + private void updateRemoveButton() { + getRemoveButton().setEnabled(getPathList().getSelectedIndex() >= 0); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesDialog.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesDialog.java new file mode 100644 index 0000000..903ab26 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesDialog.java @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.IImageManager; +import net.sf.robocode.ui.IWindowManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.KeyEvent; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Matthew Reeder (contributor) + */ +@SuppressWarnings("serial") +public class PreferencesDialog extends JDialog implements WizardListener { + + private JPanel preferencesDialogContentPane; + private WizardTabbedPane tabbedPane; + private WizardController buttonsPanel; + + private PreferencesCommonOptionsTab commonOptionsTab; + private PreferencesDevelopmentOptionsTab developmentOptionsTab; + private PreferencesViewOptionsTab viewOptionsTab; + private PreferencesRenderingOptionsTab renderingOptionsTab; + private PreferencesSoundOptionsTab soundOptionsTab; + + private final ISettingsManager properties; + private final IImageManager imageManager; + + public PreferencesDialog(ISettingsManager properties, IWindowManager windowManager, IImageManager imageManager) { + super(windowManager.getRobocodeFrame(), true); + this.properties = properties; + this.imageManager = imageManager; + initialize(); + } + + private void initialize() { + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setTitle("Preferences"); + setContentPane(getPreferencesDialogContentPane()); + } + + public void cancelButtonActionPerformed() { + dispose(); + } + + private WizardController getButtonsPanel() { + if (buttonsPanel == null) { + buttonsPanel = getTabbedPane().getWizardController(); + } + return buttonsPanel; + } + + private JPanel getPreferencesDialogContentPane() { + getButtonsPanel(); + if (preferencesDialogContentPane == null) { + preferencesDialogContentPane = new JPanel(); + preferencesDialogContentPane.setLayout(new BorderLayout()); + preferencesDialogContentPane.add(getTabbedPane(), BorderLayout.CENTER); + preferencesDialogContentPane.add(getButtonsPanel(), BorderLayout.SOUTH); + } + return preferencesDialogContentPane; + } + + private WizardTabbedPane getTabbedPane() { + if (tabbedPane == null) { + tabbedPane = new WizardTabbedPane(this); + + int tabIndex = 0; + + tabbedPane.insertTab("Common Options", null, getCommonOptionsTab(), null, tabIndex); + tabbedPane.setMnemonicAt(tabIndex, KeyEvent.VK_O); + tabbedPane.setDisplayedMnemonicIndexAt(tabIndex++, 1); + + tabbedPane.insertTab("Development Options", null, getDevelopmentOptionsTab(), null, tabIndex); + tabbedPane.setMnemonicAt(tabIndex, KeyEvent.VK_D); + tabbedPane.setDisplayedMnemonicIndexAt(tabIndex++, 0); + + tabbedPane.insertTab("View Options", null, getViewOptionsTab(), null, tabIndex); + tabbedPane.setMnemonicAt(tabIndex, KeyEvent.VK_W); + tabbedPane.setDisplayedMnemonicIndexAt(tabIndex++, 3); + + tabbedPane.insertTab("Rendering Options", null, getRenderingOptionsTab(), null, tabIndex); + tabbedPane.setMnemonicAt(tabIndex, KeyEvent.VK_R); + tabbedPane.setDisplayedMnemonicIndexAt(tabIndex++, 0); + + tabbedPane.insertTab("Sound Options", null, getSoundOptionsTab(), null, tabIndex); + tabbedPane.setMnemonicAt(tabIndex, KeyEvent.VK_S); + tabbedPane.setDisplayedMnemonicIndexAt(tabIndex++, 0); + } + return tabbedPane; + } + + private JPanel getCommonOptionsTab() { + if (commonOptionsTab == null) { + commonOptionsTab = new PreferencesCommonOptionsTab(properties); + } + return commonOptionsTab; + } + + private JPanel getDevelopmentOptionsTab() { + if (developmentOptionsTab == null) { + developmentOptionsTab = new PreferencesDevelopmentOptionsTab(properties); + } + return developmentOptionsTab; + } + + private JPanel getViewOptionsTab() { + if (viewOptionsTab == null) { + viewOptionsTab = new PreferencesViewOptionsTab(properties); + } + return viewOptionsTab; + } + + private JPanel getRenderingOptionsTab() { + if (renderingOptionsTab == null) { + renderingOptionsTab = new PreferencesRenderingOptionsTab(properties, imageManager); + } + return renderingOptionsTab; + } + + private JPanel getSoundOptionsTab() { + if (soundOptionsTab == null) { + soundOptionsTab = new PreferencesSoundOptionsTab(properties); + } + return soundOptionsTab; + } + + public void finishButtonActionPerformed() { + commonOptionsTab.storePreferences(); + developmentOptionsTab.storePreferences(); + viewOptionsTab.storePreferences(); + renderingOptionsTab.storePreferences(); + soundOptionsTab.storePreferences(); + + dispose(); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesRenderingOptionsTab.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesRenderingOptionsTab.java new file mode 100644 index 0000000..34fc834 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesRenderingOptionsTab.java @@ -0,0 +1,297 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.IImageManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class PreferencesRenderingOptionsTab extends WizardPanel { + + private final ISettingsManager properties; + + private JPanel specificSettingsPanel; + private JPanel predefinedSettingsPanel; + private JPanel otherSettingsPanel; + + private JComboBox optionsRenderingAntialiasingComboBox; + private JComboBox optionsRenderingTextAntialiasingComboBox; + private JComboBox optionsRenderingMethodComboBox; + private JComboBox optionsRenderingNoBuffersComboBox; + private JCheckBox optionsRenderingBufferImagesCheckBox; + private JCheckBox optionsRenderingForceBulletColorCheckBox; + + private JButton predefinedPlaformDefaultButton; + private JButton predefinedSpeedButton; + private JButton predefinedQualityButton; + + private EventHandler eventHandler; + private final IImageManager imageManager; + + public PreferencesRenderingOptionsTab(ISettingsManager properties, IImageManager imageManager) { + super(); + this.properties = properties; + this.imageManager = imageManager; + initialize(); + } + + private void initialize() { + eventHandler = new EventHandler(); + + setLayout(new GridLayout(1, 3)); + + add(getSpecificSettingsPanel()); + add(getPredefinedSettingsPanel()); + add(getOtherSettingsPanel()); + + loadPreferences(properties); + } + + private JPanel getSpecificSettingsPanel() { + if (specificSettingsPanel == null) { + specificSettingsPanel = new JPanel(); + specificSettingsPanel.setBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Specific settings")); + specificSettingsPanel.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + + c.fill = GridBagConstraints.HORIZONTAL; + c.insets = new Insets(5, 5, 5, 5); + c.anchor = GridBagConstraints.PAGE_START; + + c.weightx = 0; + + c.gridwidth = 2; + + c.gridx = 0; + c.gridy = 0; + specificSettingsPanel.add(new JLabel("Set individual rendering options:"), c); + + c.gridwidth = 1; + + c.gridy = 1; + specificSettingsPanel.add(new JLabel("Antialiasing", SwingConstants.RIGHT), c); + c.gridx = 1; + specificSettingsPanel.add(getOptionsRenderingAntialiasingComboBox(), c); + + c.gridx = 0; + c.gridy = 2; + specificSettingsPanel.add(new JLabel("Text Antialiasing", SwingConstants.RIGHT), c); + c.gridx = 1; + specificSettingsPanel.add(getOptionsRenderingTextAntialiasingComboBox(), c); + + c.gridx = 0; + c.gridy = 3; + specificSettingsPanel.add(new JLabel("Rendering Method", SwingConstants.RIGHT), c); + c.gridx = 1; + specificSettingsPanel.add(getOptionsRenderingMethodComboBox(), c); + + c.gridx = 0; + c.gridy = 4; + specificSettingsPanel.add(new JLabel(" "), c); + + c.gridx = 0; + c.gridy = 5; + specificSettingsPanel.add(new JLabel("Number of buffers", SwingConstants.RIGHT), c); + c.gridx = 1; + specificSettingsPanel.add(getOptionsRenderingNoBuffersComboBox(), c); + } + return specificSettingsPanel; + } + + private JPanel getPredefinedSettingsPanel() { + if (predefinedSettingsPanel == null) { + predefinedSettingsPanel = new JPanel(); + predefinedSettingsPanel.setBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Predefined settings")); + predefinedSettingsPanel.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + + c.fill = GridBagConstraints.HORIZONTAL; + c.insets = new Insets(5, 5, 5, 5); + c.anchor = GridBagConstraints.PAGE_START; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 3; + predefinedSettingsPanel.add(new JLabel("Set all rendering settings towards:"), c); + + c.weightx = 1f / 3; + c.gridwidth = 1; + c.gridy = 2; + predefinedSettingsPanel.add(getPredefinedPlatformDefaultButton(), c); + c.gridx = 1; + predefinedSettingsPanel.add(getPredefinedSpeedButton(), c); + c.gridx = 2; + predefinedSettingsPanel.add(getPredefinedQualityButton(), c); + } + return predefinedSettingsPanel; + } + + private JPanel getOtherSettingsPanel() { + if (otherSettingsPanel == null) { + otherSettingsPanel = new JPanel(); + otherSettingsPanel.setBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Other settings")); + otherSettingsPanel.setLayout(new BoxLayout(otherSettingsPanel, BoxLayout.Y_AXIS)); + otherSettingsPanel.add(getOptionsRenderingBufferImagesCheckBox()); + otherSettingsPanel.add(getOptionsRenderingForceBulletColorCheckBox()); + } + return otherSettingsPanel; + } + + private JComboBox getOptionsRenderingAntialiasingComboBox() { + if (optionsRenderingAntialiasingComboBox == null) { + optionsRenderingAntialiasingComboBox = new JComboBox(new String[] { "Default", "On", "Off"}); + optionsRenderingAntialiasingComboBox.addActionListener(eventHandler); + } + return optionsRenderingAntialiasingComboBox; + } + + private JComboBox getOptionsRenderingTextAntialiasingComboBox() { + if (optionsRenderingTextAntialiasingComboBox == null) { + optionsRenderingTextAntialiasingComboBox = new JComboBox(new String[] { "Default", "On", "Off"}); + optionsRenderingTextAntialiasingComboBox.addActionListener(eventHandler); + } + return optionsRenderingTextAntialiasingComboBox; + } + + private JComboBox getOptionsRenderingMethodComboBox() { + if (optionsRenderingMethodComboBox == null) { + optionsRenderingMethodComboBox = new JComboBox(new String[] { "Default", "Quality", "Speed"}); + optionsRenderingMethodComboBox.addActionListener(eventHandler); + } + return optionsRenderingMethodComboBox; + } + + private JComboBox getOptionsRenderingNoBuffersComboBox() { + if (optionsRenderingNoBuffersComboBox == null) { + optionsRenderingNoBuffersComboBox = new JComboBox( + new String[] { "Single buffering", "Double buffering", "Triple buffering"}); + optionsRenderingNoBuffersComboBox.addActionListener(eventHandler); + } + return optionsRenderingNoBuffersComboBox; + } + + private JButton getPredefinedPlatformDefaultButton() { + if (predefinedPlaformDefaultButton == null) { + predefinedPlaformDefaultButton = new JButton("Default"); + predefinedPlaformDefaultButton.setMnemonic('u'); + predefinedPlaformDefaultButton.setDisplayedMnemonicIndex(4); + predefinedPlaformDefaultButton.addActionListener(eventHandler); + } + return predefinedPlaformDefaultButton; + } + + private JButton getPredefinedSpeedButton() { + if (predefinedSpeedButton == null) { + predefinedSpeedButton = new JButton("Speed"); + predefinedSpeedButton.setMnemonic('p'); + predefinedSpeedButton.setDisplayedMnemonicIndex(1); + predefinedSpeedButton.addActionListener(eventHandler); + } + return predefinedSpeedButton; + } + + private JButton getPredefinedQualityButton() { + if (predefinedQualityButton == null) { + predefinedQualityButton = new JButton("Quality"); + predefinedQualityButton.setMnemonic('Q'); + predefinedQualityButton.addActionListener(eventHandler); + } + return predefinedQualityButton; + } + + private JCheckBox getOptionsRenderingBufferImagesCheckBox() { + if (optionsRenderingBufferImagesCheckBox == null) { + optionsRenderingBufferImagesCheckBox = new JCheckBox("Buffer images (uses memory)"); + optionsRenderingBufferImagesCheckBox.setMnemonic('i'); + optionsRenderingBufferImagesCheckBox.setDisplayedMnemonicIndex(7); + optionsRenderingBufferImagesCheckBox.addActionListener(eventHandler); + } + return optionsRenderingBufferImagesCheckBox; + } + + private JCheckBox getOptionsRenderingForceBulletColorCheckBox() { + if (optionsRenderingForceBulletColorCheckBox == null) { + optionsRenderingForceBulletColorCheckBox = new JCheckBox("Make all bullets white"); + optionsRenderingForceBulletColorCheckBox.setMnemonic('M'); + optionsRenderingForceBulletColorCheckBox.addActionListener(eventHandler); + } + return optionsRenderingForceBulletColorCheckBox; + } + + private void loadPreferences(ISettingsManager props) { + getOptionsRenderingAntialiasingComboBox().setSelectedIndex(props.getOptionsRenderingAntialiasing()); + getOptionsRenderingTextAntialiasingComboBox().setSelectedIndex(props.getOptionsRenderingTextAntialiasing()); + getOptionsRenderingMethodComboBox().setSelectedIndex(props.getOptionsRenderingMethod()); + getOptionsRenderingNoBuffersComboBox().setSelectedIndex(props.getOptionsRenderingNoBuffers() - 1); + getOptionsRenderingBufferImagesCheckBox().setSelected(props.getOptionsRenderingBufferImages()); + getOptionsRenderingForceBulletColorCheckBox().setSelected(props.getOptionsRenderingForceBulletColor()); + } + + public void storePreferences() { + ISettingsManager props = properties; + + props.setOptionsRenderingAntialiasing(optionsRenderingAntialiasingComboBox.getSelectedIndex()); + props.setOptionsRenderingTextAntialiasing(optionsRenderingTextAntialiasingComboBox.getSelectedIndex()); + props.setOptionsRenderingMethod(optionsRenderingMethodComboBox.getSelectedIndex()); + props.setOptionsRenderingNoBuffers(optionsRenderingNoBuffersComboBox.getSelectedIndex() + 1); + props.setOptionsRenderingBufferImages(optionsRenderingBufferImagesCheckBox.isSelected()); + props.setOptionsRenderingForceBulletColor(optionsRenderingForceBulletColorCheckBox.isSelected()); + properties.saveProperties(); + } + + @Override + public boolean isReady() { + return true; + } + + private void setPredefinedSettings(int index) { + optionsRenderingAntialiasingComboBox.setSelectedIndex(index); + optionsRenderingTextAntialiasingComboBox.setSelectedIndex(index); + optionsRenderingMethodComboBox.setSelectedIndex(index); + } + + private class EventHandler implements ActionListener { + + public void actionPerformed(ActionEvent e) { + Object src = e.getSource(); + + if (src == predefinedPlaformDefaultButton) { + setPredefinedSettings(0); + } else if (src == predefinedQualityButton) { + setPredefinedSettings(1); + } else if (src == predefinedSpeedButton) { + setPredefinedSettings(2); + } else if (src == optionsRenderingBufferImagesCheckBox) { + // Reset images so they are reloaded and gets buffered or unbuffered + new Thread() { + @Override + public void run() { + storePreferences(); + imageManager.initialize(); + } + }.start(); + return; + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesSoundOptionsTab.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesSoundOptionsTab.java new file mode 100644 index 0000000..37a71e3 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesSoundOptionsTab.java @@ -0,0 +1,397 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.settings.ISettingsManager; + +import javax.sound.sampled.*; +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Vector; + + +/** + * @author Flemming N. Larsen (original) + */ +@SuppressWarnings("serial") +public class PreferencesSoundOptionsTab extends WizardPanel { + + private final ISettingsManager properties; + + private final EventHandler eventHandler = new EventHandler(); + + private JPanel soundOptionsPanel; + private JPanel mixerOptionsPanel; + + private JCheckBox enableSoundCheckBox; + private JCheckBox enableGunshotCheckBox; + private JCheckBox enableBulletHitCheckBox; + private JCheckBox enableRobotDeathCheckBox; + private JCheckBox enableWallCollisionCheckBox; + private JCheckBox enableRobotCollisionCheckBox; + + private JButton enableAllSoundsButton; + private JButton disableAllSoundsButton; + + private JComboBox mixerComboBox; + private JButton mixerDefaultButton; + + private JCheckBox enableMixerVolumeCheckBox; + private JCheckBox enableMixerPanCheckBox; + + public PreferencesSoundOptionsTab(ISettingsManager properties) { + super(); + this.properties = properties; + initialize(); + } + + private void initialize() { + setLayout(new GridLayout(1, 2)); + + add(getSoundOptionsPanel()); + add(getMixerOptionsPanel()); + + loadPreferences(properties); + } + + private JPanel getSoundOptionsPanel() { + if (soundOptionsPanel == null) { + soundOptionsPanel = new JPanel(); + soundOptionsPanel.setBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Sound Effects")); + + soundOptionsPanel.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + + c.fill = 1; + c.weightx = 1; + c.anchor = GridBagConstraints.NORTHWEST; + + c.gridwidth = GridBagConstraints.REMAINDER; + soundOptionsPanel.add(getEnableSoundCheckBox(), c); + soundOptionsPanel.add(getEnableGunshotCheckBox(), c); + soundOptionsPanel.add(getEnableBulletHitCheckBox(), c); + soundOptionsPanel.add(getEnableRobotDeathCheckBox(), c); + soundOptionsPanel.add(getEnableWallCollisionCheckBox(), c); + soundOptionsPanel.add(getEnableRobotCollisionCheckBox(), c); + + c.insets = new Insets(10, 0, 0, 10); + c.gridwidth = 1; + c.fill = 0; + c.weighty = 1; + c.weightx = 0; + soundOptionsPanel.add(getEnableAllSoundsButton(), c); + c.weightx = 1; + c.gridwidth = GridBagConstraints.REMAINDER; + soundOptionsPanel.add(getDisableAllSoundsButton(), c); + + if (AudioSystem.getMixerInfo().length == 0) { + for (Component child : soundOptionsPanel.getComponents()) { + child.setEnabled(false); + } + } + } + return soundOptionsPanel; + } + + private JCheckBox getEnableSoundCheckBox() { + if (enableSoundCheckBox == null) { + enableSoundCheckBox = new JCheckBox("Enable Sound"); + enableSoundCheckBox.setMnemonic('E'); + } + return enableSoundCheckBox; + } + + private JCheckBox getEnableGunshotCheckBox() { + if (enableGunshotCheckBox == null) { + enableGunshotCheckBox = new JCheckBox("Gun Shots"); + enableGunshotCheckBox.setMnemonic('G'); + } + return enableGunshotCheckBox; + } + + private JCheckBox getEnableBulletHitCheckBox() { + if (enableBulletHitCheckBox == null) { + enableBulletHitCheckBox = new JCheckBox("Bullet Hit"); + enableBulletHitCheckBox.setMnemonic('H'); + enableBulletHitCheckBox.setDisplayedMnemonicIndex(7); + } + return enableBulletHitCheckBox; + } + + private JCheckBox getEnableRobotDeathCheckBox() { + if (enableRobotDeathCheckBox == null) { + enableRobotDeathCheckBox = new JCheckBox("Robot Death Explosions"); + enableRobotDeathCheckBox.setMnemonic('x'); + enableRobotDeathCheckBox.setDisplayedMnemonicIndex(13); + } + return enableRobotDeathCheckBox; + } + + private JCheckBox getEnableRobotCollisionCheckBox() { + if (enableRobotCollisionCheckBox == null) { + enableRobotCollisionCheckBox = new JCheckBox("Robot Collisions"); + enableRobotCollisionCheckBox.setMnemonic('t'); + enableRobotCollisionCheckBox.setDisplayedMnemonicIndex(4); + } + return enableRobotCollisionCheckBox; + } + + private JCheckBox getEnableWallCollisionCheckBox() { + if (enableWallCollisionCheckBox == null) { + enableWallCollisionCheckBox = new JCheckBox("Wall Collisions"); + enableWallCollisionCheckBox.setMnemonic('l'); + enableWallCollisionCheckBox.setDisplayedMnemonicIndex(2); + } + return enableWallCollisionCheckBox; + } + + private JButton getEnableAllSoundsButton() { + if (enableAllSoundsButton == null) { + enableAllSoundsButton = new JButton("Enable all"); + enableAllSoundsButton.setMnemonic('a'); + enableAllSoundsButton.setDisplayedMnemonicIndex(7); + enableAllSoundsButton.addActionListener(eventHandler); + } + return enableAllSoundsButton; + } + + private JButton getDisableAllSoundsButton() { + if (disableAllSoundsButton == null) { + disableAllSoundsButton = new JButton("Disable all"); + disableAllSoundsButton.setMnemonic('i'); + disableAllSoundsButton.setDisplayedMnemonicIndex(1); + disableAllSoundsButton.addActionListener(eventHandler); + } + return disableAllSoundsButton; + } + + private JPanel getMixerOptionsPanel() { + if (mixerOptionsPanel == null) { + mixerOptionsPanel = new JPanel(); + mixerOptionsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Mixer")); + + mixerOptionsPanel.setLayout(new GridBagLayout()); + GridBagConstraints c = new GridBagConstraints(); + + c.anchor = GridBagConstraints.NORTHWEST; + c.fill = GridBagConstraints.NONE; + c.weightx = 1; + + c.insets = new Insets(8, 4, 0, 0); + mixerOptionsPanel.add(new JLabel("Select mixer:"), c); + + c.gridy = 1; + mixerOptionsPanel.add(getMixerComboBox(), c); + + c.gridy = 2; + mixerOptionsPanel.add(getMixerDefaultButton(), c); + + c.insets = new Insets(16, 4, 0, 0); + c.gridy = 3; + mixerOptionsPanel.add(new JLabel("Enable mixer features:"), c); + + c.insets = new Insets(6, 0, 0, 0); + c.gridy = 4; + mixerOptionsPanel.add(getEnableMixerVolumeCheckBox(), c); + + c.insets = new Insets(0, 0, 0, 0); + c.gridy = 5; + mixerOptionsPanel.add(getEnableMixerPanCheckBox(), c); + + if (AudioSystem.getMixerInfo().length == 0) { + for (Component child : mixerOptionsPanel.getComponents()) { + child.setEnabled(false); + } + } + } + return mixerOptionsPanel; + } + + private JComboBox getMixerComboBox() { + if (mixerComboBox == null) { + Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo(); + + Line.Info clipLineInfo = new Line.Info(Clip.class); + + Vector mixers = new Vector(); + + for (Mixer.Info mi : mixerInfo) { + if (AudioSystem.getMixer(mi).getSourceLineInfo(clipLineInfo).length > 0) { + mixers.add(mi); + } + } + + mixerComboBox = new JComboBox(mixers); + mixerComboBox.setRenderer(new MixerInfoCellRenderer()); + mixerComboBox.addActionListener(eventHandler); + } + return mixerComboBox; + } + + private JButton getMixerDefaultButton() { + if (mixerDefaultButton == null) { + mixerDefaultButton = new JButton("Default"); + mixerDefaultButton.setMnemonic('u'); + mixerDefaultButton.setDisplayedMnemonicIndex(4); + mixerDefaultButton.addActionListener(eventHandler); + } + return mixerDefaultButton; + } + + private JCheckBox getEnableMixerVolumeCheckBox() { + if (enableMixerVolumeCheckBox == null) { + enableMixerVolumeCheckBox = new JCheckBox("Volume"); + enableMixerVolumeCheckBox.setMnemonic('V'); + enableMixerVolumeCheckBox.addActionListener(eventHandler); + } + return enableMixerVolumeCheckBox; + } + + private JCheckBox getEnableMixerPanCheckBox() { + if (enableMixerPanCheckBox == null) { + enableMixerPanCheckBox = new JCheckBox("Pan"); + enableMixerPanCheckBox.setMnemonic('P'); + enableMixerPanCheckBox.addActionListener(eventHandler); + } + return enableMixerPanCheckBox; + } + + private void loadPreferences(ISettingsManager robocodeProperties) { + getEnableSoundCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableSound()); + getEnableGunshotCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableGunshot()); + getEnableBulletHitCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableBulletHit()); + getEnableRobotDeathCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableRobotDeath()); + getEnableRobotCollisionCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableRobotCollision()); + getEnableWallCollisionCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableWallCollision()); + getEnableMixerVolumeCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableMixerVolume()); + getEnableMixerPanCheckBox().setSelected(robocodeProperties.getOptionsSoundEnableMixerPan()); + + setMixerCompoBox(robocodeProperties.getOptionsSoundMixer()); + } + + public void storePreferences() { + ISettingsManager props = properties; + + props.setOptionsSoundEnableSound(getEnableSoundCheckBox().isSelected()); + props.setOptionsSoundEnableGunshot(getEnableGunshotCheckBox().isSelected()); + props.setOptionsSoundEnableBulletHit(getEnableBulletHitCheckBox().isSelected()); + props.setOptionsSoundEnableRobotDeath(getEnableRobotDeathCheckBox().isSelected()); + props.setOptionsSoundEnableRobotCollision(getEnableRobotCollisionCheckBox().isSelected()); + props.setOptionsSoundEnableWallCollision(getEnableWallCollisionCheckBox().isSelected()); + props.setOptionsSoundEnableMixerVolume(getEnableMixerVolumeCheckBox().isSelected()); + props.setOptionsSoundEnableMixerPan(getEnableMixerPanCheckBox().isSelected()); + + String mixerClassName = null; + Mixer.Info mixerInfo = (Mixer.Info) getMixerComboBox().getSelectedItem(); + + if (mixerInfo != null) { + Mixer mixer = AudioSystem.getMixer((Mixer.Info) getMixerComboBox().getSelectedItem()); + + if (mixer != null) { + mixerClassName = mixer.getClass().getSimpleName(); + } + } + if (mixerClassName != null) { + props.setOptionsSoundMixer(mixerClassName); + } + + properties.saveProperties(); + } + + @Override + public boolean isReady() { + return true; + } + + private void setMixerCompoBox(String mixerName) { + for (Mixer.Info mi : AudioSystem.getMixerInfo()) { + if (AudioSystem.getMixer(mi).getClass().getSimpleName().equals(mixerName)) { + getMixerComboBox().setSelectedItem(mi); + break; + } + } + } + + private class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + Object src = e.getSource(); + + if (src == enableAllSoundsButton) { + setAllSoundsButtonsEnabled(true); + } else if (src == disableAllSoundsButton) { + setAllSoundsButtonsEnabled(false); + } else if (src == mixerComboBox) { + mixerComboBoxActionPerformed(); + } else if (src == mixerDefaultButton) { + mixerDefaultButtonActionPerformed(); + } + } + } + + private void setAllSoundsButtonsEnabled(boolean enabled) { + enableSoundCheckBox.setSelected(enabled); + enableGunshotCheckBox.setSelected(enabled); + enableBulletHitCheckBox.setSelected(enabled); + enableRobotDeathCheckBox.setSelected(enabled); + enableWallCollisionCheckBox.setSelected(enabled); + enableRobotCollisionCheckBox.setSelected(enabled); + } + + private void mixerComboBoxActionPerformed() { + Mixer mixer = AudioSystem.getMixer((Mixer.Info) mixerComboBox.getSelectedItem()); + + Line.Info lineInfo = mixer.getSourceLineInfo(new Line.Info(Clip.class))[0]; + + boolean volumeSupported; + boolean panSupported; + + try { + Line line = mixer.getLine(lineInfo); + + volumeSupported = line.isControlSupported(FloatControl.Type.MASTER_GAIN); + panSupported = line.isControlSupported(FloatControl.Type.PAN); + } catch (LineUnavailableException e) { + volumeSupported = false; + panSupported = false; + } + + enableMixerVolumeCheckBox.setEnabled(volumeSupported); + enableMixerPanCheckBox.setEnabled(panSupported); + } + + private void mixerDefaultButtonActionPerformed() { + setMixerCompoBox("DirectAudioDevice"); + } + + private static class MixerInfoCellRenderer extends javax.swing.plaf.basic.BasicComboBoxRenderer { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + + Mixer.Info mi = (Mixer.Info) value; + + if (mi != null) { + String text = mi.getName(); + + if (!"Unknown Version".equals(mi.getVersion())) { + text += ' ' + mi.getVersion(); + } + if (!"Unknown Vendor".equals(mi.getVendor())) { + text += " by " + mi.getVendor(); + } + setText(text); + } + return component; + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesViewOptionsTab.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesViewOptionsTab.java new file mode 100644 index 0000000..e064903 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/PreferencesViewOptionsTab.java @@ -0,0 +1,470 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.settings.ISettingsListener; +import net.sf.robocode.settings.ISettingsManager; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Matthew Reeder (contributor) + */ +@SuppressWarnings("serial") +public class PreferencesViewOptionsTab extends WizardPanel { + + private static final int MIN_TPS = 1; + private static final int DEFAULT_TPS = 30; + private static final int FAST_TPS = 45; + private static final int MAX_TPS = 10000; + + private final EventHandler eventHandler = new EventHandler(); + + private JCheckBox visibleRobotEnergyCheckBox; + private JCheckBox visibleRobotNameCheckBox; + private JCheckBox visibleScanArcsCheckBox; + private JCheckBox visibleExplosionsCheckBox; + private JCheckBox visibleGroundCheckBox; + private JCheckBox visibleExplosionDebrisCheckBox; + private JCheckBox visibleSentryBorderCheckBox; + + private JButton defaultViewOptionsButton; + private JButton enableAllViewOptionsButton; + private JButton disableAllViewOptionsButton; + + private JTextField desiredTpsTextField; + private JLabel desiredTpsLabel; + private JCheckBox displayFpsCheckBox; + private JCheckBox displayTpsCheckBox; + + private JPanel visibleOptionsPanel; + private JPanel tpsOptionsPanel; + + private JButton minTpsButton; + private JButton defaultTpsButton; + private JButton fastTpsButton; + private JButton maxTpsButton; + + private JCheckBox preventSpeedupWhenMinimizedCheckBox; + + private final ISettingsManager properties; + + private class EventHandler implements ActionListener, DocumentListener { + public void actionPerformed(ActionEvent e) { + Object src = e.getSource(); + + if (src == enableAllViewOptionsButton) { + setAllViewOptionsButtonsEnabled(true); + } else if (src == disableAllViewOptionsButton) { + setAllViewOptionsButtonsEnabled(false); + } else if (src == defaultViewOptionsButton) { + defaultViewOptionsButtonActionPerformed(); + } else if (src == defaultTpsButton) { + defaultTpsButtonActionPerformed(); + } else if (src == minTpsButton) { + minTpsButtonActionPerformed(); + } else if (src == fastTpsButton) { + fastTpsButtonActionPerformed(); + } else if (src == maxTpsButton) { + maxTpsButtonActionPerformed(); + } + } + + public void changedUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void insertUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void removeUpdate(DocumentEvent e) { + fireStateChanged(); + } + } + + public PreferencesViewOptionsTab(ISettingsManager properties) { + super(); + this.properties = properties; + initialize(); + } + + private void defaultViewOptionsButtonActionPerformed() { + setAllViewOptionsButtonsEnabled(true); + getVisibleScanArcsCheckBox().setSelected(false); + } + + private void setAllViewOptionsButtonsEnabled(boolean enabled) { + getVisibleRobotEnergyCheckBox().setSelected(enabled); + getVisibleRobotNameCheckBox().setSelected(enabled); + getVisibleScanArcsCheckBox().setSelected(enabled); + getVisibleExplosionsCheckBox().setSelected(enabled); + getVisibleGroundCheckBox().setSelected(enabled); + getVisibleExplosionDebrisCheckBox().setSelected(enabled); + getVisibleSentryBorderCheckBox().setSelected(enabled); + } + + private void maxTpsButtonActionPerformed() { + getDesiredTpsTextField().setText("" + MAX_TPS); + } + + private void minTpsButtonActionPerformed() { + getDesiredTpsTextField().setText("" + MIN_TPS); + } + + private void fastTpsButtonActionPerformed() { + getDesiredTpsTextField().setText("" + FAST_TPS); + } + + private void defaultTpsButtonActionPerformed() { + getDesiredTpsTextField().setText("" + DEFAULT_TPS); + } + + private JButton getDefaultViewOptionsButton() { + if (defaultViewOptionsButton == null) { + defaultViewOptionsButton = new JButton("Defaults"); + defaultViewOptionsButton.setMnemonic('u'); + defaultViewOptionsButton.setDisplayedMnemonicIndex(4); + defaultViewOptionsButton.addActionListener(eventHandler); + } + return defaultViewOptionsButton; + } + + private JButton getEnableAllViewOptionsButton() { + if (enableAllViewOptionsButton == null) { + enableAllViewOptionsButton = new JButton("Enable all"); + enableAllViewOptionsButton.setMnemonic('a'); + enableAllViewOptionsButton.setDisplayedMnemonicIndex(7); + enableAllViewOptionsButton.addActionListener(eventHandler); + } + return enableAllViewOptionsButton; + } + + private JButton getDisableAllViewOptionsButton() { + if (disableAllViewOptionsButton == null) { + disableAllViewOptionsButton = new JButton("Disable all"); + disableAllViewOptionsButton.setMnemonic('i'); + disableAllViewOptionsButton.setDisplayedMnemonicIndex(1); + disableAllViewOptionsButton.addActionListener(eventHandler); + } + return disableAllViewOptionsButton; + } + + private JLabel getDesiredTpsLabel() { + if (desiredTpsLabel == null) { + desiredTpsLabel = new JLabel("Desired TPS (" + MIN_TPS + '-' + MAX_TPS + "): "); + } + return desiredTpsLabel; + } + + private JTextField getDesiredTpsTextField() { + if (desiredTpsTextField == null) { + desiredTpsTextField = new JTextField(); + desiredTpsTextField.setColumns(5); + desiredTpsTextField.getDocument().addDocumentListener(eventHandler); + + desiredTpsTextField.setInputVerifier( + new InputVerifier() { + @Override + public boolean verify(JComponent c) { + String text = desiredTpsTextField.getText(); + + int inputTps; + + try { + inputTps = new Integer(text); + } catch (NumberFormatException e) { + inputTps = -1; + } + return inputTps >= MIN_TPS && inputTps <= MAX_TPS; + } + + public boolean shouldYieldFocus(JComponent input) { + if (verify(input)) { + return true; + } + JOptionPane.showMessageDialog(null, + "The specified value for 'Desired TPS' (" + MIN_TPS + '-' + MAX_TPS + ") is invalid.", + "Invalid input", JOptionPane.ERROR_MESSAGE); + return false; + } + }); + } + return desiredTpsTextField; + } + + private JCheckBox getDisplayFpsCheckBox() { + if (displayFpsCheckBox == null) { + displayFpsCheckBox = new JCheckBox("Display FPS in titlebar"); + displayFpsCheckBox.setMnemonic('P'); + displayFpsCheckBox.setDisplayedMnemonicIndex(9); + } + return displayFpsCheckBox; + } + + private JCheckBox getDisplayTpsCheckBox() { + if (displayTpsCheckBox == null) { + displayTpsCheckBox = new JCheckBox("Display TPS in titlebar"); + displayTpsCheckBox.setMnemonic('T'); + displayTpsCheckBox.setDisplayedMnemonicIndex(8); + } + return displayTpsCheckBox; + } + + private JButton getDefaultTpsButton() { + if (defaultTpsButton == null) { + defaultTpsButton = new JButton("Default"); + defaultTpsButton.addActionListener(eventHandler); + } + return defaultTpsButton; + } + + private JButton getMinTpsButton() { + if (minTpsButton == null) { + minTpsButton = new JButton("Minimum"); + minTpsButton.addActionListener(eventHandler); + } + return minTpsButton; + } + + private JButton getMaxTpsButton() { + if (maxTpsButton == null) { + maxTpsButton = new JButton("Max"); + maxTpsButton.addActionListener(eventHandler); + } + return maxTpsButton; + } + + private JButton getFastTpsButton() { + if (fastTpsButton == null) { + fastTpsButton = new JButton("Fast"); + fastTpsButton.addActionListener(eventHandler); + } + return fastTpsButton; + } + + private JCheckBox getPreventSpeedupWhenMinimizedCheckBox() { + if (preventSpeedupWhenMinimizedCheckBox == null) { + preventSpeedupWhenMinimizedCheckBox = new JCheckBox("Prevent speedup when minimized"); + } + return preventSpeedupWhenMinimizedCheckBox; + } + + private JPanel getTpsOptionsPanel() { + if (tpsOptionsPanel == null) { + tpsOptionsPanel = new JPanel(); + tpsOptionsPanel.setBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Turns Per Second (TPS)")); + tpsOptionsPanel.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + + c.anchor = GridBagConstraints.NORTHWEST; + c.gridwidth = 4; + + tpsOptionsPanel.add(getDisplayTpsCheckBox(), c); + c.gridy = 1; + tpsOptionsPanel.add(getDisplayFpsCheckBox(), c); + + JPanel tpsPanel = new JPanel(); + + tpsPanel.add(getDesiredTpsLabel()); + tpsPanel.add(getDesiredTpsTextField()); + + c.fill = GridBagConstraints.VERTICAL; + c.gridy = 2; + c.insets = new Insets(10, 0, 0, 0); + tpsOptionsPanel.add(tpsPanel, c); + + c.fill = GridBagConstraints.NONE; + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.weightx = 0.25; + tpsOptionsPanel.add(getMinTpsButton(), c); + c.gridx = 1; + tpsOptionsPanel.add(getDefaultTpsButton(), c); + c.gridx = 2; + tpsOptionsPanel.add(getFastTpsButton(), c); + c.gridx = 3; + tpsOptionsPanel.add(getMaxTpsButton(), c); + + c.insets = new Insets(20, 0, 0, 0); + c.gridwidth = 4; + c.gridx = 0; + c.gridy = 4; + c.weighty = 1; + tpsOptionsPanel.add(getPreventSpeedupWhenMinimizedCheckBox(), c); + } + return tpsOptionsPanel; + } + + private JPanel getVisibleOptionsPanel() { + if (visibleOptionsPanel == null) { + visibleOptionsPanel = new JPanel(); + visibleOptionsPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Arena")); + visibleOptionsPanel.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + + c.anchor = GridBagConstraints.NORTHWEST; + c.gridwidth = GridBagConstraints.REMAINDER; + c.weightx = 1; + + visibleOptionsPanel.add(getVisibleRobotEnergyCheckBox(), c); + visibleOptionsPanel.add(getVisibleRobotNameCheckBox(), c); + visibleOptionsPanel.add(getVisibleScanArcsCheckBox(), c); + visibleOptionsPanel.add(getVisibleExplosionsCheckBox(), c); + visibleOptionsPanel.add(getVisibleGroundCheckBox(), c); + visibleOptionsPanel.add(getVisibleExplosionDebrisCheckBox(), c); + visibleOptionsPanel.add(getVisibleSentryBorderCheckBox(), c); + + c.insets = new Insets(10, 0, 0, 10); + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.weighty = 1; + c.weightx = 0; + visibleOptionsPanel.add(getEnableAllViewOptionsButton(), c); + visibleOptionsPanel.add(getDisableAllViewOptionsButton(), c); + visibleOptionsPanel.add(getDefaultViewOptionsButton(), c); + } + return visibleOptionsPanel; + } + + private JCheckBox getVisibleRobotEnergyCheckBox() { + if (visibleRobotEnergyCheckBox == null) { + visibleRobotEnergyCheckBox = new JCheckBox("Visible Robot Energy"); + visibleRobotEnergyCheckBox.setMnemonic('y'); + visibleRobotEnergyCheckBox.setDisplayedMnemonicIndex(19); + } + return visibleRobotEnergyCheckBox; + } + + private JCheckBox getVisibleRobotNameCheckBox() { + if (visibleRobotNameCheckBox == null) { + visibleRobotNameCheckBox = new JCheckBox("Visible Robot Name"); + visibleRobotNameCheckBox.setMnemonic('V'); + } + return visibleRobotNameCheckBox; + } + + private JCheckBox getVisibleScanArcsCheckBox() { + if (visibleScanArcsCheckBox == null) { + visibleScanArcsCheckBox = new JCheckBox("Visible Scan Arcs"); + visibleScanArcsCheckBox.setMnemonic('b'); + visibleScanArcsCheckBox.setDisplayedMnemonicIndex(4); + } + return visibleScanArcsCheckBox; + } + + private JCheckBox getVisibleExplosionsCheckBox() { + if (visibleExplosionsCheckBox == null) { + visibleExplosionsCheckBox = new JCheckBox("Visible Explosions"); + visibleExplosionsCheckBox.setMnemonic('x'); + visibleExplosionsCheckBox.setDisplayedMnemonicIndex(9); + } + return visibleExplosionsCheckBox; + } + + private JCheckBox getVisibleGroundCheckBox() { + if (visibleGroundCheckBox == null) { + visibleGroundCheckBox = new JCheckBox("Visible Ground"); + visibleGroundCheckBox.setMnemonic('G'); + visibleGroundCheckBox.setDisplayedMnemonicIndex(8); + } + return visibleGroundCheckBox; + } + + private JCheckBox getVisibleExplosionDebrisCheckBox() { + if (visibleExplosionDebrisCheckBox == null) { + visibleExplosionDebrisCheckBox = new JCheckBox("Visible Explosion Debris"); + visibleExplosionDebrisCheckBox.setMnemonic('E'); + visibleExplosionDebrisCheckBox.setDisplayedMnemonicIndex(8); + } + return visibleExplosionDebrisCheckBox; + } + + private JCheckBox getVisibleSentryBorderCheckBox() { + if (visibleSentryBorderCheckBox == null) { + visibleSentryBorderCheckBox = new JCheckBox("Visible Sentry Border"); + visibleSentryBorderCheckBox.setMnemonic('l'); + visibleSentryBorderCheckBox.setDisplayedMnemonicIndex(5); + } + return visibleSentryBorderCheckBox; + } + + private void initialize() { + setLayout(new GridLayout(1, 2)); + add(getVisibleOptionsPanel()); + add(getTpsOptionsPanel()); + + final ISettingsManager props = properties; + + loadPreferences(props); + + props.addPropertyListener(new ISettingsListener() { + public void settingChanged(String property) { + if (property.equals(ISettingsManager.OPTIONS_BATTLE_DESIREDTPS)) { + PreferencesViewOptionsTab.this.desiredTpsTextField.setText("" + props.getOptionsBattleDesiredTPS()); + } + } + }); + } + + private void loadPreferences(ISettingsManager robocodeProperties) { + getDisplayFpsCheckBox().setSelected(robocodeProperties.getOptionsViewFPS()); + getDisplayTpsCheckBox().setSelected(robocodeProperties.getOptionsViewTPS()); + getVisibleRobotNameCheckBox().setSelected(robocodeProperties.getOptionsViewRobotNames()); + getVisibleRobotEnergyCheckBox().setSelected(robocodeProperties.getOptionsViewRobotEnergy()); + getVisibleScanArcsCheckBox().setSelected(robocodeProperties.getOptionsViewScanArcs()); + getVisibleExplosionsCheckBox().setSelected(robocodeProperties.getOptionsViewExplosions()); + getVisibleGroundCheckBox().setSelected(robocodeProperties.getOptionsViewGround()); + getVisibleExplosionDebrisCheckBox().setSelected(robocodeProperties.getOptionsViewExplosionDebris()); + getVisibleSentryBorderCheckBox().setSelected(robocodeProperties.getOptionsViewSentryBorder()); + getDesiredTpsTextField().setText("" + robocodeProperties.getOptionsBattleDesiredTPS()); + getPreventSpeedupWhenMinimizedCheckBox().setSelected( + robocodeProperties.getOptionsViewPreventSpeedupWhenMinimized()); + } + + public void storePreferences() { + ISettingsManager props = properties; + + props.setOptionsViewFPS(getDisplayFpsCheckBox().isSelected()); + props.setOptionsViewTPS(getDisplayTpsCheckBox().isSelected()); + props.setOptionsViewRobotNames(getVisibleRobotNameCheckBox().isSelected()); + props.setOptionsViewRobotEnergy(getVisibleRobotEnergyCheckBox().isSelected()); + props.setOptionsViewScanArcs(getVisibleScanArcsCheckBox().isSelected()); + props.setOptionsViewExplosions(getVisibleExplosionsCheckBox().isSelected()); + props.setOptionsViewGround(getVisibleGroundCheckBox().isSelected()); + props.setOptionsViewExplosionDebris(getVisibleExplosionDebrisCheckBox().isSelected()); + props.setOptionsViewSentryBorder(getVisibleSentryBorderCheckBox().isSelected()); + props.setOptionsBattleDesiredTPS(Integer.parseInt(getDesiredTpsTextField().getText())); + props.setOptionsViewPreventSpeedupWhenMinimized(getPreventSpeedupWhenMinimizedCheckBox().isSelected()); + properties.saveProperties(); + } + + @Override + public boolean isReady() { + try { + int tps = Integer.parseInt(getDesiredTpsTextField().getText()); + + return (tps >= MIN_TPS && tps <= MAX_TPS); + } catch (Exception e) { + return false; + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RankingDialog.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RankingDialog.java new file mode 100644 index 0000000..66db429 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RankingDialog.java @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.battle.BattleRankingTableModel; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.ui.IWindowManager; +import robocode.control.events.BattleAdaptor; +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.ITurnSnapshot; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.concurrent.atomic.AtomicReference; + + +/** + * Frame to display the battle results or ranking during battles. + * + * @author Mathew A. Nelson (original) + * @author Luis Crespo (original) + * @author Flemming N. Larsen (contributor) + * @author Nathaniel Troutman (contributor) + */ +@SuppressWarnings("serial") +public class RankingDialog extends BaseScoreDialog { + private final BattleRankingTableModel tableModel; + private final Timer timerTask; + private final BattleObserver battleObserver; + private final AtomicReference snapshot; + private ITurnSnapshot lastSnapshot; + private int lastRows; + private final MenuBar menu; + private final IWindowManager windowManager; + + public RankingDialog(IWindowManager windowManager, ISettingsManager settingsManager, MenuBar menu) { + super(settingsManager.getOptionsCommonDontHideRankings() ? null : windowManager, false); + + initialize(); + + this.windowManager = windowManager; + battleObserver = new BattleObserver(); + timerTask = new Timer(1000 / 2, new TimerTask()); + snapshot = new AtomicReference(); + lastRows = 0; + tableModel = new BattleRankingTableModel(); + this.menu = menu; + setTitle("Ranking"); + } + + @Override + protected AbstractTableModel getTableModel() { + return tableModel; + } + + private void update() { + final ITurnSnapshot current = snapshot.get(); + + if (lastSnapshot != current) { + setResultsData(); + + lastSnapshot = current; + tableModel.updateSource(lastSnapshot); + if (table.getModel().getRowCount() != lastRows) { + lastRows = table.getModel().getRowCount(); + + table.setPreferredSize( + new Dimension(table.getColumnModel().getTotalColumnWidth(), + table.getModel().getRowCount() * table.getRowHeight())); + table.setPreferredScrollableViewportSize(table.getPreferredSize()); + pack(); + } + repaint(); + } + } + + protected void onDialogShown() { + windowManager.addBattleListener(battleObserver); + timerTask.start(); + } + + protected void onDialogHidden() { + menu.getOptionsShowRankingCheckBoxMenuItem().setState(false); + timerTask.stop(); + windowManager.removeBattleListener(battleObserver); + dispose(); + } + + private class BattleObserver extends BattleAdaptor { + @Override + public void onBattleFinished(BattleFinishedEvent event) { + snapshot.set(null); + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + snapshot.set(event.getTurnSnapshot()); + } + } + + + private class TimerTask implements ActionListener { + public void actionPerformed(ActionEvent e) { + update(); + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RcSplashScreen.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RcSplashScreen.java new file mode 100644 index 0000000..89f9729 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RcSplashScreen.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.ui.gfx.RobocodeLogo; +import net.sf.robocode.version.IVersionManager; + +import javax.swing.*; +import javax.swing.border.EtchedBorder; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.awt.image.BufferedImage; + + +/** + * The splash screen. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class RcSplashScreen extends JWindow { + + private final static Color LABEL_COLOR = Color.WHITE; + + private JLabel splashLabel; + private JPanel splashPanel; + private JPanel splashScreenContentPane; + private Image splashImage; + private final String version; + + private final transient WindowListener eventHandler = new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + if (e.getSource() == RcSplashScreen.this) { + RcSplashScreen.this.dispose(); + } + } + }; + + public RcSplashScreen(IVersionManager versionManager) { + super(); + this.version = versionManager.getVersion(); + initialize(); + } + + public JLabel getSplashLabel() { + if (splashLabel == null) { + splashLabel = new JLabel(); + splashLabel.setText(""); + splashLabel.setForeground(LABEL_COLOR); + splashLabel.setOpaque(false); + } + return splashLabel; + } + + private JPanel getSplashPanel() { + if (splashPanel == null) { + splashPanel = new JPanel() { + @Override + public void paintComponent(Graphics g) { + g.drawImage(splashImage, 0, 0, null); + g.setColor(LABEL_COLOR); + g.setFont(new Font("Arial", 1, 12)); + FontMetrics fm = g.getFontMetrics(); + + g.drawString("Version: " + version, + splashImage.getWidth(null) - fm.stringWidth("Version: " + version), + splashImage.getHeight(null) - 4); + } + + @Override + public Dimension getPreferredSize() { + return new Dimension(splashImage.getWidth(null), splashImage.getHeight(null)); + } + }; + splashPanel.setLayout(new BorderLayout()); + splashPanel.add(getSplashLabel(), BorderLayout.NORTH); + } + return splashPanel; + } + + private JPanel getSplashScreenContentPane() { + if (splashScreenContentPane == null) { + splashScreenContentPane = new JPanel(); + splashScreenContentPane.setBorder(new EtchedBorder()); + splashScreenContentPane.setLayout(new BorderLayout()); + splashScreenContentPane.add(getSplashPanel(), "Center"); + } + return splashScreenContentPane; + } + + private void initialize() { + splashImage = new BufferedImage(RobocodeLogo.WIDTH, RobocodeLogo.HEIGHT, BufferedImage.TYPE_INT_RGB); + new RobocodeLogo().paintLogoWithTanks(splashImage.getGraphics()); + + setContentPane(getSplashScreenContentPane()); + addWindowListener(eventHandler); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ResultsDialog.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ResultsDialog.java new file mode 100644 index 0000000..1c40a64 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ResultsDialog.java @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.battle.BattleResultsTableModel; +import net.sf.robocode.ui.IWindowManager; +import robocode.BattleResults; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; + + +/** + * Dialog to display results (scores) of a battle. + *

+ * This class is just a wrapper class used for storing the window position and + * dimension. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class ResultsDialog extends BaseScoreDialog { + + private JPanel buttonPanel; + private JButton okButton; + private JButton saveButton; + private BattleResultsTableModel tableModel; + private final ButtonEventHandler buttonEventHandler; + + public ResultsDialog(IWindowManager manager) { + super(manager, true); + buttonEventHandler = new ButtonEventHandler(); + initialize(); + addCancelByEscapeKey(); + } + + public void setup(BattleResults[] results, int numRounds) { + tableModel = new BattleResultsTableModel(results, numRounds); + setTitle(((BattleResultsTableModel) getTableModel()).getTitle()); + setResultsData(); + + table.setPreferredSize( + new Dimension(table.getColumnModel().getTotalColumnWidth(), + table.getModel().getRowCount() * table.getRowHeight())); + table.setPreferredScrollableViewportSize(table.getPreferredSize()); + } + + private void saveButtonActionPerformed() { + windowManager.showSaveResultsDialog(tableModel); + } + + private void okButtonActionPerformed() { + setVisible(false); + } + + @Override + protected AbstractTableModel getTableModel() { + return tableModel; + } + + @Override + protected JPanel getDialogContentPane() { + if (contentPane == null) { + contentPane = new JPanel(); + contentPane.setLayout(new BorderLayout()); + contentPane.add(getScrollPane(), "Center"); + contentPane.add(getButtonPanel(), "South"); + } + return contentPane; + } + + private JPanel getButtonPanel() { + if (buttonPanel == null) { + buttonPanel = new JPanel(); + buttonPanel.setLayout(new BorderLayout()); + buttonPanel.add(getOkButton(), "East"); + buttonPanel.add(getSaveButton(), "West"); + } + return buttonPanel; + } + + private JButton getOkButton() { + if (okButton == null) { + okButton = new JButton(); + okButton.setText("OK"); + okButton.addActionListener(buttonEventHandler); + WindowUtil.setFixedSize(okButton, new Dimension(80, 25)); + } + return okButton; + } + + private JButton getSaveButton() { + if (saveButton == null) { + saveButton = new JButton(); + saveButton.setText("Save"); + saveButton.addActionListener(buttonEventHandler); + WindowUtil.setFixedSize(saveButton, new Dimension(80, 25)); + } + return saveButton; + } + + private void addCancelByEscapeKey() { + String CANCEL_ACTION_KEY = "CANCEL_ACTION_KEY"; + int noModifiers = 0; + KeyStroke escapeKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, noModifiers, false); + InputMap inputMap = getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + + inputMap.put(escapeKey, CANCEL_ACTION_KEY); + AbstractAction cancelAction = new AbstractAction() { + public void actionPerformed(ActionEvent e) { + okButtonActionPerformed(); + } + }; + + getRootPane().getActionMap().put(CANCEL_ACTION_KEY, cancelAction); + } + + private class ButtonEventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + + if (source == ResultsDialog.this.getOkButton()) { + okButtonActionPerformed(); + } else if (source == ResultsDialog.this.getSaveButton()) { + saveButtonActionPerformed(); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ResultsTableCellRenderer.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ResultsTableCellRenderer.java new file mode 100644 index 0000000..1d99f65 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/ResultsTableCellRenderer.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.*; +import javax.swing.border.EtchedBorder; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.*; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class ResultsTableCellRenderer extends DefaultTableCellRenderer { + + private final boolean isBordered; + + public ResultsTableCellRenderer(boolean isBordered) { + super(); + this.isBordered = isBordered; + setHorizontalAlignment(SwingConstants.CENTER); + setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0)); + } + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, + boolean hasFocus, int row, int column) { + if (isBordered) { + setBorder(new EtchedBorder(EtchedBorder.RAISED)); + setBackground(SystemColor.menu); + setForeground(SystemColor.menuText); + } else if (isSelected) { + setBackground(SystemColor.textHighlight); + setForeground(SystemColor.textHighlightText); + } else { + setBackground(SystemColor.text); + setForeground(SystemColor.textText); + } + setText(value.toString()); + + return this; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobocodeFrame.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobocodeFrame.java new file mode 100644 index 0000000..23f6f82 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobocodeFrame.java @@ -0,0 +1,1011 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.recording.IRecordManager; +import net.sf.robocode.settings.ISettingsManager; +import net.sf.robocode.settings.ISettingsListener; +import net.sf.robocode.ui.*; +import net.sf.robocode.ui.battleview.BattleView; +import net.sf.robocode.ui.battleview.InteractiveHandler; +import net.sf.robocode.ui.battleview.ScreenshotUtil; +import net.sf.robocode.ui.gfx.ImageUtil; +import net.sf.robocode.version.IVersionManager; +import net.sf.robocode.version.Version; +import robocode.control.events.*; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.*; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryUsage; +import java.util.*; +import java.util.List; + + +/** + * @author Mathew Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Matthew Reeder (contributor) + * @author Luis Crespo (contributor) + * @author Pavel Savara (contributor) + */ +@SuppressWarnings("serial") +public class RobocodeFrame extends JFrame { + + private final static int MAX_TPS = 10000; + private final static int MAX_TPS_SLIDER_VALUE = 61; + + private final static int UPDATE_TITLE_INTERVAL = 500; // milliseconds + private final static String INSTALL_URL = "http://robocode.sourceforge.net/installer"; + + private static final Cursor BUSY_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); + private static final Cursor DEFAULT_CURSOR = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); + + private final EventHandler eventHandler = new EventHandler(); + private BattleObserver battleObserver; + + private final InteractiveHandler interactiveHandler; + + private JPanel robocodeContentPane; + private JLabel statusLabel; + + private JScrollPane robotButtonsScrollPane; + + private JPanel mainPanel; + private JPanel battleViewPanel; + private JPanel sidePanel; + private JPanel robotButtonsPanel; + + private JToolBar toolBar; + + private JToggleButton pauseButton; + private JButton nextTurnButton; + private JButton stopButton; + private JButton restartButton; + private JButton replayButton; + + private JSlider tpsSlider; + private JLabel tpsLabel; + + private boolean iconified; + private boolean exitOnClose = true; + + private final ISettingsManager properties; + + private final IWindowManagerExt windowManager; + private final IVersionManager versionManager; + private final IBattleManager battleManager; + private final IRobotDialogManager dialogManager; + private final IRecordManager recordManager; + private final BattleView battleView; + private final MenuBar menuBar; + + final List robotButtons = new ArrayList(); + + public RobocodeFrame(ISettingsManager properties, + IWindowManager windowManager, + IRobotDialogManager dialogManager, + IVersionManager versionManager, + IBattleManager battleManager, + IRecordManager recordManager, + InteractiveHandler interactiveHandler, + MenuBar menuBar, + BattleView battleView + ) { + this.windowManager = (IWindowManagerExt) windowManager; + this.properties = properties; + this.interactiveHandler = interactiveHandler; + this.versionManager = versionManager; + this.battleManager = battleManager; + this.dialogManager = dialogManager; + this.recordManager = recordManager; + this.battleView = battleView; + this.menuBar = menuBar; + menuBar.setup(this); + initialize(); + } + + protected void finalize() throws Throwable { + try { + windowManager.removeBattleListener(battleObserver); + } finally { + super.finalize(); + } + } + + public void setBusyPointer(boolean enabled) { + setCursor(enabled ? BUSY_CURSOR : DEFAULT_CURSOR); + } + + public void addRobotButton(JButton b) { + if (b instanceof RobotButton) { + robotButtons.add((RobotButton) b); + } + getRobotButtonsPanel().add(b); + b.setVisible(true); + getRobotButtonsPanel().validate(); + } + + public void checkUpdateOnStart() { + if (!isIconified()) { + Date lastCheckedDate = properties.getVersionChecked(); + + Date today = new Date(); + + if (lastCheckedDate == null) { + lastCheckedDate = today; + properties.setVersionChecked(lastCheckedDate); + properties.saveProperties(); + } + Calendar checkDate = Calendar.getInstance(); + + checkDate.setTime(lastCheckedDate); + checkDate.add(Calendar.DATE, 5); + + if (checkDate.getTime().before(today) && checkForNewVersion(false)) { + properties.setVersionChecked(today); + properties.saveProperties(); + } + } + } + + public boolean checkForNewVersion(boolean notifyNoUpdate) { + String currentVersion = versionManager.getVersion(); + String newVersion = versionManager.checkForNewVersion(); + + boolean newVersionAvailable = false; + + if (newVersion != null && currentVersion != null) { + if (Version.compare(newVersion, currentVersion) > 0) { + newVersionAvailable = true; + if (Version.isFinal(newVersion) + || (Version.isBeta(newVersion) && properties.getOptionsCommonNotifyAboutNewBetaVersions())) { + showNewVersion(newVersion); + } + } + } + if (notifyNoUpdate && !newVersionAvailable) { + showLatestVersion(currentVersion); + } + return true; + } + + public void takeScreenshot() { + setBusyPointer(true); + try { + ScreenshotUtil.saveScreenshot(battleView.getScreenshot(), "PNG", 1); + } finally { + setBusyPointer(false); + } + } + + private void showLatestVersion(String version) { + JOptionPane.showMessageDialog(this, "You have version " + version + ". This is the latest version of Robocode.", + "No update available", JOptionPane.INFORMATION_MESSAGE); + } + + private void showNewVersion(String newVersion) { + if (JOptionPane.showConfirmDialog(this, + "Version " + newVersion + " of Robocode is now available. Would you like to download it?", + "Version " + newVersion + " available", JOptionPane.YES_NO_OPTION) + == JOptionPane.YES_OPTION) { + try { + BrowserManager.openURL(INSTALL_URL); + } catch (IOException e) { + JOptionPane.showMessageDialog(this, e.getMessage(), "Unable to open browser!", + JOptionPane.INFORMATION_MESSAGE); + } + } else if (Version.isFinal(newVersion)) { + JOptionPane.showMessageDialog(this, + "It is highly recommended that you always download the latest version. You may get it at " + INSTALL_URL, + "Update when you can!", JOptionPane.INFORMATION_MESSAGE); + } + } + + /** + * Rather than use a layout manager for the battleview panel, we just + * calculate the proper aspect ratio and set the battleview's size. We could + * use a layout manager if someone wants to write one... + */ + private void battleViewPanelResized() { + battleView.setBounds(getBattleViewPanel().getBounds()); + } + + /** + * Return the MainPanel (which contains the BattleView and the robot + * buttons) + * + * @return JPanel + */ + private JPanel getMainPanel() { + if (mainPanel == null) { + mainPanel = new JPanel(); + mainPanel.setLayout(new BorderLayout()); + mainPanel.add(getSidePanel(), BorderLayout.EAST); + mainPanel.add(getBattleViewPanel()); + } + return mainPanel; + } + + /** + * Return the BattleViewMainPanel (which contains the BattleView and a + * spacer) + * + * @return JPanel + */ + private JPanel getBattleViewPanel() { + if (battleViewPanel == null) { + battleViewPanel = new JPanel(); + battleViewPanel.setPreferredSize(new Dimension(800, 600)); + battleViewPanel.setLayout(null); + battleViewPanel.add(battleView); + battleViewPanel.addComponentListener(eventHandler); + } + return battleViewPanel; + } + + /** + * Return the JFrameContentPane. + * + * @return JPanel + */ + private JPanel getRobocodeContentPane() { + if (robocodeContentPane == null) { + robocodeContentPane = new JPanel(); + robocodeContentPane.setLayout(new BorderLayout()); + robocodeContentPane.add(getToolBar(), "South"); + robocodeContentPane.add(getMainPanel(), "Center"); + } + return robocodeContentPane; + } + + /** + * Return the sidePanel. + * + * @return JPanel + */ + private JPanel getSidePanel() { + if (sidePanel == null) { + sidePanel = new JPanel(); + sidePanel.setLayout(new BorderLayout()); + sidePanel.add(getRobotButtonsScrollPane(), BorderLayout.CENTER); + final BattleButton btn = net.sf.robocode.core.Container.getComponent(BattleButton.class); + + btn.attach(); + sidePanel.add(btn, BorderLayout.SOUTH); + } + return sidePanel; + } + + /** + * Return the robotButtons panel. + * + * @return JPanel + */ + private JPanel getRobotButtonsPanel() { + if (robotButtonsPanel == null) { + robotButtonsPanel = new JPanel(); + robotButtonsPanel.setLayout(new BoxLayout(robotButtonsPanel, BoxLayout.Y_AXIS)); + robotButtonsPanel.addContainerListener(eventHandler); + } + return robotButtonsPanel; + } + + /** + * Return the robotButtonsScrollPane + * + * @return JScrollPane + */ + private JScrollPane getRobotButtonsScrollPane() { + if (robotButtonsScrollPane == null) { + robotButtonsScrollPane = new JScrollPane(); + robotButtonsScrollPane.setAutoscrolls(false); + robotButtonsScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + robotButtonsScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + robotButtonsScrollPane.setAlignmentY(Component.TOP_ALIGNMENT); + robotButtonsScrollPane.setMaximumSize(new Dimension(113, 32767)); + robotButtonsScrollPane.setPreferredSize(new Dimension(113, 28)); + robotButtonsScrollPane.setAlignmentX(Component.CENTER_ALIGNMENT); + robotButtonsScrollPane.setMinimumSize(new Dimension(113, 53)); + robotButtonsScrollPane.setViewportView(getRobotButtonsPanel()); + } + return robotButtonsScrollPane; + } + + /** + * Return the statusLabel + * + * @return JLabel + */ + public JLabel getStatusLabel() { + if (statusLabel == null) { + statusLabel = new JLabel(); + statusLabel.setText(""); + } + return statusLabel; + } + + /** + * Return the pauseButton + * + * @return JToggleButton + */ + private JToggleButton getPauseButton() { + if (pauseButton == null) { + pauseButton = new JToggleButton("Pause/Debug"); + pauseButton.setMnemonic('P'); + pauseButton.setHorizontalTextPosition(SwingConstants.CENTER); + pauseButton.setVerticalTextPosition(SwingConstants.BOTTOM); + pauseButton.addActionListener(eventHandler); + } + return pauseButton; + } + + /** + * Return the nextTurnButton + * + * @return JButton + */ + private Component getNextTurnButton() { + if (nextTurnButton == null) { + nextTurnButton = new JButton("Next Turn"); + nextTurnButton.setMnemonic('N'); + nextTurnButton.setHorizontalTextPosition(SwingConstants.CENTER); + nextTurnButton.setVerticalTextPosition(SwingConstants.BOTTOM); + nextTurnButton.addActionListener(eventHandler); + + nextTurnButton.setEnabled(false); + } + return nextTurnButton; + } + + /** + * Return the stopButton + * + * @return JButton + */ + private JButton getStopButton() { + if (stopButton == null) { + stopButton = new JButton("Stop"); + stopButton.setMnemonic('S'); + stopButton.setHorizontalTextPosition(SwingConstants.CENTER); + stopButton.setVerticalTextPosition(SwingConstants.BOTTOM); + stopButton.addActionListener(eventHandler); + + stopButton.setEnabled(false); + } + return stopButton; + } + + /** + * Return the restartButton + * + * @return JButton + */ + private JButton getRestartButton() { + if (restartButton == null) { + restartButton = new JButton("Restart"); + restartButton.setMnemonic('t'); + restartButton.setDisplayedMnemonicIndex(3); + restartButton.setHorizontalTextPosition(SwingConstants.CENTER); + restartButton.setVerticalTextPosition(SwingConstants.BOTTOM); + restartButton.addActionListener(eventHandler); + + restartButton.setEnabled(false); + } + return restartButton; + } + + /** + * Return the replayButton + * + * @return JButton + */ + public JButton getReplayButton() { + if (replayButton == null) { + replayButton = new JButton("Replay"); + replayButton.setMnemonic('y'); + replayButton.setDisplayedMnemonicIndex(5); + replayButton.setHorizontalTextPosition(SwingConstants.CENTER); + replayButton.setVerticalTextPosition(SwingConstants.BOTTOM); + replayButton.addActionListener(eventHandler); + + ISettingsManager props = properties; + + replayButton.setVisible(props.getOptionsCommonEnableReplayRecording()); + + props.addPropertyListener(new ISettingsListener() { + public void settingChanged(String property) { + if (property.equals(ISettingsManager.OPTIONS_COMMON_ENABLE_REPLAY_RECORDING)) { + replayButton.setVisible(properties.getOptionsCommonEnableReplayRecording()); + } + } + }); + + replayButton.setEnabled(false); + } + return replayButton; + } + + /** + * Return the tpsSlider + * + * @return JSlider + */ + private JSlider getTpsSlider() { + if (tpsSlider == null) { + final ISettingsManager props = properties; + + int tps = Math.max(props.getOptionsBattleDesiredTPS(), 1); + + tpsSlider = new JSlider(0, MAX_TPS_SLIDER_VALUE, tpsToSliderValue(tps)); + tpsSlider.setPaintLabels(true); + tpsSlider.setPaintTicks(true); + tpsSlider.setMinorTickSpacing(1); + + tpsSlider.addChangeListener(eventHandler); + + Dictionary labels = new Hashtable(); + + labels.put(0, new JLabel("0")); + labels.put(5, new JLabel("5")); + labels.put(10, new JLabel("10")); + labels.put(15, new JLabel("15")); + labels.put(20, new JLabel("20")); + labels.put(25, new JLabel("25")); + labels.put(30, new JLabel("30")); + labels.put(35, new JLabel("40")); + labels.put(40, new JLabel("50")); + labels.put(45, new JLabel("65")); + labels.put(50, new JLabel("90")); + labels.put(55, new JLabel("150")); + labels.put(60, new JLabel("1000")); + + tpsSlider.setMajorTickSpacing(5); + tpsSlider.setLabelTable(labels); + + WindowUtil.setFixedSize(tpsSlider, new Dimension((MAX_TPS_SLIDER_VALUE + 1) * 6, 40)); + + props.addPropertyListener(new ISettingsListener() { + public void settingChanged(String property) { + if (property.equals(ISettingsManager.OPTIONS_BATTLE_DESIREDTPS)) { + setTpsOnSlider(props.getOptionsBattleDesiredTPS()); + } + } + }); + } + return tpsSlider; + } + + /** + * Return the tpsLabel + * + * @return JLabel + */ + private JLabel getTpsLabel() { + if (tpsLabel == null) { + tpsLabel = new JLabel(getTpsFromSliderAsString()); + } + return tpsLabel; + } + + /** + * Return the toolBar. + * + * @return JToolBar + */ + private JToolBar getToolBar() { + if (toolBar == null) { + toolBar = new JToolBar(); + toolBar.add(getPauseButton()); + toolBar.add(getNextTurnButton()); + toolBar.add(getStopButton()); + toolBar.add(getRestartButton()); + toolBar.add(getReplayButton()); + + toolBar.addSeparator(); + + toolBar.add(getTpsSlider()); + toolBar.add(getTpsLabel()); + + toolBar.addSeparator(); + + toolBar.add(getStatusLabel()); + WindowUtil.setDefaultStatusLabel(getStatusLabel()); + } + return toolBar; + } + + /** + * Initialize the class. + */ + private void initialize() { + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + setTitle("Robocode"); + setIconImage(ImageUtil.getImage("/net/sf/robocode/ui/icons/robocode-icon.png")); + setResizable(true); + setVisible(false); + + setContentPane(getRobocodeContentPane()); + setJMenuBar(menuBar); + + battleObserver = new BattleObserver(); + + addWindowListener(eventHandler); + + battleView.addMouseListener(interactiveHandler); + battleView.addMouseMotionListener(interactiveHandler); + battleView.addMouseWheelListener(interactiveHandler); + battleView.setFocusable(true); + KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(interactiveHandler); + + if (windowManager.isSlave()) { + menuBar.getBattleMenu().setEnabled(false); + menuBar.getRobotMenu().setEnabled(false); + getStopButton().setEnabled(false); + getPauseButton().setEnabled(false); + getNextTurnButton().setEnabled(false); + getRestartButton().setEnabled(false); + getReplayButton().setEnabled(false); + exitOnClose = false; + } + } + + private void pauseResumeButtonActionPerformed() { + battleManager.togglePauseResumeBattle(); + } + + /** + * Gets the iconified. + * + * @return Returns a boolean + */ + public boolean isIconified() { + return iconified; + } + + public void afterIntroBattle() { + getRestartButton().setEnabled(false); + getRobotButtonsPanel().removeAll(); + getRobotButtonsPanel().repaint(); + } + + /** + * Sets the iconified. + * + * @param iconified The iconified to set + */ + private void setIconified(boolean iconified) { + this.iconified = iconified; + } + + private int getTpsFromSlider() { + final int value = getTpsSlider().getValue(); + + if (value <= 30) { + return value; + } + if (value <= 40) { + return 2 * value - 30; + } + if (value <= 45) { + return 3 * value - 70; + } + if (value <= 52) { + return 5 * value - 160; + } + switch (value) { + case 53: + return 110; + + case 54: + return 130; + + case 55: + return 150; + + case 56: + return 200; + + case 57: + return 300; + + case 58: + return 500; + + case 59: + return 750; + + case 60: + return 1000; + } + return MAX_TPS; + } + + private void setTpsOnSlider(int tps) { + tpsSlider.setValue(tpsToSliderValue(tps)); + } + + private int tpsToSliderValue(int tps) { + if (tps <= 30) { + return tps; + } + if (tps <= 50) { + return (tps + 30) / 2; + } + if (tps <= 65) { + return (tps + 70) / 3; + } + if (tps <= 100) { + return (tps + 160) / 5; + } + if (tps <= 110) { + return 53; + } + if (tps <= 130) { + return 54; + } + if (tps <= 150) { + return 55; + } + if (tps <= 200) { + return 56; + } + if (tps <= 300) { + return 57; + } + if (tps <= 500) { + return 58; + } + if (tps <= 750) { + return 59; + } + if (tps <= 1000) { + return 60; + } + return MAX_TPS_SLIDER_VALUE; + } + + private String getTpsFromSliderAsString() { + int tps = getTpsFromSlider(); + + return " " + ((tps == MAX_TPS) ? "max" : "" + tps) + " "; + } + + private class EventHandler implements ComponentListener, ActionListener, ContainerListener, WindowListener, + ChangeListener { + + public void actionPerformed(ActionEvent e) { + final Object source = e.getSource(); + + if (source == getPauseButton()) { + pauseResumeButtonActionPerformed(); + } else if (source == getStopButton()) { + battleManager.stop(false); + } else if (source == getRestartButton()) { + battleManager.restart(); + } else if (source == getNextTurnButton()) { + battleManager.nextTurn(); + } else if (source == getReplayButton()) { + battleManager.replay(); + } + } + + public void componentResized(ComponentEvent e) { + if (e.getSource() == getBattleViewPanel()) { + battleViewPanelResized(); + } + } + + public void componentShown(ComponentEvent e) {} + + public void componentHidden(ComponentEvent e) {} + + public void componentRemoved(ContainerEvent e) {} + + public void componentAdded(ContainerEvent e) {} + + public void componentMoved(ComponentEvent e) {} + + public void windowActivated(WindowEvent e) {} + + public void windowClosed(WindowEvent e) { + if (exitOnClose) { + System.exit(0); + } + } + + public void windowClosing(WindowEvent e) { + exitOnClose = true; + if (windowManager.isSlave()) { + WindowUtil.message("If you wish to exit Robocode, please exit the program controlling it."); + exitOnClose = false; + return; + } + if (windowManager.closeRobocodeEditor()) { + WindowUtil.saveWindowPositions(); + battleObserver = null; + dispose(); + } + properties.saveProperties(); + } + + public void windowDeactivated(WindowEvent e) {} + + public void windowDeiconified(WindowEvent e) { + setIconified(false); + battleManager.setManagedTPS(true); + } + + public void windowIconified(WindowEvent e) { + setIconified(true); + battleManager.setManagedTPS(properties.getOptionsViewPreventSpeedupWhenMinimized()); + } + + public void windowOpened(WindowEvent e) { + battleManager.setManagedTPS(true); + } + + public void stateChanged(ChangeEvent e) { + if (e.getSource() == getTpsSlider()) { + int tps = getTpsFromSlider(); + + // TODO refactor + if (tps == 0) { + battleManager.pauseIfResumedBattle(); + } else { + // Only set desired TPS if it is not set to zero + properties.setOptionsBattleDesiredTPS(tps); + battleManager.resumeIfPausedBattle(); // TODO causing problems when called from PreferencesViewOptionsTab.storePreferences() + } + + tpsLabel.setText(getTpsFromSliderAsString()); + } + } + } + + + private class BattleObserver extends BattleAdaptor { + private int tps; + private int currentRound; + private int numberOfRounds; + private int currentTurn; + private boolean isBattleRunning; + private boolean isBattlePaused; + private boolean isBattleReplay; + private long lastTitleUpdateTime; + + public BattleObserver() { + windowManager.addBattleListener(this); + } + + protected void finalize() throws Throwable { + try { + windowManager.removeBattleListener(this); + } finally { + super.finalize(); + } + } + + @Override + public void onBattleStarted(BattleStartedEvent event) { + numberOfRounds = event.getBattleRules().getNumRounds(); + isBattleRunning = true; + isBattleReplay = event.isReplay(); + + getStopButton().setEnabled(true); + getRestartButton().setEnabled(battleManager.getBattleProperties().getSelectedRobots() != null); + getReplayButton().setEnabled(event.isReplay()); + menuBar.getBattleSaveRecordAsMenuItem().setEnabled(false); + menuBar.getBattleExportRecordMenuItem().setEnabled(false); + menuBar.getBattleSaveAsMenuItem().setEnabled(true); + menuBar.getBattleSaveMenuItem().setEnabled(true); + + JCheckBoxMenuItem rankingCheckBoxMenuItem = menuBar.getOptionsShowRankingCheckBoxMenuItem(); + + rankingCheckBoxMenuItem.setEnabled(!isBattleReplay); + if (rankingCheckBoxMenuItem.isSelected()) { + windowManager.showRankingDialog(!isBattleReplay); + } + + validate(); + + updateTitle(); + } + + public void onRoundStarted(final RoundStartedEvent event) { + if (event.getRound() == 0) { + getRobotButtonsPanel().removeAll(); + + final List robots = Arrays.asList(event.getStartSnapshot().getRobots()); + + dialogManager.trim(robots); + + int maxEnergy = 0; + + for (IRobotSnapshot robot : robots) { + if (maxEnergy < robot.getEnergy()) { + maxEnergy = (int) robot.getEnergy(); + } + } + if (maxEnergy == 0) { + maxEnergy = 1; + } + for (int index = 0; index < robots.size(); index++) { + final IRobotSnapshot robot = robots.get(index); + final boolean attach = index < RobotDialogManager.MAX_PRE_ATTACHED; + final RobotButton button = net.sf.robocode.core.Container.createComponent(RobotButton.class); + + button.setup(robot.getName(), maxEnergy, index, robot.getContestantIndex(), attach); + button.setText(robot.getShortName()); + addRobotButton(button); + } + getRobotButtonsPanel().repaint(); + } + } + + @Override + public void onBattleFinished(BattleFinishedEvent event) { + isBattleRunning = false; + + for (RobotButton robotButton : robotButtons) { + robotButton.detach(); + } + robotButtons.clear(); + + final boolean canReplayRecord = recordManager.hasRecord(); + final boolean enableSaveRecord = (properties.getOptionsCommonEnableReplayRecording() & canReplayRecord); + + getStopButton().setEnabled(false); + getReplayButton().setEnabled(canReplayRecord); + getNextTurnButton().setEnabled(false); + + menuBar.getBattleSaveRecordAsMenuItem().setEnabled(enableSaveRecord); + menuBar.getBattleExportRecordMenuItem().setEnabled(enableSaveRecord); + menuBar.getOptionsShowRankingCheckBoxMenuItem().setEnabled(false); + + updateTitle(); + } + + @Override + public void onBattlePaused(BattlePausedEvent event) { + isBattlePaused = true; + + getPauseButton().setSelected(true); + getNextTurnButton().setEnabled(true); + + updateTitle(); + } + + @Override + public void onBattleResumed(BattleResumedEvent event) { + isBattlePaused = false; + + getPauseButton().setSelected(false); + getNextTurnButton().setEnabled(false); + + // TODO: Refactor? + if (getTpsFromSlider() == 0) { + setTpsOnSlider(1); + } + + updateTitle(); + } + + public void onTurnEnded(TurnEndedEvent event) { + if (event == null) { + return; + } + final ITurnSnapshot turn = event.getTurnSnapshot(); + + if (turn == null) { + return; + } + + tps = event.getTurnSnapshot().getTPS(); + currentRound = event.getTurnSnapshot().getRound(); + currentTurn = event.getTurnSnapshot().getTurn(); + + // Only update every half second to spare CPU cycles + if ((System.currentTimeMillis() - lastTitleUpdateTime) >= UPDATE_TITLE_INTERVAL) { + updateTitle(); + } + } + + private void updateTitle() { + StringBuffer title = new StringBuffer("Robocode"); + + if (isBattleRunning) { + title.append(": "); + + if (currentTurn == 0) { + title.append("Starting round"); + } else { + if (isBattleReplay) { + title.append("Replaying: "); + } + title.append("Turn "); + title.append(currentTurn); + + title.append(", Round "); + title.append(currentRound + 1).append(" of ").append(numberOfRounds); + + if (!isBattlePaused) { + boolean dispTps = properties.getOptionsViewTPS(); + boolean dispFps = properties.getOptionsViewFPS(); + + if (dispTps | dispFps) { + title.append(", "); + + if (dispTps) { + title.append(tps).append(" TPS"); + } + if (dispTps & dispFps) { + title.append(", "); + } + if (dispFps) { + title.append(windowManager.getFPS()).append(" FPS"); + } + } + } + } + } + if (isBattlePaused) { + title.append(" (paused)"); + } + + MemoryUsage memUsage = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + + long usedMem = memUsage.getUsed() / (1024 * 1024); + + title.append(", Used mem: ").append(usedMem); + + long maxMem = memUsage.getMax(); + + if (maxMem >= 0) { + maxMem /= (1024 * 1024); + title.append(" of ").append(maxMem); + } + title.append(" MB"); + + setTitle(title.toString()); + + lastTitleUpdateTime = System.currentTimeMillis(); + } + + @Override + public void onBattleCompleted(BattleCompletedEvent event) { + if (windowManager.isShowResultsEnabled()) { + // show on ATW thread + ResultsTask resultTask = new ResultsTask(event); + + EventQueue.invokeLater(resultTask); + } + } + + private class ResultsTask implements Runnable { + final BattleCompletedEvent event; + + ResultsTask(BattleCompletedEvent event) { + this.event = event; + } + + public void run() { + windowManager.showResultsDialog(event); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotButton.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotButton.java new file mode 100644 index 0000000..16e5e38 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotButton.java @@ -0,0 +1,228 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.ui.IRobotDialogManager; +import net.sf.robocode.ui.IWindowManager; +import net.sf.robocode.ui.IWindowManagerExt; +import robocode.BattleResults; +import robocode.control.events.BattleAdaptor; +import robocode.control.events.BattleCompletedEvent; +import robocode.control.events.BattleFinishedEvent; +import robocode.control.events.TurnEndedEvent; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.snapshot.IScoreSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class RobotButton extends JButton implements ActionListener { + + private static final int BAR_MARGIN = 2; + private static final int BAR_HEIGHT = 3; + + private final IWindowManagerExt windowManager; + private final IBattleManager battleManager; + private final BattleObserver battleObserver = new BattleObserver(); + private final IRobotDialogManager dialogManager; + private RobotDialog robotDialog; + private String name; + private int robotIndex; + private int contestantIndex; + private int maxEnergy = 1; + private int maxScore = 1; + private int lastEnergy; + private int lastScore; + private boolean isListening; + + public RobotButton(IWindowManager windowManager, IBattleManager battleManager, IRobotDialogManager dialogManager) { + this.windowManager = (IWindowManagerExt) windowManager; + this.battleManager = battleManager; + this.dialogManager = dialogManager; + } + + public void setup(String name, int maxEnergy, int robotIndex, int contestantIndex, boolean attach) { + this.name = name; + this.robotIndex = robotIndex; + this.contestantIndex = contestantIndex; + this.lastEnergy = maxEnergy; + this.maxEnergy = maxEnergy; + initialize(); + if (attach) { + attach(); + robotDialog.reset(); + battleManager.setPaintEnabled(robotIndex, robotDialog.isPaintEnabled()); + battleManager.setSGPaintEnabled(robotIndex, robotDialog.isSGPaintEnabled()); + } + } + + public void actionPerformed(ActionEvent e) { + if (robotDialog == null) { + attach(); + if (!robotDialog.isVisible() || robotDialog.getState() != Frame.NORMAL) { + WindowUtil.packPlaceShow(robotDialog); + } + } else { + robotDialog.setVisible(true); + } + } + + @Override + public void paint(Graphics g) { + super.paint(g); + + Graphics2D g2 = (Graphics2D) g; + + final int barMaxWidth = getWidth() - (2 * BAR_MARGIN); + + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f)); + + if (lastEnergy > 0) { + Color color; + + if (lastEnergy > 50) { + color = Color.GREEN; + } else if (lastEnergy > 25) { + color = Color.YELLOW; + } else { + color = Color.RED; + } + g.setColor(color); + + final int widthLife = Math.max(Math.min(barMaxWidth * lastEnergy / maxEnergy, barMaxWidth), 0); + + g.fillRect(BAR_MARGIN, getHeight() - (2 * BAR_HEIGHT + BAR_MARGIN), widthLife, BAR_HEIGHT); + } + if (lastScore > 0) { + g.setColor(Color.BLUE); + + final int widthScore = Math.max(Math.min(barMaxWidth * lastScore / maxScore, barMaxWidth), 0); + + g.fillRect(BAR_MARGIN, getHeight() - (BAR_HEIGHT + BAR_MARGIN), widthScore, BAR_HEIGHT); + } + } + + /** + * Initialize the class. + */ + private void initialize() { + addActionListener(this); + setPreferredSize(new Dimension(110, 25)); + setMinimumSize(new Dimension(110, 25)); + setMaximumSize(new Dimension(110, 25)); + setHorizontalAlignment(SwingConstants.LEFT); + setMargin(new Insets(0, 0, 0, 0)); + setToolTipText(name); + } + + public void attach() { + if (!isListening) { + isListening = true; + windowManager.addBattleListener(battleObserver); + } + if (robotDialog == null) { + robotDialog = dialogManager.getRobotDialog(this, name, true); + } + robotDialog.attach(this); + } + + public void detach() { + if (isListening) { + windowManager.removeBattleListener(battleObserver); + isListening = false; + } + if (robotDialog != null) { + final RobotDialog dialog = robotDialog; + + robotDialog = null; + dialog.detach(); + } + } + + public int getRobotIndex() { + return robotIndex; + } + + public String getRobotName() { + return name; + } + + private class BattleObserver extends BattleAdaptor { + + @Override + public void onTurnEnded(TurnEndedEvent event) { + final ITurnSnapshot turn = event.getTurnSnapshot(); + + if (turn == null) { + return; + } + final IRobotSnapshot[] robots = turn.getRobots(); + final IScoreSnapshot[] scoreSnapshotList = event.getTurnSnapshot().getIndexedTeamScores(); + + maxEnergy = 0; + for (IRobotSnapshot robot : robots) { + if (maxEnergy < robot.getEnergy()) { + maxEnergy = (int) robot.getEnergy(); + } + } + if (maxEnergy == 0) { + maxEnergy = 1; + } + + maxScore = 0; + for (IScoreSnapshot team : scoreSnapshotList) { + if (maxScore < team.getCurrentScore()) { + maxScore = (int) team.getCurrentScore(); + } + } + if (maxScore == 0) { + maxScore = 1; + } + + final int newScore = (int) scoreSnapshotList[contestantIndex].getCurrentScore(); + final int newEnergy = (int) robots[robotIndex].getEnergy(); + boolean rep = (lastEnergy != newEnergy || lastScore != newScore); + + lastEnergy = newEnergy; + lastScore = newScore; + if (rep) { + repaint(); + } + } + + public void onBattleCompleted(final BattleCompletedEvent event) { + maxScore = 0; + for (BattleResults team : event.getIndexedResults()) { + if (maxScore < team.getScore()) { + maxScore = team.getScore(); + } + } + if (maxScore == 0) { + maxScore = 1; + } + lastScore = event.getIndexedResults()[contestantIndex].getScore(); + repaint(); + } + + public void onBattleFinished(final BattleFinishedEvent event) { + lastEnergy = 0; + repaint(); + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotDescriptionPanel.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotDescriptionPanel.java new file mode 100644 index 0000000..02cddb9 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotDescriptionPanel.java @@ -0,0 +1,230 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.ui.BrowserManager; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLDecoder; +import java.util.StringTokenizer; + + +/** + * @author Mathew A. Nelson (original) + * @author Matthew Reeder (contributor) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class RobotDescriptionPanel extends JPanel { + private JLabel robotNameLabel; + private final JLabel[] descriptionLabel = new JLabel[3]; + private JPanel descriptionPanel; + private JButton webpageButton; + private JLabel robocodeVersionLabel; + private JLabel filePathLabel; + private IRobotSpecItem currentRobotSpecification; + + private final static String BLANK_STRING = " "; + + private final EventHandler eventHandler = new EventHandler(); + + private class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (e.getSource() == getWebpageButton()) { + if (currentRobotSpecification != null) { + URL htmlFile = currentRobotSpecification.getWebpage(); + + if (htmlFile != null && htmlFile.toString().length() > 0) { + try { + BrowserManager.openURL(htmlFile.toString()); + } catch (IOException ignored) {} + } + } + } + } + } + + public RobotDescriptionPanel() { + super(); + initialize(); + } + + private JLabel getFilePathLabel() { + if (filePathLabel == null) { + filePathLabel = new JLabel(); + filePathLabel.setText(" "); + } + return filePathLabel; + } + + private JLabel getDescriptionLabel(int index) { + if (descriptionLabel[index] == null) { + descriptionLabel[index] = new JLabel(); + descriptionLabel[index].setFont(new Font("Monospaced", Font.PLAIN, 12)); + descriptionLabel[index].setHorizontalAlignment(SwingConstants.LEFT); + descriptionLabel[index].setText(BLANK_STRING); + } + return descriptionLabel[index]; + } + + private JPanel getDescriptionPanel() { + if (descriptionPanel == null) { + descriptionPanel = new JPanel(); + descriptionPanel.setAlignmentY(Component.CENTER_ALIGNMENT); + descriptionPanel.setLayout(new BoxLayout(descriptionPanel, BoxLayout.Y_AXIS)); + descriptionPanel.setBorder(BorderFactory.createEtchedBorder()); + for (int i = 0; i < 3; i++) { + descriptionPanel.add(getDescriptionLabel(i)); + } + } + return descriptionPanel; + } + + private JButton getWebpageButton() { + if (webpageButton == null) { + webpageButton = new JButton("Webpage"); + webpageButton.setMnemonic('W'); + webpageButton.setVisible(false); + webpageButton.setAlignmentY(Component.CENTER_ALIGNMENT); + webpageButton.addActionListener(eventHandler); + } + return webpageButton; + } + + private JLabel getRobocodeVersionLabel() { + if (robocodeVersionLabel == null) { + robocodeVersionLabel = new JLabel(); + } + return robocodeVersionLabel; + } + + private JLabel getRobotNameLabel() { + if (robotNameLabel == null) { + robotNameLabel = new JLabel(); + robotNameLabel.setHorizontalAlignment(SwingConstants.CENTER); + robotNameLabel.setText(" "); + } + return robotNameLabel; + } + + private void initialize() { + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + JPanel p = new JPanel(); + + p.setLayout(new BorderLayout()); + p.add(getRobotNameLabel(), BorderLayout.CENTER); + + JPanel q = new JPanel(); + + q.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); + q.add(getRobocodeVersionLabel()); + p.add(q, BorderLayout.EAST); + + q = new JPanel(); + q.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); + p.add(q, BorderLayout.WEST); + add(p); + + p = new JPanel(); + p.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); + p.add(getDescriptionPanel()); + add(p); + + p = new JPanel(); + p.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); + p.add(getWebpageButton()); + add(p); + + p = new JPanel(); + p.setLayout(new FlowLayout(FlowLayout.CENTER, 1, 1)); + p.add(getFilePathLabel()); + add(p); + } + + public void showDescription(IRobotSpecItem robotSpecification) { + this.currentRobotSpecification = robotSpecification; + if (robotSpecification == null) { + getRobotNameLabel().setText(" "); + for (int i = 0; i < 3; i++) { + getDescriptionLabel(i).setText(BLANK_STRING); + } + getWebpageButton().setVisible(false); + getRobocodeVersionLabel().setText(" "); + getFilePathLabel().setText(" "); + } else { + String name = robotSpecification.getUniqueFullClassNameWithVersion(); + + if (name.charAt(name.length() - 1) == '*') { + name = name.substring(0, name.length() - 1) + " (development version)"; + } + + String s = robotSpecification.getAuthorName(); + + if (s != null && s.length() > 0) { + name += " by " + s; + } + getRobotNameLabel().setText(name); + final URL url = robotSpecification.getItemURL(); + + if (url != null) { + String path = url.toString(); + + try { + path = URLDecoder.decode(url.toString(), "UTF-8"); + } catch (UnsupportedEncodingException ignore) {} + + getFilePathLabel().setText(path); + } else { + getFilePathLabel().setText(""); + } + + String desc = robotSpecification.getDescription(); + int count = 0; + + if (desc != null) { + StringTokenizer tok = new StringTokenizer(desc, "\n"); + + while (tok.hasMoreTokens() && count < 3) { + StringBuffer line = new StringBuffer(tok.nextToken()); + + if (line != null) { + if (line.length() > BLANK_STRING.length()) { + line.delete(BLANK_STRING.length(), line.length()); + } + for (int i = line.length(); i < BLANK_STRING.length(); i++) { + line.append(' '); + } + getDescriptionLabel(count).setText(line.toString()); + } + count++; + } + } + for (int i = count; i < 3; i++) { + getDescriptionLabel(i).setText(BLANK_STRING); + } + + URL u = robotSpecification.getWebpage(); + + getWebpageButton().setVisible(u != null && u.toString().length() > 0); + + String v = robotSpecification.getRobocodeVersion(); + + getRobocodeVersionLabel().setText(v == null ? "" : "Built for " + v); + } + getDescriptionPanel().setMaximumSize(getDescriptionPanel().getPreferredSize()); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotDialog.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotDialog.java new file mode 100644 index 0000000..25fe87f --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotDialog.java @@ -0,0 +1,450 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.battle.IBattleManager; +import net.sf.robocode.ui.IWindowManager; +import robocode.control.events.*; +import robocode.control.snapshot.IDebugProperty; +import robocode.control.snapshot.IRobotSnapshot; +import robocode.control.snapshot.ITurnSnapshot; + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.Map; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class RobotDialog extends JFrame { + private final Color grayGreen = new Color(0x0080C080); + private RobotButton robotButton; + private JTabbedPane tabbedPane; + private ConsoleScrollPane consoleScrollPane; + private ConsoleScrollPane propertiesScrollPane; + private JPanel robotDialogContentPane; + private JPanel buttonPanel; + private JButton okButton; + private JButton clearButton; + private JButton killButton; + private JToggleButton paintButton; + private JCheckBox sgCheckBox; + private JToggleButton pauseButton; + private boolean isListening; + private int robotIndex; + private IRobotSnapshot lastSnapshot; + private boolean printSnapshot; + private boolean grayGreenButton; + private final Map debugProperties = new HashMap(); + + private final BattleObserver battleObserver = new BattleObserver(); + private final IWindowManager windowManager; + private final IBattleManager battleManager; + + public RobotDialog(IWindowManager windowManager, IBattleManager battleManager) { + super(); + this.battleManager = battleManager; + this.windowManager = windowManager; + } + + public void setup(RobotButton robotButton) { + this.robotButton = robotButton; + initialize(); + } + + private void initialize() { + robotIndex = robotButton.getRobotIndex(); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setContentPane(getRobotDialogContentPane()); + if (windowManager.isSlave()) { + getKillButton().setEnabled(false); + } + this.setTitle(robotButton.getRobotName()); + pack(); + } + + @Override + protected void finalize() throws Throwable { + try { + detach(); + } finally { + super.finalize(); + } + } + + public void detach() { + if (isListening) { + windowManager.removeBattleListener(battleObserver); + isListening = false; + } + robotButton.detach(); + + getPauseButton().setEnabled(false); + getKillButton().setEnabled(false); + + lastSnapshot = null; + printSnapshot(); + } + + public void attach(RobotButton robotButton) { + this.robotButton = robotButton; + robotIndex = this.robotButton.getRobotIndex(); + if (!isListening) { + isListening = true; + windowManager.addBattleListener(battleObserver); + } + getPauseButton().setEnabled(true); + if (!windowManager.isSlave()) { + getKillButton().setEnabled(true); + } + } + + public void reset() { + getConsoleScrollPane().setText(null); + lastSnapshot = null; + debugProperties.clear(); + } + + /** + * When robotDialog is packed, we want to set a reasonable size. However, + * after that, we need a null preferred size so the scrollpane will scroll. + * (preferred size should be based on the text inside) + */ + @Override + public void pack() { + getConsoleScrollPane().setPreferredSize(new Dimension(426, 200)); + super.pack(); + getTabbedPane().setPreferredSize(null); + } + + /** + * Returns true if Paint is enabled; false otherwise + * + * @return true if Paint is enabled; false otherwise + */ + public boolean isPaintEnabled() { + return getPaintButton().isSelected(); + } + + /** + * Returns true if the Robocode SG paint is enabled; false otherwise + * + * @return true if the Robocode SG paint enabled; false otherwise + */ + public boolean isSGPaintEnabled() { + return getSGCheckBox().isSelected(); + } + + private final transient ActionListener eventHandler = new ActionListener() { + public void actionPerformed(ActionEvent e) { + Object src = e.getSource(); + + if (src == RobotDialog.this.getOkButton()) { + okButtonActionPerformed(); + } else if (src == RobotDialog.this.getClearButton()) { + clearButtonActionPerformed(); + } else if (src == RobotDialog.this.getKillButton()) { + killButtonActionPerformed(); + } else if (src == RobotDialog.this.getPaintButton()) { + paintButtonActionPerformed(); + } else if (src == RobotDialog.this.getSGCheckBox()) { + sgCheckBoxActionPerformed(); + } else if (src == RobotDialog.this.getPauseButton()) { + pauseResumeButtonActionPerformed(); + } + } + }; + + /** + * Returns the dialog's content pane + * + * @return the dialog's content pane + */ + private JPanel getRobotDialogContentPane() { + if (robotDialogContentPane == null) { + robotDialogContentPane = new JPanel(); + robotDialogContentPane.setLayout(new BorderLayout()); + robotDialogContentPane.add(getTabbedPane()); + robotDialogContentPane.add(getButtonPanel(), BorderLayout.SOUTH); + } + return robotDialogContentPane; + } + + private JTabbedPane getTabbedPane() { + if (tabbedPane == null) { + tabbedPane = new JTabbedPane(); + tabbedPane.setLayout(new BorderLayout()); + tabbedPane.addTab("Console", getConsoleScrollPane()); + tabbedPane.addTab("Properties", getPropertiesScrollPane()); + tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); + + tabbedPane.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + printSnapshot = (tabbedPane.getSelectedIndex() == 1); + printSnapshot(); + } + }); + } + return tabbedPane; + } + + private void printSnapshot() { + if (printSnapshot) { + String text = null; + + if (lastSnapshot != null) { + StringBuilder sb = new StringBuilder(); + + sb.append("energy: ").append(lastSnapshot.getEnergy()).append('\n'); + sb.append("x: ").append(lastSnapshot.getX()).append('\n'); + sb.append("y: ").append(lastSnapshot.getY()).append('\n'); + sb.append("velocity: ").append(lastSnapshot.getVelocity()).append('\n'); + sb.append("heat: ").append(lastSnapshot.getGunHeat()).append('\n'); + sb.append("bodyHeading: rad: ").append(lastSnapshot.getBodyHeading()).append(" deg: ").append(Math.toDegrees(lastSnapshot.getBodyHeading())).append( + '\n'); + sb.append("gunHeading: rad: ").append(lastSnapshot.getGunHeading()).append(" deg: ").append(Math.toDegrees(lastSnapshot.getGunHeading())).append( + '\n'); + sb.append("radarHeading: rad: ").append(lastSnapshot.getRadarHeading()).append(" deg: ").append(Math.toDegrees(lastSnapshot.getRadarHeading())).append( + '\n'); + sb.append("state: ").append(lastSnapshot.getState()).append('\n'); + sb.append('\n'); + IDebugProperty[] debugPropeties = lastSnapshot.getDebugProperties(); + + if (debugPropeties != null) { + for (IDebugProperty prop : debugPropeties) { + if (prop.getValue() == null || prop.getValue().length() == 0) { + debugProperties.remove(prop.getKey()); + } else { + debugProperties.put(prop.getKey(), prop.getValue()); + } + } + } + for (Map.Entry prop : debugProperties.entrySet()) { + sb.append(prop.getKey()).append(": ").append(prop.getValue()).append('\n'); + } + + text = sb.toString(); + } + getPropertiesScrollPane().setText(text); + } + } + + private ConsoleScrollPane getPropertiesScrollPane() { + if (propertiesScrollPane == null) { + propertiesScrollPane = new ConsoleScrollPane(); + } + return propertiesScrollPane; + } + + /** + * Returns the console scroll pane + * + * @return the console scroll pane + */ + private ConsoleScrollPane getConsoleScrollPane() { + if (consoleScrollPane == null) { + consoleScrollPane = new ConsoleScrollPane(); + } + return consoleScrollPane; + } + + /** + * Returns the button panel + * + * @return the button panel + */ + private JPanel getButtonPanel() { + if (buttonPanel == null) { + buttonPanel = new JPanel(); + buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT)); + buttonPanel.add(getOkButton()); + buttonPanel.add(getClearButton()); + buttonPanel.add(getKillButton()); + buttonPanel.add(getPaintButton()); + buttonPanel.add(getSGCheckBox()); + buttonPanel.add(getPauseButton()); + } + return buttonPanel; + } + + /** + * Returns the OK button + * + * @return the OK button + */ + private JButton getOkButton() { + if (okButton == null) { + okButton = getNewButton("OK"); + } + return okButton; + } + + /** + * Returns the Clear button + * + * @return the Clear button + */ + private JButton getClearButton() { + if (clearButton == null) { + clearButton = getNewButton("Clear"); + } + return clearButton; + } + + /** + * Returns the Kill button. + * + * @return the Kill button + */ + private JButton getKillButton() { + if (killButton == null) { + killButton = getNewButton("Kill Robot"); + } + return killButton; + } + + /** + * Returns the Paint button. + * + * @return the Paint button + */ + private JToggleButton getPaintButton() { + if (paintButton == null) { + paintButton = new JToggleButton("Paint"); + paintButton.addActionListener(eventHandler); + } + return paintButton; + } + + /** + * Returns the SG checkbox. + * + * @return the SG checkbox + */ + private JCheckBox getSGCheckBox() { + if (sgCheckBox == null) { + sgCheckBox = new JCheckBox("Robocode SG"); + sgCheckBox.addActionListener(eventHandler); + } + return sgCheckBox; + } + + /** + * Returns the Pause button. + * + * @return the Pause button + */ + private JToggleButton getPauseButton() { + if (pauseButton == null) { + pauseButton = new JToggleButton("Pause/Debug"); + pauseButton.addActionListener(eventHandler); + } + return pauseButton; + } + + /** + * Returns a new button with event handler and with the specified text + * + * @param text The text of the button + * @return a new button with event handler and with the specified text + */ + private JButton getNewButton(String text) { + JButton button = new JButton(text); + + button.addActionListener(eventHandler); + return button; + } + + /** + * Is called when the OK button has been activated + */ + private void okButtonActionPerformed() { + dispose(); + } + + /** + * Is called when the Clear button has been activated + */ + private void clearButtonActionPerformed() { + reset(); + } + + /** + * Is called when the Kill button has been activated + */ + private void killButtonActionPerformed() { + battleManager.killRobot(robotIndex); + } + + /** + * Is called when the Paint button has been activated + */ + private void paintButtonActionPerformed() { + battleManager.setPaintEnabled(robotIndex, getPaintButton().isSelected()); + } + + /** + * Is called when the SG check box has been activated + */ + private void sgCheckBoxActionPerformed() { + battleManager.setSGPaintEnabled(robotIndex, getSGCheckBox().isSelected()); + } + + /** + * Is called when the Pause/Resume button has been activated + */ + private void pauseResumeButtonActionPerformed() { + battleManager.togglePauseResumeBattle(); + } + + private class BattleObserver extends BattleAdaptor { + + @Override + public void onBattlePaused(BattlePausedEvent event) { + getPauseButton().setSelected(true); + } + + @Override + public void onBattleResumed(BattleResumedEvent event) { + getPauseButton().setSelected(false); + } + + @Override + public void onTurnEnded(TurnEndedEvent event) { + final ITurnSnapshot turn = event.getTurnSnapshot(); + + if (turn == null) { + return; + } + + lastSnapshot = turn.getRobots()[robotIndex]; + final String text = lastSnapshot.getOutputStreamSnapshot(); + + if (text != null && text.length() > 0) { + getConsoleScrollPane().append(text); + getConsoleScrollPane().scrollToBottom(); + } + + if (lastSnapshot.isPaintRobot() && !grayGreenButton) { + grayGreenButton = true; + getPaintButton().setBackground(grayGreen); + } + + printSnapshot(); + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotExtractor.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotExtractor.java new file mode 100644 index 0000000..6b6bee1 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotExtractor.java @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.repository.IRepositoryManager; +import net.sf.robocode.ui.IWindowManager; +import static net.sf.robocode.ui.util.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.List; + + +/** + * @author Mathew A. Nelson (original) + * @author Matthew Reeder (contributor) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +@SuppressWarnings("serial") +public class RobotExtractor extends JDialog implements WizardListener { + String unusedrobotPath; + + private static final int MIN_ROBOTS = 1; + private static final int MAX_ROBOTS = 1; // 250; + + private JPanel robotImporterContentPane; + + private WizardCardPanel wizardPanel; + private WizardController buttonsPanel; + private RobotSelectionPanel robotSelectionPanel; + + public byte buf[] = new byte[4096]; + private StringWriter output; + private final IWindowManager windowManager; + private final IRepositoryManager repositoryManager; + + private final EventHandler eventHandler = new EventHandler(); + + class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("Refresh")) { + getRobotSelectionPanel().refreshRobotList(false); + } + } + } + + public RobotExtractor(JFrame owner, IWindowManager windowManager, IRepositoryManager repositoryManager) { + super(owner); + this.repositoryManager = repositoryManager; + this.windowManager = windowManager; + initialize(); + } + + public void update() { + getRobotSelectionPanel().refreshRobotList(false); + } + + public void cancelButtonActionPerformed() { + dispose(); + } + + public void finishButtonActionPerformed() { + int rc = extractRobot(); + ConsoleDialog d; + + d = new ConsoleDialog(windowManager.getRobocodeFrame(), "Extract results", false); + d.setText(output.toString()); + d.pack(); + d.pack(); + WindowUtil.packCenterShow(this, d); + if (rc < 8) { + this.dispose(); + } + } + + private WizardController getButtonsPanel() { + if (buttonsPanel == null) { + buttonsPanel = getWizardPanel().getWizardController(); + } + return buttonsPanel; + } + + private JPanel getRobotImporterContentPane() { + if (robotImporterContentPane == null) { + robotImporterContentPane = new JPanel(); + robotImporterContentPane.setLayout(new BorderLayout()); + robotImporterContentPane.add(getButtonsPanel(), BorderLayout.SOUTH); + robotImporterContentPane.add(getWizardPanel(), BorderLayout.CENTER); + getWizardPanel().getWizardController().setFinishButtonTextAndMnemonic("Extract!", 'E', 0); + robotImporterContentPane.registerKeyboardAction(eventHandler, "Refresh", + KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + robotImporterContentPane.registerKeyboardAction(eventHandler, "Refresh", + KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_FOCUSED); + } + return robotImporterContentPane; + } + + public RobotSelectionPanel getRobotSelectionPanel() { + if (robotSelectionPanel == null) { + robotSelectionPanel = net.sf.robocode.core.Container.createComponent(RobotSelectionPanel.class); + robotSelectionPanel.setup(MIN_ROBOTS, MAX_ROBOTS, false, + "Select the robot you would like to extract to the robots directory. Robots not shown do not include source.", + true, true, true, false, true, true, null); + } + return robotSelectionPanel; + } + + private WizardCardPanel getWizardPanel() { + if (wizardPanel == null) { + wizardPanel = new WizardCardPanel(this); + wizardPanel.add(getRobotSelectionPanel(), "Select robot"); + } + return wizardPanel; + } + + private void initialize() { + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setTitle("Robot Extract"); + setContentPane(getRobotImporterContentPane()); + } + + private int extractRobot() { + repositoryManager.refresh(); + int rv = 0; + + output = new StringWriter(); + PrintWriter out = new PrintWriter(output); + + out.println("Robot Extract"); + List selectedRobots = getRobotSelectionPanel().getSelectedRobots(); + IRobotSpecItem spec = selectedRobots.get(0); + + try { + WindowUtil.setStatusWriter(out); + + rv = repositoryManager.extractJar(spec); + WindowUtil.setStatusWriter(null); + WindowUtil.setStatus(""); + if (rv == 0) { + out.println("Robot extracted successfully."); + } else if (rv == -1) { + out.println("Cancelled."); + } + } catch (Exception e) { + out.println(e); + rv = 8; + } + return rv; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotSelectionPanel.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotSelectionPanel.java new file mode 100644 index 0000000..71cbe8a --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/RobotSelectionPanel.java @@ -0,0 +1,487 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.core.Container; +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.repository.IRepositoryManager; +import net.sf.robocode.ui.IWindowManager; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.awt.event.*; +import java.util.List; +import java.util.ArrayList; + + +/** + * @author Mathew A. Nelson (original) + * @author Matthew Reeder (contributor) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +@SuppressWarnings("serial") +public class RobotSelectionPanel extends WizardPanel { + + private AvailableRobotsPanel availableRobotsPanel; + + private JPanel selectedRobotsPanel; + private JScrollPane selectedRobotsScrollPane; + private JList selectedRobotsList; + + private JPanel buttonsPanel; + private JPanel addButtonsPanel; + private JPanel removeButtonsPanel; + private JButton addButton; + private JButton addAllButton; + private JButton removeButton; + private JButton removeAllButton; + + private final EventHandler eventHandler = new EventHandler(); + private RobotDescriptionPanel descriptionPanel; + private String instructions; + private JLabel instructionsLabel; + private JPanel mainPanel; + private int maxRobots = 1; + private int minRobots = 1; + private boolean onlyShowSource; + private boolean onlyShowWithPackage; + private boolean onlyShowRobots; + private boolean onlyShowDevelopment; + private boolean onlyShowInJar; + private boolean ignoreTeamRobots; + private String preSelectedRobots; + private final List selectedRobots = new ArrayList(); + private final IRepositoryManager repositoryManager; + + public RobotSelectionPanel(IRepositoryManager repositoryManager) { + super(); + this.repositoryManager = repositoryManager; + } + + public void setup(int minRobots, int maxRobots, + boolean showNumRoundsPanel, String instructions, boolean onlyShowSource, boolean onlyShowWithPackage, + boolean onlyShowRobots, boolean onlyShowDevelopment, boolean onlyShowInJar, boolean ignoreTeamRobots, + String preSelectedRobots) { + this.minRobots = minRobots; + this.maxRobots = maxRobots; + this.instructions = instructions; + this.onlyShowSource = onlyShowSource; + this.onlyShowWithPackage = onlyShowWithPackage; + this.onlyShowRobots = onlyShowRobots; + this.onlyShowDevelopment = onlyShowDevelopment; + this.onlyShowInJar = onlyShowInJar; + + this.ignoreTeamRobots = ignoreTeamRobots; + this.preSelectedRobots = preSelectedRobots; + initialize(); + } + + private class EventHandler implements ActionListener, ListSelectionListener { + public void actionPerformed(ActionEvent e) { + if (e.getSource() == getAddAllButton()) { + addAllButtonActionPerformed(); + } else if (e.getSource() == getAddButton()) { + addButtonActionPerformed(); + } else if (e.getSource() == getRemoveAllButton()) { + removeAllButtonActionPerformed(); + } else if (e.getSource() == getRemoveButton()) { + removeButtonActionPerformed(); + } + } + + public void valueChanged(ListSelectionEvent e) { + if (e.getValueIsAdjusting()) { + return; + } + if (e.getSource() == getSelectedRobotsList()) { + selectedRobotsListSelectionChanged(); + } + } + } + + private void addAllButtonActionPerformed() { + JList selectedList = getSelectedRobotsList(); + SelectedRobotsModel selectedModel = (SelectedRobotsModel) selectedList.getModel(); + + for (AvailableRobotsPanel.ItemWrapper selected : availableRobotsPanel.getAvailableRobots()) { + selectedRobots.add(selected); + } + + selectedList.clearSelection(); + selectedModel.changed(); + fireStateChanged(); + if (selectedModel.getSize() >= minRobots && selectedModel.getSize() <= maxRobots) { + showInstructions(); + } else if (selectedModel.getSize() > maxRobots) { + showWrongNumInstructions(); + } + + availableRobotsPanel.getAvailableRobotsList().requestFocus(); + } + + private void addButtonActionPerformed() { + SelectedRobotsModel selectedModel = (SelectedRobotsModel) getSelectedRobotsList().getModel(); + List moves = availableRobotsPanel.getSelectedRobots(); + + for (AvailableRobotsPanel.ItemWrapper move : moves) { + selectedRobots.add(new AvailableRobotsPanel.ItemWrapper(move.getItem())); + } + + selectedModel.changed(); + fireStateChanged(); + if (selectedModel.getSize() >= minRobots && selectedModel.getSize() <= maxRobots) { + showInstructions(); + } else if (selectedModel.getSize() > maxRobots) { + showWrongNumInstructions(); + } + + availableRobotsPanel.getAvailableRobotsList().requestFocus(); + } + + private JButton getAddAllButton() { + if (addAllButton == null) { + addAllButton = new JButton(); + addAllButton.setText("Add All ->"); + addAllButton.setMnemonic('l'); + addAllButton.setDisplayedMnemonicIndex(5); + addAllButton.addActionListener(eventHandler); + } + return addAllButton; + } + + private JButton getAddButton() { + if (addButton == null) { + addButton = new JButton(); + addButton.setText("Add ->"); + addButton.setMnemonic('A'); + addButton.addActionListener(eventHandler); + } + return addButton; + } + + private JPanel getAddButtonsPanel() { + if (addButtonsPanel == null) { + addButtonsPanel = new JPanel(); + addButtonsPanel.setLayout(new GridLayout(2, 1)); + addButtonsPanel.add(getAddButton()); + addButtonsPanel.add(getAddAllButton()); + } + return addButtonsPanel; + } + + private JPanel getButtonsPanel() { + if (buttonsPanel == null) { + buttonsPanel = new JPanel(); + buttonsPanel.setLayout(new BorderLayout(5, 5)); + buttonsPanel.setBorder(BorderFactory.createEmptyBorder(21, 5, 5, 5)); + buttonsPanel.add(getAddButtonsPanel(), BorderLayout.NORTH); + buttonsPanel.add(getRemoveButtonsPanel(), BorderLayout.SOUTH); + } + return buttonsPanel; + } + + private JButton getRemoveAllButton() { + if (removeAllButton == null) { + removeAllButton = new JButton(); + removeAllButton.setText("<- Remove All"); + removeAllButton.setMnemonic('v'); + removeAllButton.setDisplayedMnemonicIndex(7); + removeAllButton.addActionListener(eventHandler); + } + return removeAllButton; + } + + private JButton getRemoveButton() { + if (removeButton == null) { + removeButton = new JButton(); + removeButton.setText("<- Remove"); + removeButton.setMnemonic('m'); + removeButton.setDisplayedMnemonicIndex(5); + removeButton.addActionListener(eventHandler); + } + return removeButton; + } + + private JPanel getRemoveButtonsPanel() { + if (removeButtonsPanel == null) { + removeButtonsPanel = new JPanel(); + removeButtonsPanel.setLayout(new GridLayout(2, 1)); + removeButtonsPanel.add(getRemoveButton()); + removeButtonsPanel.add(getRemoveAllButton()); + } + return removeButtonsPanel; + } + + public String getSelectedRobotsAsString() { + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < selectedRobots.size(); i++) { + if (i != 0) { + sb.append(','); + } + sb.append(selectedRobots.get(i).getItem().getUniqueFullClassNameWithVersion()); + } + return sb.toString(); + } + + public List getSelectedRobots() { + List res = new ArrayList(); + + for (AvailableRobotsPanel.ItemWrapper item : selectedRobots) { + res.add(item.getItem()); + } + return res; + } + + private JList getSelectedRobotsList() { + if (selectedRobotsList == null) { + selectedRobotsList = new JList(); + selectedRobotsList.setModel(new SelectedRobotsModel()); + selectedRobotsList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + MouseListener mouseListener = new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + removeButtonActionPerformed(); + } + if ((e.getModifiers() & InputEvent.BUTTON3_MASK) != 0) { + contextMenuActionPerformed(); + } + } + }; + + selectedRobotsList.addMouseListener(mouseListener); + selectedRobotsList.addListSelectionListener(eventHandler); + } + return selectedRobotsList; + } + + private JPanel getSelectedRobotsPanel() { + if (selectedRobotsPanel == null) { + selectedRobotsPanel = new JPanel(); + selectedRobotsPanel.setLayout(new BorderLayout()); + selectedRobotsPanel.setPreferredSize(new Dimension(120, 100)); + selectedRobotsPanel.setBorder( + BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Selected Robots")); + selectedRobotsPanel.add(getSelectedRobotsScrollPane(), BorderLayout.CENTER); + } + return selectedRobotsPanel; + } + + private JScrollPane getSelectedRobotsScrollPane() { + if (selectedRobotsScrollPane == null) { + selectedRobotsScrollPane = new JScrollPane(); + selectedRobotsScrollPane.setViewportView(getSelectedRobotsList()); + } + return selectedRobotsScrollPane; + } + + private void initialize() { + setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + setLayout(new BorderLayout()); + add(getInstructionsLabel(), BorderLayout.NORTH); + add(getMainPanel(), BorderLayout.CENTER); + add(getDescriptionPanel(), BorderLayout.SOUTH); + setVisible(true); + showInstructions(); + refreshRobotList(false); + } + + private void removeAllButtonActionPerformed() { + JList selectedList = getSelectedRobotsList(); + SelectedRobotsModel selectedModel = (SelectedRobotsModel) selectedList.getModel(); + + selectedRobots.clear(); + selectedList.clearSelection(); + selectedModel.changed(); + fireStateChanged(); + showInstructions(); + } + + private void contextMenuActionPerformed() {} + + private void removeButtonActionPerformed() { + JList selectedList = getSelectedRobotsList(); + SelectedRobotsModel selectedModel = (SelectedRobotsModel) selectedList.getModel(); + int sel[] = selectedList.getSelectedIndices(); + + for (int i = 0; i < sel.length; i++) { + selectedRobots.remove(sel[i] - i); + } + selectedList.clearSelection(); + selectedModel.changed(); + fireStateChanged(); + if (selectedModel.getSize() < minRobots || selectedModel.getSize() > maxRobots) { + showWrongNumInstructions(); + } else { + showInstructions(); + } + } + + class SelectedRobotsModel extends AbstractListModel { + public void changed() { + fireContentsChanged(this, 0, getSize()); + } + + public int getSize() { + return selectedRobots.size(); + } + + public Object getElementAt(int which) { + return selectedRobots.get(which); + } + } + + public AvailableRobotsPanel getAvailableRobotsPanel() { + if (availableRobotsPanel == null) { + availableRobotsPanel = new AvailableRobotsPanel(getAddButton(), "Available Robots", getSelectedRobotsList(), + this); + } + return availableRobotsPanel; + } + + private RobotDescriptionPanel getDescriptionPanel() { + if (descriptionPanel == null) { + descriptionPanel = new RobotDescriptionPanel(); + descriptionPanel.setBorder(BorderFactory.createEmptyBorder(1, 10, 1, 10)); + } + return descriptionPanel; + } + + private JLabel getInstructionsLabel() { + if (instructionsLabel == null) { + instructionsLabel = new JLabel(); + if (instructions != null) { + instructionsLabel.setText(instructions); + } + } + return instructionsLabel; + } + + private JPanel getMainPanel() { + if (mainPanel == null) { + mainPanel = new JPanel(); + mainPanel.setPreferredSize(new Dimension(550, 300)); + GridBagLayout layout = new GridBagLayout(); + + mainPanel.setLayout(layout); + + GridBagConstraints constraints = new GridBagConstraints(); + + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 2; + constraints.weighty = 1; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.gridwidth = 2; + layout.setConstraints(getAvailableRobotsPanel(), constraints); + mainPanel.add(getAvailableRobotsPanel()); + constraints.gridwidth = 1; + constraints.weightx = 0; + constraints.weighty = 0; + constraints.anchor = GridBagConstraints.CENTER; + layout.setConstraints(getButtonsPanel(), constraints); + mainPanel.add(getButtonsPanel()); + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.weightx = 1; + constraints.weighty = 1; + constraints.anchor = GridBagConstraints.NORTHWEST; + layout.setConstraints(getSelectedRobotsPanel(), constraints); + mainPanel.add(getSelectedRobotsPanel()); + } + return mainPanel; + } + + public int getSelectedRobotsCount() { + return selectedRobots.size(); + } + + @Override + public boolean isReady() { + return (getSelectedRobotsCount() >= minRobots && getSelectedRobotsCount() <= maxRobots); + } + + public void refreshRobotList(final boolean withClear) { + + final Runnable runnable = new Runnable() { + public void run() { + final IWindowManager windowManager = Container.getComponent(IWindowManager.class); + + try { + windowManager.setBusyPointer(true); + repositoryManager.refresh(withClear); + + List robotList = repositoryManager.getRepositoryItems(onlyShowSource, + onlyShowWithPackage, onlyShowRobots, onlyShowDevelopment, false, ignoreTeamRobots, onlyShowInJar); + + getAvailableRobotsPanel().setRobotList(robotList); + if (preSelectedRobots != null && preSelectedRobots.length() > 0) { + setSelectedRobots(preSelectedRobots); + preSelectedRobots = null; + } + } finally { + windowManager.setBusyPointer(false); + } + } + }; + + SwingUtilities.invokeLater(runnable); + } + + private void selectedRobotsListSelectionChanged() { + int sel[] = getSelectedRobotsList().getSelectedIndices(); + + if (sel.length == 1) { + availableRobotsPanel.clearSelection(); + IRobotSpecItem robotSpecification = ((AvailableRobotsPanel.ItemWrapper) getSelectedRobotsList().getModel().getElementAt(sel[0])).getItem(); + + showDescription(robotSpecification); + } else { + showDescription(null); + } + } + + private void setSelectedRobots(String selectedRobotsString) { + if (selectedRobotsString != null) { + for (IRobotSpecItem item: repositoryManager.getSelectedSpecifications(selectedRobotsString)) { + this.selectedRobots.add(new AvailableRobotsPanel.ItemWrapper(item)); + } + } + ((SelectedRobotsModel) getSelectedRobotsList().getModel()).changed(); + fireStateChanged(); + } + + public void showDescription(IRobotSpecItem robotSpecification) { + getDescriptionPanel().showDescription(robotSpecification); + } + + public void showInstructions() { + if (instructions != null) { + instructionsLabel.setText(instructions); + instructionsLabel.setVisible(true); + } else { + instructionsLabel.setVisible(false); + } + } + + public void showWrongNumInstructions() { + if (minRobots == maxRobots) { + if (minRobots == 1) { + instructionsLabel.setText("Please select exactly 1 robot."); + } else { + instructionsLabel.setText("Please select exactly " + minRobots + " robots."); + } + } else { + instructionsLabel.setText("Please select between " + minRobots + " and " + maxRobots + " robots."); + } + instructionsLabel.setVisible(true); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/TeamCreator.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/TeamCreator.java new file mode 100644 index 0000000..b3e10d6 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/TeamCreator.java @@ -0,0 +1,178 @@ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.IRepositoryManager; +import net.sf.robocode.repository.TeamProperties; +import net.sf.robocode.ui.IWindowManager; +import static net.sf.robocode.ui.util.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; + +import javax.swing.*; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + + + +@SuppressWarnings("serial") +public class TeamCreator extends JDialog implements WizardListener { + + private JPanel teamCreatorContentPane; + + private WizardCardPanel wizardPanel; + private WizardController wizardController; + + private RobotSelectionPanel robotSelectionPanel; + private TeamCreatorOptionsPanel teamCreatorOptionsPanel; + + private final int minRobots = 2; + private final int maxRobots = 10; + + private final EventHandler eventHandler = new EventHandler(); + + class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("Refresh")) { + getRobotSelectionPanel().refreshRobotList(true); + } + } + } + + private final IRepositoryManager repositoryManager; + + public TeamCreator(IWindowManager windowManager, IRepositoryManager repositoryManager) { + super(windowManager.getRobocodeFrame()); + this.repositoryManager = repositoryManager; + initialize(); + } + + protected TeamCreatorOptionsPanel getTeamCreatorOptionsPanel() { + if (teamCreatorOptionsPanel == null) { + teamCreatorOptionsPanel = new TeamCreatorOptionsPanel(this); + } + return teamCreatorOptionsPanel; + } + + private JPanel getTeamCreatorContentPane() { + if (teamCreatorContentPane == null) { + teamCreatorContentPane = new JPanel(); + teamCreatorContentPane.setLayout(new BorderLayout()); + teamCreatorContentPane.add(getWizardController(), BorderLayout.SOUTH); + teamCreatorContentPane.add(getWizardPanel(), BorderLayout.CENTER); + getWizardPanel().getWizardController().setFinishButtonTextAndMnemonic("Create Team!", 'C', 0); + teamCreatorContentPane.registerKeyboardAction(eventHandler, "Refresh", + KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + teamCreatorContentPane.registerKeyboardAction(eventHandler, "Refresh", + KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_FOCUSED); + } + return teamCreatorContentPane; + } + + protected RobotSelectionPanel getRobotSelectionPanel() { + if (robotSelectionPanel == null) { + robotSelectionPanel = net.sf.robocode.core.Container.createComponent(RobotSelectionPanel.class); + robotSelectionPanel.setup(minRobots, maxRobots, false, "Select the robots for this team.", false, true, true, + false, false, false, null); + } + return robotSelectionPanel; + } + + private WizardCardPanel getWizardPanel() { + if (wizardPanel == null) { + wizardPanel = new WizardCardPanel(this); + wizardPanel.add(getRobotSelectionPanel(), "Select robots"); + wizardPanel.add(getTeamCreatorOptionsPanel(), "Select options"); + } + return wizardPanel; + } + + public void initialize() { + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setTitle("Create a team"); + setContentPane(getTeamCreatorContentPane()); + } + + private WizardController getWizardController() { + if (wizardController == null) { + wizardController = getWizardPanel().getWizardController(); + } + return wizardController; + } + + public void cancelButtonActionPerformed() { + dispose(); + } + + public void finishButtonActionPerformed() { + try { + int rc = createTeam(); + + if (rc == 0) { + JOptionPane.showMessageDialog(this, "Team created successfully.", "Success", + JOptionPane.INFORMATION_MESSAGE, null); + this.dispose(); + } else { + JOptionPane.showMessageDialog(this, "Team creation cancelled", "Cancelled", + JOptionPane.INFORMATION_MESSAGE, null); + } + } catch (IOException e) { + JOptionPane.showMessageDialog(this, e.toString(), "Team Creation Failed", JOptionPane.ERROR_MESSAGE, null); + } + } + + public int createTeam() throws IOException { + File file = new File(repositoryManager.getRobotsDirectory(), + teamCreatorOptionsPanel.getTeamPackage().replace('.', File.separatorChar) + + teamCreatorOptionsPanel.getTeamNameField().getText() + ".team"); + + if (file.exists()) { + int ok = JOptionPane.showConfirmDialog(this, file + " already exists. Are you sure you want to replace it?", + "Warning", JOptionPane.YES_NO_CANCEL_OPTION); + + if (ok == JOptionPane.NO_OPTION || ok == JOptionPane.CANCEL_OPTION) { + return -1; + } + } + if (!file.getParentFile().exists()) { + if (!file.getParentFile().mkdirs()) { + Logger.logError("Can't create " + file.getParentFile().toString()); + } + } + + URL webPageUrl = null; + String webPageFieldString = teamCreatorOptionsPanel.getWebpageField().getText(); + + if (webPageFieldString != null && webPageFieldString.length() > 0) { + try { + webPageUrl = new URL(webPageFieldString); + } catch (MalformedURLException e) { + try { + webPageUrl = new URL("http://" + webPageFieldString); + teamCreatorOptionsPanel.getWebpageField().setText(webPageUrl.toString()); + } catch (MalformedURLException ignored) {} + } + } + + String members = robotSelectionPanel.getSelectedRobotsAsString(); + String version = teamCreatorOptionsPanel.getVersionField().getText(); + String author = teamCreatorOptionsPanel.getAuthorField().getText(); + String desc = teamCreatorOptionsPanel.getDescriptionArea().getText(); + + TeamProperties props = new TeamProperties(); + props.setMembers(members); + props.setVersion(version); + props.setAuthor(author); + props.setDescription(desc); + props.setWebPage(webPageUrl); + + repositoryManager.createTeam(file, props); + return 0; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/TeamCreatorOptionsPanel.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/TeamCreatorOptionsPanel.java new file mode 100644 index 0000000..7d4dc12 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/TeamCreatorOptionsPanel.java @@ -0,0 +1,314 @@ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.ui.packager.RobotPackager; +import net.sf.robocode.ui.util.LimitedClassnameDocument; +import net.sf.robocode.ui.util.LimitedDocument; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +import java.awt.*; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.net.URL; +import java.util.List; + + +@SuppressWarnings("serial") +public class TeamCreatorOptionsPanel extends WizardPanel { + private TeamCreator teamCreator; + private RobotPackager teamPackager; + private final EventHandler eventHandler = new EventHandler(); + + private JLabel authorLabel; + private JTextField authorField; + private JLabel descriptionLabel; + private JTextArea descriptionArea; + private JLabel versionLabel; + private JTextField versionField; + private JLabel webpageLabel; + private JTextField webpageField; + private JLabel webpageHelpLabel; + + private JLabel teamNameLabel; + private JLabel teamPackageLabel; + private JTextField teamNameField; + + private String teamPackage; + + private class EventHandler implements ComponentListener, DocumentListener { + public void insertUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void changedUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void removeUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void componentMoved(ComponentEvent e) {} + + public void componentHidden(ComponentEvent e) {} + + public void componentShown(ComponentEvent e) { + List selectedRobots; + + if (teamCreator != null) { + selectedRobots = teamCreator.getRobotSelectionPanel().getSelectedRobots(); + } else { + selectedRobots = teamPackager.getRobotSelectionPanel().getSelectedRobots(); + } + + if (selectedRobots != null) { + IRobotSpecItem robotSpecification = selectedRobots.get(0); + + getTeamNameLabel().setText("Please choose a name for your team: (Must be a valid Java classname)"); + getTeamNameField().setText(robotSpecification.getShortClassName() + "Team"); + getTeamPackageLabel().setText(robotSpecification.getFullPackage() + "."); + teamPackage = robotSpecification.getFullPackage(); + if (teamPackage != null) { + teamPackage += "."; + } + + String d = robotSpecification.getDescription(); + + if (d == null) { + d = ""; + } + getDescriptionArea().setText(d); + String a = robotSpecification.getAuthorName(); + + if (a == null) { + a = ""; + } + getAuthorField().setText(a); + URL u = robotSpecification.getWebpage(); + + if (u == null) { + getWebpageField().setText(""); + } else { + getWebpageField().setText(u.toString()); + } + + getVersionLabel().setVisible(true); + getVersionField().setVisible(true); + getAuthorLabel().setVisible(true); + getAuthorField().setVisible(true); + getWebpageLabel().setVisible(true); + getWebpageField().setVisible(true); + getWebpageHelpLabel().setVisible(true); + getDescriptionLabel().setText( + "Please enter a short description of this team (up to 3 lines of 72 chars each)."); + } + } + + public void componentResized(ComponentEvent e) {} + } + + public JPanel robotListPanel; + + public TeamCreatorOptionsPanel(TeamCreator teamCreator) { + super(); + this.teamCreator = teamCreator; + initialize(); + } + + public TeamCreatorOptionsPanel(RobotPackager teamPackager) { + super(); + this.teamPackager = teamPackager; + initialize(); + } + + private void initialize() { + setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + getTeamNameLabel().setAlignmentX(Component.LEFT_ALIGNMENT); + add(getTeamNameLabel()); + + JPanel teamNamePanel = new JPanel(); + teamNamePanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + teamNamePanel.setAlignmentX(Component.LEFT_ALIGNMENT); + getTeamNameField().setAlignmentX(Component.LEFT_ALIGNMENT); + getTeamNameField().setMaximumSize(getTeamNameField().getPreferredSize()); + // getVersionField().setMaximumSize(getVersionField().getPreferredSize()); + teamNamePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, getTeamNameField().getPreferredSize().height)); + teamNamePanel.add(getTeamPackageLabel()); + teamNamePanel.add(getTeamNameField()); + add(teamNamePanel); + JLabel label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + add(getVersionLabel()); + + JPanel versionPanel = new JPanel(); + versionPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + versionPanel.setAlignmentX(Component.LEFT_ALIGNMENT); + getVersionField().setAlignmentX(Component.LEFT_ALIGNMENT); + getVersionField().setMaximumSize(getVersionField().getPreferredSize()); + versionPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, getVersionField().getPreferredSize().height)); + versionPanel.add(getVersionField()); + add(versionPanel); + + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + add(getDescriptionLabel()); + + JScrollPane scrollPane = new JScrollPane(getDescriptionArea(), ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + + scrollPane.setMaximumSize(scrollPane.getPreferredSize()); + scrollPane.setMinimumSize(new Dimension(100, scrollPane.getPreferredSize().height)); + scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT); + add(scrollPane); + + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + add(getAuthorLabel()); + + getAuthorField().setAlignmentX(Component.LEFT_ALIGNMENT); + getAuthorField().setMaximumSize(getAuthorField().getPreferredSize()); + add(getAuthorField()); + + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + add(getWebpageLabel()); + + getWebpageField().setAlignmentX(Component.LEFT_ALIGNMENT); + getWebpageField().setMaximumSize(getWebpageField().getPreferredSize()); + add(getWebpageField()); + + getWebpageHelpLabel().setAlignmentX(Component.LEFT_ALIGNMENT); + add(getWebpageHelpLabel()); + + JPanel panel = new JPanel(); + + panel.setAlignmentX(Component.LEFT_ALIGNMENT); + add(panel); + addComponentListener(eventHandler); + } + + @Override + public boolean isReady() { + return getTeamNameField().getText().length() != 0 && getDescriptionArea().getText().length() != 0; + } + + private JLabel getAuthorLabel() { + if (authorLabel == null) { + authorLabel = new JLabel("Please enter your name. (optional)"); + authorLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + } + return authorLabel; + } + + public JTextField getAuthorField() { + if (authorField == null) { + authorField = new JTextField(40); + } + return authorField; + } + + public JLabel getDescriptionLabel() { + if (descriptionLabel == null) { + descriptionLabel = new JLabel(""); + descriptionLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + } + return descriptionLabel; + } + + public JTextArea getDescriptionArea() { + if (descriptionArea == null) { + LimitedDocument doc = new LimitedDocument(3, 72); + + descriptionArea = new JTextArea(doc, null, 3, 72); + doc.addDocumentListener(eventHandler); + } + return descriptionArea; + } + + private JLabel getVersionLabel() { + if (versionLabel == null) { + versionLabel = new JLabel( + "Please enter a version number for this robot (up to 10 word chars: letters, digits, dots, but no spaces)."); + versionLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + } + return versionLabel; + } + + public JTextField getVersionField() { + if (versionField == null) { + LimitedDocument doc = new LimitedDocument(1, 10); + + versionField = new JTextField(doc, null, 10); + doc.addDocumentListener(eventHandler); + } + return versionField; + } + + public JLabel getWebpageLabel() { + if (webpageLabel == null) { + webpageLabel = new JLabel("Please enter a URL for your team's webpage (optional)"); + webpageLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + } + return webpageLabel; + } + + public JTextField getWebpageField() { + if (webpageField == null) { + webpageField = new JTextField(40); + } + return webpageField; + } + + public JLabel getWebpageHelpLabel() { + if (webpageHelpLabel == null) { + webpageHelpLabel = new JLabel(""); + } + return webpageHelpLabel; + } + + public JTextField getTeamNameField() { + if (teamNameField == null) { + LimitedDocument doc = new LimitedClassnameDocument(1, 32); + + teamNameField = new JTextField(doc, null, 32); + doc.addDocumentListener(eventHandler); + } + return teamNameField; + } + + public JLabel getTeamNameLabel() { + if (teamNameLabel == null) { + teamNameLabel = new JLabel(""); + } + return teamNameLabel; + } + + public JLabel getTeamPackageLabel() { + if (teamPackageLabel == null) { + teamPackageLabel = new JLabel(""); + } + return teamPackageLabel; + } + + /** + * õ + * + * @return һַ + */ + public String getTeamPackage() { + return (teamPackage != null) ? teamPackage : "."; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WindowPositionManager.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WindowPositionManager.java new file mode 100644 index 0000000..4f3bf61 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WindowPositionManager.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; + +import java.awt.*; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; +import java.util.StringTokenizer; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class WindowPositionManager implements ComponentListener { + + private Properties windowPositions; + + public WindowPositionManager() { + super(); + } + + public Properties getWindowPositions() { + if (windowPositions == null) { + windowPositions = new Properties(); + + FileInputStream in = null; + + try { + in = new FileInputStream(FileUtil.getWindowConfigFile()); + windowPositions.load(in); + } catch (FileNotFoundException e) { + Logger.logMessage("Creating " + FileUtil.getWindowConfigFile().getName() + " file"); + } catch (Exception e) { + Logger.logError(e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ignored) {} + } + } + } + return windowPositions; + } + + public void componentHidden(ComponentEvent e) {} + + public void componentMoved(ComponentEvent e) { + // Hack, because we cannot detect maximized frame in Java 1.3 + if (e.getComponent().getBounds().getWidth() >= Toolkit.getDefaultToolkit().getScreenSize().width + || e.getComponent().getBounds().getHeight() >= Toolkit.getDefaultToolkit().getScreenSize().height) { + return; + } + setWindowRect((Window) e.getComponent(), e.getComponent().getBounds()); + } + + public void componentResized(ComponentEvent e) { + // Hack, because we cannot detect maximized frame in Java 1.3 + if (e.getComponent().getBounds().getWidth() >= Toolkit.getDefaultToolkit().getScreenSize().width + || e.getComponent().getBounds().getHeight() >= Toolkit.getDefaultToolkit().getScreenSize().height) { + return; + } + setWindowRect((Window) e.getComponent(), e.getComponent().getBounds()); + } + + public void componentShown(ComponentEvent e) {} + + public void setWindowRect(Window w, Rectangle rect) { + String rString = rect.x + "," + rect.y + "," + rect.width + "," + rect.height; + + getWindowPositions().put(w.getClass().getName(), rString); + } + + public Rectangle getWindowRect(Window window) { + window.addComponentListener(this); + + String rString = (String) getWindowPositions().get(window.getClass().getName()); + + if (rString == null) { + return null; + } + + StringTokenizer tokenizer = new StringTokenizer(rString, ","); + int x = Integer.parseInt(tokenizer.nextToken()); + int y = Integer.parseInt(tokenizer.nextToken()); + int width = Integer.parseInt(tokenizer.nextToken()); + int height = Integer.parseInt(tokenizer.nextToken()); + + return fitWindowBoundsToScreen(new Rectangle(x, y, width, height)); + } + + public void saveWindowPositions() { + FileOutputStream out = null; + + try { + out = new FileOutputStream(FileUtil.getWindowConfigFile()); + + getWindowPositions().store(out, "Robocode window sizes"); + } catch (IOException e) { + Logger.logWarning("Unable to save window positions: " + e); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException ignored) {} + } + } + } + + private Rectangle fitWindowBoundsToScreen(Rectangle windowBounds) { + if (windowBounds == null) { + return null; + } + + // Return the input window bounds, if we can find a screen device that contains these bounds + + final GraphicsEnvironment gfxEnv = GraphicsEnvironment.getLocalGraphicsEnvironment(); + final GraphicsDevice[] screenDevices = gfxEnv.getScreenDevices(); + + for (int i = screenDevices.length - 1; i >= 0; i--) { + GraphicsConfiguration[] gfxCfg = screenDevices[i].getConfigurations(); + + for (int j = gfxCfg.length - 1; j >= 0; j--) { + if (gfxCfg[j].getBounds().contains(windowBounds.getLocation())) { + return windowBounds; // Found the bounds + } + } + } + + // Otherwise, return window bounds at a location within the current screen + + final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + int x = (screenSize.width - windowBounds.width) / 2; + int y = (screenSize.height - windowBounds.height) / 2; + + return new Rectangle(x, y, windowBounds.width, windowBounds.height); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WindowUtil.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WindowUtil.java new file mode 100644 index 0000000..17c3f2f --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WindowUtil.java @@ -0,0 +1,207 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.*; +import java.awt.*; +import java.io.PrintWriter; + + +/** + * This is a class for window utilization. + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public class WindowUtil { + + private static final Point origin = new Point(0, 0); + private static final WindowPositionManager windowPositionManager = new WindowPositionManager(); + private static JLabel statusLabel; + private static PrintWriter statusWriter; + private static JLabel defaultStatusLabel; + + public static void center(Window w) { + WindowUtil.center(null, w); + } + + public static void center(Window main, Window w) { + WindowUtil.center(main, w, true); + } + + public static void center(Window main, Window w, boolean move) { + Point location = null; + Dimension size = null; + + Rectangle windowRect = windowPositionManager.getWindowRect(w); + + if (windowRect != null) { + location = new Point(windowRect.x, windowRect.y); + size = new Dimension(windowRect.width, windowRect.height); + } + if (!move) { + size = null; + } + if (location == null || size == null) { + // Center a window + Dimension screenSize; + + if (main != null) { + screenSize = main.getSize(); + } else { + screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + } + size = w.getSize(); + if (size.height > screenSize.height - 20 || size.width > screenSize.width - 20) { + // Keep aspect ratio for the robocode frame. + if (w.getName().equals("RobocodeFrame")) { + int shrink = size.width - screenSize.width + 20; + + if (size.height - screenSize.height + 20 > shrink) { + shrink = size.height - screenSize.height + 20; + } + + size.width -= shrink; + size.height -= shrink; + } else { + if (size.height > screenSize.height - 20) { + size.height = screenSize.height - 20; + } + if (size.width > screenSize.width - 20) { + size.width = screenSize.width - 20; + } + } + } + if (main != null) { + location = main.getLocation(); + location.x += (screenSize.width - size.width) / 2; + location.y += (screenSize.height - size.height) / 2; + } else { + location = new Point((screenSize.width - size.width) / 2, (screenSize.height - size.height) / 2); + } + } + + w.setSize(size); + if (move) { + w.setLocation(location); + } + } + + public static void centerShow(Window main, Window window) { + center(main, window); + window.setVisible(true); + } + + public static void setFixedSize(JComponent component, Dimension size) { + component.setPreferredSize(size); + component.setMinimumSize(size); + component.setMaximumSize(size); + } + + public static void error(JFrame frame, String msg) { + Object[] options = { "OK"}; + + JOptionPane.showOptionDialog(frame, msg, "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, + options, options[0]); + } + + public static void fitWindow(Window w) { + // We don't want to receive the resize event for this pack! + // ... yes we do! + // w.removeComponentListener(windowPositionManager); + w.pack(); + + center(null, w, false); + } + + public static void packCenterShow(Window window) { + // We don't want to receive the resize event for this pack! + window.removeComponentListener(windowPositionManager); + window.pack(); + center(window); + window.setVisible(true); + } + + public static void packCenterShow(Window main, Window window) { + // We don't want to receive the resize event for this pack! + window.removeComponentListener(windowPositionManager); + window.pack(); + center(main, window); + window.setVisible(true); + } + + public static void packPlaceShow(Window window) { + window.pack(); + WindowUtil.place(window); + window.setVisible(true); + } + + public static void place(Window w) { + // Center a window + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension size = w.getSize(); + + if (size.height > screenSize.height) { + size.height = screenSize.height; + } + if (size.width > screenSize.width) { + size.width = screenSize.width; + } + + w.setLocation(origin); + origin.y += 150; + if (origin.y + size.height > screenSize.height) { + origin.y = 0; + origin.x += 40; + } + if (origin.x + size.width > screenSize.width) { + origin.x = 0; + } + } + + public static void saveWindowPositions() { + windowPositionManager.saveWindowPositions(); + } + + public static void message(String s) { + JOptionPane.showMessageDialog(null, s, "Message", JOptionPane.INFORMATION_MESSAGE); + } + + public static void messageWarning(String s) { + JOptionPane.showMessageDialog(null, s, "Warning", JOptionPane.WARNING_MESSAGE); + } + + public static void messageError(String s) { + Toolkit.getDefaultToolkit().beep(); + JOptionPane.showMessageDialog(null, s, "Message", JOptionPane.ERROR_MESSAGE); + } + + public static void setStatus(String s) { + if (statusWriter != null) { + statusWriter.println(s); + } + if (statusLabel != null) { + statusLabel.setText(s); + } else if (defaultStatusLabel != null) { + defaultStatusLabel.setText(s); + } + } + + public static void setStatusLabel(JLabel label) { + statusLabel = label; + } + + public static void setDefaultStatusLabel(JLabel label) { + defaultStatusLabel = label; + } + + public static void setStatusWriter(PrintWriter out) { + statusWriter = out; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/Wizard.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/Wizard.java new file mode 100644 index 0000000..4effe7b --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/Wizard.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import java.awt.*; + + +/** + * @author Mathew A. Nelson (original) + */ +public interface Wizard { + abstract void back(); + + abstract Component getCurrentPanel(); + + abstract WizardController getWizardController(); + + WizardListener getWizardListener(); + + abstract boolean isBackAvailable(); + + abstract boolean isNextAvailable(); + + abstract boolean isReady(); + + abstract void next(); + + void setWizardControllerOnPanel(WizardPanel panel); +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardCardPanel.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardCardPanel.java new file mode 100644 index 0000000..3744916 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardCardPanel.java @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import java.awt.*; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class WizardCardPanel extends JPanel implements Wizard { + private WizardController wizardController; + private CardLayout cardLayout = null; + private int currentIndex = 0; + private final WizardListener listener; + private final EventHandler eventHandler = new EventHandler(); + + public class EventHandler implements ContainerListener { + public void componentRemoved(ContainerEvent e) {} + + public void componentAdded(ContainerEvent e) { + if (e.getChild() instanceof WizardPanel) { + setWizardControllerOnPanel((WizardPanel) e.getChild()); + getWizardController().stateChanged(new ChangeEvent(e.getChild())); + } + } + } + + /** + * WizardCardLayout constructor + * + * @param listener WizardListener + */ + public WizardCardPanel(WizardListener listener) { + this.listener = listener; + initialize(); + } + + public void back() { + currentIndex--; + getWizardController().stateChanged(null); + getCardLayout().previous(this); + } + + public CardLayout getCardLayout() { + if (cardLayout == null) { + cardLayout = new CardLayout(); + } + return cardLayout; + } + + public Component getCurrentPanel() { + return getComponent(currentIndex); + } + + public WizardController getWizardController() { + if (wizardController == null) { + wizardController = new WizardController(this); + } + return wizardController; + } + + public WizardListener getWizardListener() { + return listener; + } + + public void initialize() { + this.setLayout(getCardLayout()); + this.addContainerListener(eventHandler); + } + + public boolean isBackAvailable() { + return (currentIndex > 0); + } + + public boolean isCurrentPanelReady() { + Component c = getCurrentPanel(); + + return (!(c instanceof WizardPanel)) || ((WizardPanel) c).isReady(); + } + + public boolean isNextAvailable() { + return ((currentIndex < getComponentCount() - 1) && isCurrentPanelReady()); + } + + public boolean isReady() { + for (Component c : getComponents()) { + if (!((WizardPanel) c).isReady()) { + return false; + } + } + return true; + } + + public void next() { + currentIndex++; + getWizardController().stateChanged(null); + getCardLayout().next(this); + } + + public void setWizardControllerOnPanel(WizardPanel panel) { + panel.setWizardController(getWizardController()); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardController.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardController.java new file mode 100644 index 0000000..3796002 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardController.java @@ -0,0 +1,195 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + + +/** + * @author Mathew A. Nelson (original) + * @author Matthew Reeder (contributor) + * @author Flemming N. Larsen (contributor) + */ +@SuppressWarnings("serial") +public class WizardController extends JPanel implements ChangeListener { + + private final EventHandler eventHandler = new EventHandler(); + + private JButton backButton; + private JButton nextButton; + private JButton finishButton; + private JButton cancelButton; + private boolean focusOnEnabled; + + class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (e.getSource() == WizardController.this.getFinishButton()) { + finishButtonActionPerformed(); + } + if (e.getSource() == WizardController.this.getCancelButton()) { + cancelButtonActionPerformed(); + } + if (e.getSource() == WizardController.this.getNextButton()) { + nextButtonActionPerformed(); + } + if (e.getSource() == WizardController.this.getBackButton()) { + backButtonActionPerformed(); + } + } + } + + private void backButtonActionPerformed() { + wizard.back(); + } + + private void cancelButtonActionPerformed() { + wizard.getWizardListener().cancelButtonActionPerformed(); + } + + private void finishButtonActionPerformed() { + wizard.getWizardListener().finishButtonActionPerformed(); + } + + /** + * Return the backButton + * + * @return JButton + */ + private JButton getBackButton() { + if (backButton == null) { + backButton = new JButton(); + backButton.setText("Back"); + backButton.setMnemonic('B'); + backButton.addActionListener(eventHandler); + } + return backButton; + } + + /** + * Return the cancelButton + * + * @return JButton + */ + private JButton getCancelButton() { + if (cancelButton == null) { + cancelButton = new JButton(); + cancelButton.setText("Cancel"); + cancelButton.setMnemonic('C'); + cancelButton.addActionListener(eventHandler); + } + return cancelButton; + } + + /** + * Return the finishButton + * + * @return JButton + */ + private JButton getFinishButton() { + if (finishButton == null) { + finishButton = new JButton(); + finishButton.setText("Finish"); + finishButton.setMnemonic('F'); + finishButton.addActionListener(eventHandler); + } + return finishButton; + } + + public void setFinishButtonText(String text) { + getFinishButton().setText(text); + } + + public void setFinishButtonTextAndMnemonic(String text, char mnemonic, int mnemonicIndex) { + getFinishButton().setText(text); + getFinishButton().setMnemonic(mnemonic); + getFinishButton().setDisplayedMnemonicIndex(mnemonicIndex); + } + + /** + * Return the nextButton + * + * @return JButton + */ + private JButton getNextButton() { + if (nextButton == null) { + nextButton = new JButton(); + nextButton.setText("Next"); + nextButton.setMnemonic('N'); + nextButton.addActionListener(eventHandler); + } + return nextButton; + } + + /** + * Initialize the class. + */ + private void initialize() { + add(getBackButton()); + add(getNextButton()); + add(new JLabel(" ")); + add(getFinishButton()); + add(getCancelButton()); + } + + private void nextButtonActionPerformed() { + wizard.next(); + } + + private void setBackButtonEnabled(boolean enabled) { + getBackButton().setEnabled(enabled); + } + + public void setFinishButtonEnabled(boolean enabled) { + getFinishButton().setEnabled(enabled); + if (focusOnEnabled && enabled) { + getFinishButton().requestFocus(); + } + } + + private void setNextButtonEnabled(boolean enabled) { + getNextButton().setEnabled(enabled); + } + + private Wizard wizard = null; + + protected WizardController(Wizard wizard) { + super(); + this.wizard = wizard; + initialize(); + stateChanged(null); + } + + public void stateChanged(ChangeEvent e) { + setBackButtonEnabled(wizard.isBackAvailable()); + setNextButtonEnabled(wizard.isNextAvailable()); + setFinishButtonEnabled(wizard.isReady()); + } + + /** + * Gets the focusOnEnabled. + * + * @return Returns a boolean + */ + public boolean getFocusOnEnabled() { + return focusOnEnabled; + } + + /** + * Sets the focusOnEnabled. + * + * @param focusOnEnabled The focusOnEnabled to set + */ + public void setFocusOnEnabled(boolean focusOnEnabled) { + this.focusOnEnabled = focusOnEnabled; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardListener.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardListener.java new file mode 100644 index 0000000..83171f8 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardListener.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +/** + * @author Mathew A. Nelson (original) + */ +public interface WizardListener { + void cancelButtonActionPerformed(); + + void finishButtonActionPerformed(); +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardPanel.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardPanel.java new file mode 100644 index 0000000..f6061ba --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardPanel.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.event.ChangeEvent; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + */ +public abstract class WizardPanel extends javax.swing.JPanel { + private static final long serialVersionUID = 1L; + + private WizardController wizardController; + + public void fireStateChanged() { + if (wizardController != null) { + wizardController.stateChanged(new ChangeEvent(this)); + } + } + + public abstract boolean isReady(); + + public void setWizardController(WizardController wizardController) { + this.wizardController = wizardController; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardTabbedPane.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardTabbedPane.java new file mode 100644 index 0000000..51958a9 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/dialog/WizardTabbedPane.java @@ -0,0 +1,106 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.dialog; + + +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; + + +/** + * @author Mathew A. Nelson (original) + */ +@SuppressWarnings("serial") +public class WizardTabbedPane extends JTabbedPane implements Wizard { + private WizardController wizardController; + private int currentIndex = 0; + private final WizardListener listener; + private final EventHandler eventHandler = new EventHandler(); + + public class EventHandler implements ContainerListener, ChangeListener { + public void componentRemoved(ContainerEvent e) {} + + public void componentAdded(ContainerEvent e) { + if (e.getChild() instanceof WizardPanel) { + setWizardControllerOnPanel((WizardPanel) e.getChild()); + getWizardController().stateChanged(new ChangeEvent(e.getChild())); + } + } + + public void stateChanged(javax.swing.event.ChangeEvent e) { + currentIndex = getSelectedIndex(); + getWizardController().stateChanged(e); + } + } + + public WizardTabbedPane(WizardListener listener) { + this.listener = listener; + initialize(); + } + + public void back() { + setSelectedIndex(currentIndex - 1); + } + + public Component getCurrentPanel() { + return getSelectedComponent(); + } + + public WizardController getWizardController() { + if (wizardController == null) { + wizardController = new WizardController(this); + } + return wizardController; + } + + public WizardListener getWizardListener() { + return listener; + } + + public void initialize() { + addChangeListener(eventHandler); + addContainerListener(eventHandler); + } + + public boolean isBackAvailable() { + return (currentIndex > 0); + } + + public boolean isCurrentPanelReady() { + Component c = getCurrentPanel(); + + return (!(c instanceof WizardPanel)) || ((WizardPanel) c).isReady(); + } + + public boolean isNextAvailable() { + return ((currentIndex < getComponentCount() - 1) && isCurrentPanelReady()); + } + + public boolean isReady() { + for (Component c : getComponents()) { + if (c instanceof WizardPanel) { + if (!((WizardPanel) c).isReady()) { + return false; + } + } + } + return true; + } + + public void next() { + setSelectedIndex(currentIndex + 1); + } + + public void setWizardControllerOnPanel(WizardPanel panel) { + panel.setWizardController(getWizardController()); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/editor/IRobocodeEditor.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/editor/IRobocodeEditor.java new file mode 100644 index 0000000..30a02a1 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/editor/IRobocodeEditor.java @@ -0,0 +1,16 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.editor; + + +/** + * @author Pavel Savara (original) + */ +public interface IRobocodeEditor { + boolean close(); +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/ColorUtil.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/ColorUtil.java new file mode 100644 index 0000000..6100b82 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/ColorUtil.java @@ -0,0 +1,153 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.gfx; + + +import static robocode.util.Utils.isNear; + +import java.awt.*; + + +/** + * Class used for utilizing colors. + * + * @author Flemming N. Larsen (original) + */ +class ColorUtil { + + /** + * Return a Color based on a color in RGB565 format. + * + * @param rgb565 the color in RGB565 format. + * @return a Color based on the specifed color in RGB565 format. + */ + public static Color toColor(short rgb565) { + if (rgb565 == 0) { + return null; + } + if (rgb565 == 0x20) { + return Color.BLACK; + } + return new Color(255 * ((rgb565 & 0xF800) >> 11) / 31, 255 * ((rgb565 & 0x07e0) >> 5) / 63, + 255 * (rgb565 & 0x001f) / 31); + } + + /** + * Returns a color in the RGB565 format based on a Color instance. + * + * @param c the color to convert into a RGB565 color. + * @return a color in the RGB565 format based on the specified Color. + */ + public static short toRGB565(Color c) { + if (c == null) { + return 0; + } + short rgb = (short) (((c.getRed() & 0xf8) << 8) | ((c.getGreen() & 0xfc) << 3) | (c.getBlue() >> 3)); + + // 0 is reserved for null -> set green (has highest resolution) to 1 + if (rgb == 0) { + return 0x20; + } + // If the color actually was 0x20 then set it to 0x40 (to the nearest green) + if (rgb == 0x20) { + return 0x40; + } + return rgb; + } + + /** + * Converts a RGB color into a HSL color. + * + * @param r the red color component. + * @param g the green color component. + * @param b the blue color component. + * @return a {@code float[] { H, S, L }} representing the HSL color. + */ + public static float[] fromRGBtoHSL(int r, int g, int b) { + float R = (float) r / 255; + float G = (float) g / 255; + float B = (float) b / 255; + + float min = Math.min(Math.min(R, G), B); // Min. value of RGB + float max = Math.max(Math.max(R, G), B); // Max. value of RGB + float delta = max - min; // Delta RGB value + + float L = (max + min) / 2; + + float H, S; + + if (delta == 0) { // This is a gray, no chroma... + H = 0; + S = 0; + } else { // Chromatic data... + if (L < 0.5f) { + S = delta / (max + min); + } else { + S = delta / (2 - max - min); + } + + float deltaR = (((max - R) / 6) + (delta / 2)) / delta; + float deltaG = (((max - G) / 6) + (delta / 2)) / delta; + float deltaB = (((max - B) / 6) + (delta / 2)) / delta; + + if (isNear(R, max)) { + H = deltaB - deltaG; + } else if (isNear(G, max)) { + H = (1f / 3) + deltaR - deltaB; + } else { + H = (2f / 3) + deltaG - deltaR; + } + + if (H < 0) { + H++; + } + if (H > 1) { + H--; + } + } + return new float[] { H, S, L}; + } + + /** + * Converts a HSL color into a RGB color integer value. + * + * @param h the color hue. + * @param s the color saturation. + * @param l the color lumination. + * @return an RGB integer value. + */ + public static int fromHSLtoRGB(float h, float s, float l) { + float m2 = (l <= 0.5f) ? (l * (s + 1)) : (l + s - l * s); + float m1 = 2 * l - m2; + + int r = (int) (255 * fromHUEtoRGB(m1, m2, h + (1f / 3))); + int g = (int) (255 * fromHUEtoRGB(m1, m2, h)); + int b = (int) (255 * fromHUEtoRGB(m1, m2, h - (1f / 3))); + + return (((r << 8) | g) << 8) | b; + } + + private static float fromHUEtoRGB(float m1, float m2, float h) { + if (h < 0) { + h++; + } + if (h > 1) { + h--; + } + if ((h * 6) < 1) { + return m1 + (m2 - m1) * h * 6; + } + if ((h * 2) < 1) { + return m2; + } + if ((h * 3) < 2) { + return m1 + (m2 - m1) * ((2f / 3) - h) * 6; + } + return m1; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/GraphicsState.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/GraphicsState.java new file mode 100644 index 0000000..30fcb71 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/GraphicsState.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.gfx; + + +import java.awt.*; +import java.awt.geom.AffineTransform; + + +/** + * This class is used for storing the state of a Graphics object, which can be + * restored later. + * + * @author Flemming N. Larsen (original) + */ +public class GraphicsState { + + private Paint paint; + private Font font; + private Stroke stroke; + private AffineTransform transform; + private Composite composite; + private Shape clip; + private RenderingHints renderingHints; + private Color color; + private Color background; + + public void save(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + + paint = g2.getPaint(); + font = g2.getFont(); + stroke = g2.getStroke(); + transform = g2.getTransform(); + composite = g2.getComposite(); + clip = g2.getClip(); + renderingHints = g2.getRenderingHints(); + color = g2.getColor(); + background = g2.getBackground(); + } + + public void restore(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + + g2.setPaint(paint); + g2.setFont(font); + g2.setStroke(stroke); + g2.setTransform(transform); + g2.setComposite(composite); + g2.setClip(clip); + g2.setRenderingHints(renderingHints); + g2.setColor(color); + g2.setBackground(background); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/ImageUtil.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/ImageUtil.java new file mode 100644 index 0000000..c69c97c --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/ImageUtil.java @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.gfx; + + +import net.sf.robocode.io.Logger; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.awt.image.FilteredImageSource; +import java.awt.image.RGBImageFilter; +import java.io.IOException; +import java.net.URL; + + +/** + * Class used for utilizing images. + * + * @author Flemming N. Larsen (original) + */ +public class ImageUtil { + + /** + * Returns an image resource. + * + * @param filename the filename of the image to load + * @return the loaded image + */ + public static Image getImage(String filename) { + URL url = ImageUtil.class.getResource(filename); + + if (url == null) { + Logger.logError("Could not load image because of invalid filename: " + filename); + return null; + } + + try { + final BufferedImage result = ImageIO.read(url); + + if (result == null) { + final String message = "Could not load image: " + filename; + + Logger.logError(message); + throw new Error(); + } + return result; + } catch (IOException e) { + Logger.logError("Could not load image: " + filename); + return null; + } + + } + + /** + * Creates and returns a buffered version of the specified image. + * + * @param image the image to create a buffered image for + * @return a buffered image based on the specified image + */ + public static BufferedImage getBufferedImage(Image image) { + BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), + BufferedImage.TYPE_INT_ARGB); + + Graphics g = bufferedImage.getGraphics(); + + g.drawImage(image, 0, 0, null); + + return bufferedImage; + } + + /** + * Create a copy of an robot image into a coloured robot image. The colors of the + * input image are changed into the input color, but with the same lumination. + * + * @param img the source image + * @param color the new color that substitutes the old color(s) in the source image + * @return a new image + */ + public static Image createColouredRobotImage(Image img, Color color) { + return (color == null) + ? img + : (img == null) + ? null + : Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(img.getSource(), new ColorFilter(color))); + } + + /** + * A color filter used for changing colors into another color. + * + * @author Flemming N. Larsen + */ + private static class ColorFilter extends RGBImageFilter { + private final float[] hsl; + + public ColorFilter(Color color) { + hsl = ColorUtil.fromRGBtoHSL(color.getRed(), color.getGreen(), color.getBlue()); + } + + @Override + public int filterRGB(int x, int y, int argb) { + int r = (argb >> 16) & 0xff; + int g = (argb >> 8) & 0xff; + int b = argb & 0xff; + + float[] HSL = ColorUtil.fromRGBtoHSL(r, g, b); + + if (HSL[1] > 0) { + float L = Math.min(1, (hsl[2] + HSL[2]) / 2 + hsl[2] / 7); + + return argb & 0xff000000 | ColorUtil.fromHSLtoRGB(hsl[0], hsl[1], L); + } + return argb; + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RenderImage.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RenderImage.java new file mode 100644 index 0000000..a2f3ae5 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RenderImage.java @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.gfx; + + +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.geom.Area; + + +/** + * An image that can be rendered. + * + * @author Flemming N. Larsen (original) + */ +public class RenderImage extends RenderObject { + + /** + * Image + */ + protected final Image image; + + /** + * Area containing the bounds of the image to paint + */ + protected final Area boundArea; + + /** + * Constructs a new {@code RenderImage}, which has it's origin in the center + * of the image. + * + * @param image the image to be rendered + */ + public RenderImage(Image image) { + this(image, ((double) image.getWidth(null) / 2), ((double) image.getHeight(null) / 2)); + } + + /** + * Constructs a new {@code RenderImage} + * + * @param image the image to be rendered + * @param originX the x coordinate of the origin for the rendered image + * @param originY the y coordinate of the origin for the rendered image + */ + public RenderImage(Image image, double originX, double originY) { + super(); + + this.image = image; + + baseTransform = AffineTransform.getTranslateInstance(-originX, -originY); + + boundArea = new Area(new Rectangle(0, 0, image.getWidth(null), image.getHeight(null))); + } + + /** + * Constructs a new {@code RenderImage} that is a copy of another + * {@code RenderImage}. + * + * @param ri the {@code RenderImage} to copy + */ + public RenderImage(RenderImage ri) { + super(ri); + + image = ri.image; + + boundArea = new Area(ri.boundArea); + } + + @Override + public void paint(Graphics2D g) { + g.drawImage(image, transform, null); + } + + @Override + public Rectangle getBounds() { + return boundArea.createTransformedArea(transform).getBounds(); + } + + @Override + public RenderObject copy() { + return new RenderImage(this); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RenderObject.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RenderObject.java new file mode 100644 index 0000000..6a1b462 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RenderObject.java @@ -0,0 +1,139 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.gfx; + + +import java.awt.*; +import java.awt.geom.AffineTransform; + + +/** + * The base of all renderable objects. + * An {@code RenderObject} is an object that can be painted and transformed. + * + * @author Flemming N. Larsen (original) + */ +public class RenderObject { + + /** + * Base transform, e.g. the initial rotation and translation + */ + protected AffineTransform baseTransform; + + /** + * Current transform that is concatenated with the base transform + */ + protected final AffineTransform transform; + + /** + * Current frame that must be rendered + */ + protected int frame; + + /** + * Constructs a new {@code RenderObject}. + */ + public RenderObject() { + baseTransform = new AffineTransform(); + transform = new AffineTransform(); + } + + /** + * Constructs a new {@code RenderObject} that is a copy of another {@code RenderObject}. + * + * @param renderObject the RenderObject to copy. + */ + public RenderObject(RenderObject renderObject) { + baseTransform = new AffineTransform(renderObject.baseTransform); + transform = new AffineTransform(renderObject.transform); + frame = renderObject.frame; + } + + /** + * Sets the base transform which is pre-concatenated with the current transform. + * + * @param Tx the new transform + */ + public void setBaseTransform(AffineTransform Tx) { + baseTransform.setTransform(Tx); + } + + /** + * Returns a copy of the base transform + * + * @return a copy of the base transform + */ + public AffineTransform getBaseTransform() { + return new AffineTransform(baseTransform); + } + + /** + * Sets the current transform, which is concatenated with the base transform. + * + * @param Tx the new transform + */ + public void setTransform(AffineTransform Tx) { + transform.setTransform(Tx); + transform.concatenate(baseTransform); + } + + /** + * Returns a copy of the current transform + * + * @return a copy of the current transform + */ + public AffineTransform getTransform() { + return transform; + } + + /** + * Sets the current frame number + * + * @param frame the new frame number + */ + public void setFrame(int frame) { + this.frame = frame; + } + + /** + * Returns the current frame number + * + * @return the current frame number + */ + public int getFrame() { + return frame; + } + + /** + * Paint this object. + * This method must be overridden in derived classes. + * + * @param g the graphics context where this object must be painted. + */ + public void paint(Graphics2D g) {} + + /** + * Returns the bounds of this object based on it's current transform. + * This method must be overridden in derived classes. + * + * @return the bounds of this object based on it's current transform. + */ + public Rectangle getBounds() { + return new Rectangle(); + } + + /** + * Returns a copy of this object. + * This method must be overridden in derived classes. + * + * @return a copy of this object. + */ + public RenderObject copy() { + return new RenderObject(this); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RobocodeLogo.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RobocodeLogo.java new file mode 100644 index 0000000..48f2d4e --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/gfx/RobocodeLogo.java @@ -0,0 +1,445 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.gfx; + + +import java.awt.*; +import java.awt.geom.*; + + +/** + * This class is used for rendering the Robocode logo. + * + * @author Flemming N. Larsen (original) + */ +public class RobocodeLogo { + + public final static int WIDTH = 570; + public final static int HEIGHT = 213; + + private final static Color WHITE_ALPHA_7F = new Color(0xff, 0xff, 0xff, 0x7f); + + private final static Color GLOW_GREEN = new Color(0x0A, 0xff, 0x0A, 0x66); + + private final static Color DARK_GREEN_ALPHA_80 = new Color(0x00, 0x70, 0x00, 0x80); + private final static Color GREEN_ALPHA_08 = new Color(0x00, 0xff, 0x00, 0x08); + private final static Color GREEN_ALPHA_20 = new Color(0x00, 0xff, 0x00, 0x20); + private final static Color GREEN_ALPHA_40 = new Color(0x00, 0xff, 0x00, 0x40); + private final static Color GREEN_ALPHA_48 = new Color(0x00, 0xff, 0x00, 0x48); + private final static Color GREEN_ALPHA_80 = new Color(0x00, 0xff, 0x00, 0x80); + + private final static Shape I_SHAPE = new Rectangle2D.Float(0, 0, 13, 46); + + private final static Stroke THIN_STROKE = new BasicStroke(1.5f); + + public void paintLogoWithTanks(Graphics graphics) { + Graphics2D g = (Graphics2D) graphics; + AffineTransform origTransform = g.getTransform(); + + g.setColor(Color.BLACK); + g.fillRect(0, 0, WIDTH, HEIGHT); + + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + + drawTanks(g); + drawOuterDecoration(g); + drawMiddleEllipse(g); + drawMiddleDecoration(g); + drawInnerDecoration(g); + drawInnerSubDecoration(g); + drawRobocodeText(g); + + g.setTransform(origTransform); + } + + private void transform(Graphics2D g, AffineTransform tx) { + AffineTransform at = new AffineTransform(); + + if (tx != null) { + at.concatenate(tx); + } + g.setTransform(at); + } + + private void drawTanks(Graphics2D g) { + AffineTransform origTransform = g.getTransform(); + + drawRobot(g, 22, 192, (float) Math.PI / 2, -0.2f, -0.2f, new Color(0x30, 0x00, 0x10, 0xff)); + drawRobot(g, 22, 92, (float) Math.PI / 2, (float) Math.PI, (float) Math.PI, new Color(0x16, 0x00, 0x2c, 0xff)); + + drawRobot(g, 212, 173, 0.75f, 0.75f, 0.75f, new Color(0x02, 0x01, 0x00, 0xff)); + + drawRobot(g, 455, 50, 2.4f, 2f, 2f, new Color(0x02, 0x00, 0x01, 0xff)); + drawRobot(g, 492, 82, -0.3f, -0.27f, -0.27f, new Color(0x00, 0x00, 0x01, 0xff)); + + transform(g, AffineTransform.getTranslateInstance(270, -25)); + RenderImage explRenderImage1 = new RenderImage( + ImageUtil.getImage("/net/sf/robocode/ui/images/explosion/explosion2-24.png")); + + explRenderImage1.paint(g); + + transform(g, AffineTransform.getTranslateInstance(23, 102)); + RenderImage explRenderImage2 = new RenderImage( + ImageUtil.getImage("/net/sf/robocode/ui/images/explosion/explosion1-8.png")); + + explRenderImage2.setTransform(AffineTransform.getScaleInstance(0.3, 0.3)); + explRenderImage2.paint(g); + + transform(g, AffineTransform.getTranslateInstance(464, 55)); + RenderImage explRenderImage3 = new RenderImage( + ImageUtil.getImage("/net/sf/robocode/ui/images/explosion/explosion1-1.png")); + + explRenderImage3.setTransform(AffineTransform.getScaleInstance(0.5, 0.5)); + explRenderImage3.paint(g); + + transform(g, AffineTransform.getTranslateInstance(488, 72)); + RenderImage explRenderImage4 = new RenderImage( + ImageUtil.getImage("/net/sf/robocode/ui/images/explosion/explosion1-6.png")); + + explRenderImage4.setTransform(AffineTransform.getScaleInstance(0.4, 0.4)); + explRenderImage4.paint(g); + + transform(g, origTransform); + g.setColor(Color.LIGHT_GRAY); + g.fillOval(20, 154, 3, 3); + } + + private void drawRobot(Graphics2D g, int x, int y, float bodyAngle, float gunAngle, float radarAngle, Color color) { + transform(g, AffineTransform.getTranslateInstance(x, y)); + + RenderImage bodyRenderImage = new RenderImage( + ImageUtil.createColouredRobotImage(ImageUtil.getImage("/net/sf/robocode/ui/images/body.png"), color)); + + bodyRenderImage.setTransform(AffineTransform.getRotateInstance(bodyAngle)); + bodyRenderImage.paint(g); + + RenderImage gunRenderImage = new RenderImage( + ImageUtil.createColouredRobotImage(ImageUtil.getImage("/net/sf/robocode/ui/images/turret.png"), color)); + + gunRenderImage.setTransform(AffineTransform.getRotateInstance(gunAngle)); + gunRenderImage.paint(g); + + RenderImage radarRenderImage = new RenderImage( + ImageUtil.createColouredRobotImage(ImageUtil.getImage("/net/sf/robocode/ui/images/radar.png"), color)); + + radarRenderImage.setTransform(AffineTransform.getRotateInstance(radarAngle)); + radarRenderImage.paint(g); + } + + private void drawOuterDecoration(Graphics2D g) { + Shape shape = getOuterDecoration(); + + transform(g, AffineTransform.getTranslateInstance(26, 24)); + + g.setColor(WHITE_ALPHA_7F); + g.fill(shape); + + g.setStroke(THIN_STROKE); + g.drawOval(16, 5, 490, 163); + } + + private void drawMiddleEllipse(Graphics2D g) { + transform(g, null); + + Shape ellipse = new Ellipse2D.Float(68, 38, 440, 146); + + g.setColor(DARK_GREEN_ALPHA_80); + g.fill(ellipse); + + g.setColor(GREEN_ALPHA_40); + g.setStroke(THIN_STROKE); + g.draw(ellipse); + } + + private void drawMiddleDecoration(Graphics2D g) { + Shape shape = getMiddleDecoration(); + + transform(g, AffineTransform.getTranslateInstance(77, 41)); + + g.setColor(GREEN_ALPHA_20); + g.fill(shape); + + g.setStroke(THIN_STROKE); + g.setColor(GREEN_ALPHA_48); + g.draw(shape); + } + + private void drawInnerDecoration(Graphics2D g) { + Shape shape = getInnerDecoration(); + + transform(g, AffineTransform.getTranslateInstance(103, 52)); + + g.setColor(DARK_GREEN_ALPHA_80); + g.fill(shape); + + g.setStroke(THIN_STROKE); + g.setColor(GLOW_GREEN); + g.draw(shape); + } + + private void drawInnerSubDecoration(Graphics2D g) { + Shape shape = getInnerSubDecoration(); + + transform(g, AffineTransform.getTranslateInstance(110, 54)); + + g.setColor(GREEN_ALPHA_08); + g.fill(shape); + + g.setStroke(THIN_STROKE); + g.setColor(GREEN_ALPHA_48); + g.draw(shape); + } + + private void drawRobocodeText(Graphics2D g) { + Shape shape = getRobocodeText(); + + transform(g, AffineTransform.getTranslateInstance(121, 88)); + + g.setColor(GREEN_ALPHA_40); + g.fill(shape); + + g.setStroke(THIN_STROKE); + g.setColor(GREEN_ALPHA_80); + g.draw(shape); + } + + private Area outerDecoration; + + private Shape getOuterDecoration() { + if (outerDecoration == null) { + float W = 523; + float H = 174; + + outerDecoration = new Area(new Ellipse2D.Float(0, 0, W, H)); + outerDecoration.subtract(new Area(new Ellipse2D.Float(16, 5, W - 2 * 16, H - 2 * 5))); + + outerDecoration.subtract(new Area(new Rectangle2D.Float(W / 2, 0, W / 2, H / 2))); + outerDecoration.subtract(new Area(new Rectangle2D.Float(0, H / 2, W / 2, H / 2))); + } + return outerDecoration; + } + + private Area middleDecoration; + + private Shape getMiddleDecoration() { + if (middleDecoration == null) { + middleDecoration = new Area(new Ellipse2D.Float(0, 0, 420, 140)); + + Rectangle2D.Float rect = new Rectangle2D.Float(180, 69, 500, 3); + + for (float deg = 120; deg <= 335; deg += 4.8f) { + Area rectArea = new Area(rect); + + rectArea.transform(AffineTransform.getRotateInstance(Math.toRadians(deg), 151, 72)); + middleDecoration.subtract(rectArea); + } + + middleDecoration.subtract(new Area(new Ellipse2D.Float(18, 2, 408, 144))); + } + return middleDecoration; + } + + private Area innerSubDecoration; + + private Shape getInnerSubDecoration() { + if (innerSubDecoration == null) { + innerSubDecoration = new Area(new Ellipse2D.Float(0, 0, 356, 114)); + innerSubDecoration.subtract( + new Area(new Rectangle2D.Float(Float.MIN_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, 88))); + innerSubDecoration.subtract( + new Area(new Rectangle2D.Float(Float.MIN_VALUE, Float.MIN_VALUE, 184, Float.MAX_VALUE))); + innerSubDecoration.subtract(new Area(new Rectangle2D.Float(209, Float.MIN_VALUE, 3, Float.MAX_VALUE))); + } + return innerSubDecoration; + } + + private Area innerDecoration; + + private Shape getInnerDecoration() { + if (innerDecoration == null) { + innerDecoration = new Area(new Ellipse2D.Float(0, 0, 368, 120)); + innerDecoration.subtract(new Area(new Rectangle2D.Float(Float.MIN_VALUE, 30, Float.MAX_VALUE, 56))); + innerDecoration.subtract(new Area(new Rectangle2D.Float(181, Float.MIN_VALUE, 7, Float.MAX_VALUE))); + } + return innerDecoration; + } + + private GeneralPath robocodeTextPath; + + public GeneralPath getRobocodeText() { + if (robocodeTextPath == null) { + robocodeTextPath = new GeneralPath(); + + GeneralPath R = getPathR(); + GeneralPath o = getPathO(); + GeneralPath b = getPathB(); + GeneralPath c = getPathC(); + GeneralPath d = getPathD(); + GeneralPath e = getPathE(); + + robocodeTextPath.append(R, false); + + o.transform(AffineTransform.getTranslateInstance(42, 16)); + robocodeTextPath.append(o, false); + + b.transform(AffineTransform.getTranslateInstance(84, 0)); + robocodeTextPath.append(b, false); + + o.transform(AffineTransform.getTranslateInstance(127 - 42, 0)); + robocodeTextPath.append(o, false); + + c.transform(AffineTransform.getTranslateInstance(170, 16)); + robocodeTextPath.append(c, false); + + o.transform(AffineTransform.getTranslateInstance(204 - 127, 0)); + robocodeTextPath.append(o, false); + + d.transform(AffineTransform.getTranslateInstance(246, 0)); + robocodeTextPath.append(d, false); + + e.transform(AffineTransform.getTranslateInstance(290, 16)); + robocodeTextPath.append(e, false); + } + return robocodeTextPath; + } + + private GeneralPath getPathR() { + GeneralPath path = new GeneralPath(I_SHAPE); + + GeneralPath bow = getPathPBow(); + + bow.transform(AffineTransform.getTranslateInstance(15, 0)); + path.append(bow, false); + + path.moveTo(21, 29); + path.lineTo(31, 46); + path.lineTo(44.5f, 46); + path.lineTo(33.5f, 27); + path.curveTo(33.5f, 27, 31, 29, 21, 29); + path.closePath(); + + return path; + } + + private GeneralPath getPathO() { + GeneralPath path = getPathOBow(); + + path.transform(AffineTransform.getTranslateInstance(20, 0)); + + GeneralPath bow2 = getPathOBow(); + + bow2.transform(AffineTransform.getScaleInstance(-1, 1)); + bow2.transform(AffineTransform.getTranslateInstance(18, 0)); + path.append(bow2, false); + + return path; + } + + private GeneralPath getPathB() { + GeneralPath path = new GeneralPath(I_SHAPE); + + GeneralPath bow = getPathPBow(); + + bow.transform(AffineTransform.getTranslateInstance(15, 20)); + path.append(bow, false); + + return path; + } + + private GeneralPath getPathC() { + GeneralPath path = getPathCBow(); + + GeneralPath bow2 = getPathCBow(); + + bow2.transform(AffineTransform.getScaleInstance(1, -1)); + bow2.transform(AffineTransform.getTranslateInstance(0, 31)); + path.append(bow2, false); + + return path; + } + + private GeneralPath getPathD() { + GeneralPath path = new GeneralPath(I_SHAPE); + + path.transform(AffineTransform.getTranslateInstance(27, 0)); + + GeneralPath bow = getPathPBow(); + + bow.transform(AffineTransform.getScaleInstance(-1, 1)); + bow.transform(AffineTransform.getTranslateInstance(25, 20)); + path.append(bow, false); + + return path; + } + + private GeneralPath getPathE() { + GeneralPath path = new GeneralPath(); + + path.moveTo(0, 14.5f); + path.lineTo(31, 14.5f); + path.curveTo(31, -4.5f, 0, -4.5f, 0, 14.5f); + path.closePath(); + + path.moveTo(12, 11); + path.lineTo(20, 11); + path.curveTo(20, 8, 12, 8, 12, 11); + path.closePath(); + + GeneralPath bow2 = getPathCBow(); + + bow2.transform(AffineTransform.getScaleInstance(1, -1)); + bow2.transform(AffineTransform.getTranslateInstance(0, 31)); + path.append(bow2, false); + + return path; + } + + private GeneralPath getPathPBow() { + GeneralPath path = new GeneralPath(); + + path.moveTo(0, 0); + path.lineTo(10, 0); + path.curveTo(30, 0, 30, 26, 10, 26); + path.lineTo(0, 26); + path.lineTo(0, 17); + path.lineTo(8, 17); + path.curveTo(14, 18, 14, 9, 8, 9); + path.lineTo(0, 9); + path.lineTo(0, 0); + path.closePath(); + + return path; + } + + private GeneralPath getPathOBow() { + GeneralPath path = new GeneralPath(); + + path.moveTo(0, 0); + path.curveTo(23, 0, 23, 31, 0, 31); + path.lineTo(0, 20); + path.curveTo(8, 20, 8, 11, 0, 11); + path.lineTo(0, 0); + path.closePath(); + + return path; + } + + private GeneralPath getPathCBow() { + GeneralPath path = new GeneralPath(); + + path.moveTo(31, 12); + path.curveTo(29, -3.5f, 2, -5.5f, 0, 14.5f); + path.lineTo(11, 14.5f); + path.curveTo(11, 8.5f, 18, 9, 18, 12); + path.lineTo(31, 12); + path.closePath(); + + return path; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/ConfirmPanel.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/ConfirmPanel.java new file mode 100644 index 0000000..2b68ac3 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/ConfirmPanel.java @@ -0,0 +1,123 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.packager; + + +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.ui.dialog.WizardPanel; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.util.List; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +@SuppressWarnings("serial") +public class ConfirmPanel extends WizardPanel { + private final RobotPackager robotPackager; + private final EventHandler eventHandler = new EventHandler(); + private boolean visible; + private JPanel robotListPanel; + + private class EventHandler implements ComponentListener { + public void componentMoved(ComponentEvent e) {} + + public void componentResized(ComponentEvent e) {} + + public void componentHidden(ComponentEvent e) { + visible = false; + fireStateChanged(); + } + + public void componentShown(ComponentEvent e) { + if (robotPackager != null) { + visible = true; + updateFields(); + fireStateChanged(); + repaint(); + } + } + } + + public ConfirmPanel(RobotPackager robotPackager) { + super(); + this.robotPackager = robotPackager; + initialize(); + } + + public JPanel getRobotListPanel() { + if (robotListPanel == null) { + robotListPanel = new JPanel(); + robotListPanel.setLayout(new BoxLayout(robotListPanel, BoxLayout.Y_AXIS)); + robotListPanel.setAlignmentX(Component.LEFT_ALIGNMENT); + } + return robotListPanel; + } + + private void initialize() { + setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + addComponentListener(eventHandler); + add(new JPanel()); + } + + @Override + public boolean isReady() { + return visible; + } + + public void setSelectedRobots(List selectedRobots) { + getRobotListPanel().removeAll(); + + if (selectedRobots == null || selectedRobots.size() == 0) { + getRobotListPanel().add(new JLabel("You have not yet selected any robots.")); + } else if (selectedRobots.size() == 1) { + String robotName = (selectedRobots.get(0)).getFullClassName(); + getRobotListPanel().add(new JLabel("You have selected " + robotName + " for packaging.")); + } else { + getRobotListPanel().add(new JLabel("You have selected the following robots for packaging:")); + for (IRobotSpecItem selected : selectedRobots) { + getRobotListPanel().add(new JLabel(selected.getFullClassName())); + } + } + getRobotListPanel().add(new JLabel("")); + getRobotListPanel().setMaximumSize(new Dimension(10000, robotListPanel.getPreferredSize().height)); + + validate(); + } + + public void updateFields() { + removeAll(); + setSelectedRobots(robotPackager.getRobotSelectionPanel().getSelectedRobots()); + add(getRobotListPanel()); + add(Box.createVerticalStrut(20)); + if (robotPackager.getPackagerOptionsPanel().getIncludeSource().isSelected()) { + add(new JLabel("Java source files will be included.")); + } else { + add(new JLabel("Java source files will NOT be included.")); + } + if (robotPackager.getPackagerOptionsPanel().getIncludeData().isSelected()) { + add(new JLabel("Data files will be included, if they exists.")); + } else { + add(new JLabel("Data source files will NOT be included.")); + } + add(Box.createVerticalStrut(20)); + add(new JLabel("The package will be saved in: " + robotPackager.getFilenamePanel().getFilenameField().getText())); + add(Box.createVerticalStrut(20)); + add(new JLabel("If all of the above is correct, click the Package button to start packaging.")); + add(new JPanel()); + + revalidate(); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/FilenamePanel.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/FilenamePanel.java new file mode 100644 index 0000000..4a9aceb --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/FilenamePanel.java @@ -0,0 +1,269 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.packager; + + +import net.sf.robocode.io.FileUtil; +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.ui.dialog.WizardPanel; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.Caret; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.io.File; +import java.lang.reflect.InvocationTargetException; +import java.util.List; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +@SuppressWarnings("serial") +public class FilenamePanel extends WizardPanel { + private final RobotPackager robotPackager; + + private final EventHandler eventHandler = new EventHandler(); + private boolean robocodeErrorShown; + + private JButton browseButton; + private JTextField filenameField; + + private class EventHandler implements ActionListener, DocumentListener, ComponentListener { + public void insertUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void changedUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void removeUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void actionPerformed(ActionEvent e) { + if (e.getSource() == getBrowseButton()) { + showFileSelectDialog(); + } + } + + public void componentMoved(ComponentEvent e) {} + + public void componentResized(ComponentEvent e) {} + + public void componentHidden(ComponentEvent e) {} + + public void componentShown(ComponentEvent e) { + String fileName = FileUtil.getRobotsDir().getAbsolutePath() + File.separator; + File outgoingFile = new File(fileName); + + if (!outgoingFile.exists()) { + if (!outgoingFile.mkdirs()) { + Logger.logError("Cannot create: " + outgoingFile); + } + } + String jarName = "myrobots.jar"; + List selectedRobots = robotPackager.getRobotSelectionPanel().getSelectedRobots(); + + if (selectedRobots != null && selectedRobots.size() == 1) { + jarName = selectedRobots.get(0).getFullClassName() + "_" + + robotPackager.getPackagerOptionsPanel().getVersionField().getText() + ".jar"; + } + + getFilenameField().setText(fileName + jarName); + Caret caret = getFilenameField().getCaret(); + + caret.setDot(fileName.length()); + caret.moveDot(fileName.length() + jarName.length() - 4); + + getFilenameField().requestFocus(); + } + } + + public FilenamePanel(RobotPackager robotPackager) { + super(); + this.robotPackager = robotPackager; + initialize(); + } + + private void initialize() { + setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + addComponentListener(eventHandler); + + GridBagLayout layout = new GridBagLayout(); + + setLayout(layout); + GridBagConstraints c = new GridBagConstraints(); + + c.insets = new Insets(5, 5, 5, 5); + c.anchor = GridBagConstraints.NORTHWEST; + + c.fill = GridBagConstraints.HORIZONTAL; + c.gridwidth = 1; + c.weightx = 1; + + add(new JLabel("Please type in a .jar file to save this robot package to: "), c); + + c.gridy = 1; + add(getFilenameField(), c); + + c.fill = GridBagConstraints.NONE; + c.gridy = 2; + c.insets = new Insets(3, 3, 3, 3); + add(getBrowseButton(), c); + + c.fill = GridBagConstraints.VERTICAL; + c.weighty = 1; + c.gridy = 3; + add(new JPanel(), c); + } + + @Override + public boolean isReady() { + if (filenameField.getText() == null) { + return false; + } + int robocodeIndex = filenameField.getText().lastIndexOf(File.separatorChar); + + if (robocodeIndex > 0) { + if (filenameField.getText().substring(robocodeIndex + 1).indexOf("robocode") == 0) { + if (!robocodeErrorShown) { + robocodeErrorShown = true; + new Thread(new Runnable() { + public void run() { + JOptionPane.showMessageDialog(FilenamePanel.this, "Filename cannot begin with robocode"); + } + }).start(); + } + return false; + } + } + return (filenameField.getText().toLowerCase().indexOf(".jar") != 0); + } + + public static void main(String[] args) { + JFrame frame = new JFrame("options"); + + frame.setSize(new Dimension(500, 300)); + frame.getContentPane().add(new FilenamePanel(null)); + + try { + SwingUtilities.invokeAndWait(new ShowFrameWorker(frame)); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + + public JButton getBrowseButton() { + if (browseButton == null) { + browseButton = new JButton("Browse"); + browseButton.addActionListener(eventHandler); + } + return browseButton; + } + + public JTextField getFilenameField() { + if (filenameField == null) { + filenameField = new JTextField("(none selected)", 60); + filenameField.getDocument().addDocumentListener(eventHandler); + } + return filenameField; + } + + public void showFileSelectDialog() { + File f = new File("outgoing" + File.separatorChar); + + JFileChooser chooser = new JFileChooser(f); + + chooser.setCurrentDirectory(f); + + javax.swing.filechooser.FileFilter filter = new javax.swing.filechooser.FileFilter() { + @Override + public boolean accept(File pathname) { + if (pathname.isDirectory()) { + return true; + } + String fn = pathname.getName(); + int idx = fn.lastIndexOf('.'); + String extension = ""; + + if (idx >= 0) { + extension = fn.substring(idx); + } + return extension.equalsIgnoreCase(".jar"); + } + + @Override + public String getDescription() { + return "JAR files"; + } + }; + + chooser.setFileFilter(filter); + + boolean done = false; + + while (!done) { + done = true; + int rv = chooser.showSaveDialog(this); + String robotFileName; + + if (rv == JFileChooser.APPROVE_OPTION) { + robotFileName = chooser.getSelectedFile().getPath(); + if (robotFileName.toLowerCase().indexOf(".jar") < 0) { + robotFileName += ".jar"; + } + File outFile = new File(robotFileName); + + if (outFile.exists()) { + int ok = JOptionPane.showConfirmDialog(this, + robotFileName + " already exists. Are you sure you want to replace it?", "Warning", + JOptionPane.YES_NO_CANCEL_OPTION); + + if (ok == JOptionPane.NO_OPTION) { + done = false; + continue; + } + if (ok == JOptionPane.CANCEL_OPTION) { + return; + } + } + getFilenameField().setText(robotFileName); + fireStateChanged(); + } + } + } + + static class ShowFrameWorker implements Runnable { + final JFrame frame; + + public ShowFrameWorker(JFrame frame) { + this.frame = frame; + } + + public void run() { + if (frame != null) { + frame.setVisible(true); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/PackagerOptionsPanel.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/PackagerOptionsPanel.java new file mode 100644 index 0000000..c8ad5cb --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/PackagerOptionsPanel.java @@ -0,0 +1,405 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.packager; + + +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.ui.dialog.WizardPanel; +import net.sf.robocode.ui.util.LimitedDocument; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import java.awt.*; +import java.awt.event.*; +import java.lang.reflect.InvocationTargetException; +import java.net.URL; +import java.util.List; + + +/** + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +@SuppressWarnings("serial") +public class PackagerOptionsPanel extends WizardPanel { + private final RobotPackager robotPackager; + + private final EventHandler eventHandler = new EventHandler(); + + private JCheckBox includeSource; + private JCheckBox includeData; + private JLabel authorLabel; + private JTextField authorField; + private JLabel descriptionLabel; + private JTextArea descriptionArea; + private JLabel versionLabel; + private JTextField versionField; + private JLabel versionHelpLabel; + private JLabel webpageLabel; + private JTextField webpageField; + private JLabel webpageHelpLabel; + + private List currentSelectedRobots; + + private class EventHandler implements ComponentListener, KeyListener, DocumentListener { + public void insertUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void changedUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void removeUpdate(DocumentEvent e) { + fireStateChanged(); + } + + public void componentMoved(ComponentEvent e) {} + + public void componentHidden(ComponentEvent e) {} + + public void componentShown(ComponentEvent e) { + List selectedRobots = robotPackager.getRobotSelectionPanel().getSelectedRobots(); + + // Make sure we don't reset content. Bug fix [3026856] + if (selectedRobots == null || selectedRobots.equals(currentSelectedRobots)) { + return; + } + currentSelectedRobots = selectedRobots; // Bug fix [3026856] + + if (selectedRobots.size() == 1) { + IRobotSpecItem robotSpecItem = selectedRobots.get(0); + + getIncludeSource().setSelected(robotSpecItem.getIncludeSource()); + + getIncludeData().setSelected(robotSpecItem.getIncludeData()); + + String ver = robotSpecItem.getVersion(); + if (ver == null || ver.length() == 0) { + getVersionHelpLabel().setVisible(false); + ver = "1.0"; + } else { + if (ver.length() == 10) { + ver = ver.substring(0, 9); + } + ver += "*"; + getVersionHelpLabel().setVisible(true); + } + getVersionField().setText(ver); + + String desc = robotSpecItem.getDescription(); + if (desc == null) { + desc = ""; + } + getDescriptionArea().setText(desc); + + String author = robotSpecItem.getAuthorName(); + if (author == null) { + author = ""; + } + getAuthorField().setText(author); + + URL url = robotSpecItem.getWebpage(); + String webPage = (url != null) ? url.toString() : ""; + getWebpageField().setText(webPage); + + String fullPackage = robotSpecItem.getFullPackage(); + + String text = ""; + if (fullPackage != null && fullPackage.indexOf(".") != -1) { + String htmlFileName = fullPackage.substring(0, fullPackage.lastIndexOf(".")) + ".html"; + + text = "(You may also leave this blank, and simply create the file: " + htmlFileName + ")"; + } + getWebpageHelpLabel().setText(text); + + getVersionLabel().setVisible(true); + getVersionField().setVisible(true); + getAuthorLabel().setVisible(true); + getAuthorField().setVisible(true); + getWebpageLabel().setVisible(true); + getWebpageField().setVisible(true); + getWebpageHelpLabel().setVisible(true); + getDescriptionLabel().setText( + "Please enter a short description of your robot (up to 3 lines of 72 chars each)."); + } else if (selectedRobots.size() > 1) { + getVersionLabel().setVisible(false); + getVersionField().setVisible(false); + getVersionHelpLabel().setVisible(false); + getAuthorLabel().setVisible(false); + getAuthorField().setVisible(false); + getWebpageLabel().setVisible(false); + getWebpageField().setVisible(false); + getWebpageHelpLabel().setVisible(false); + getDescriptionLabel().setText( + "Please enter a short description of this robot collection (up to 3 lines of 72 chars each)."); + if (getDescriptionArea().getText() == null || getDescriptionArea().getText().length() == 0) { + getDescriptionArea().setText("(Example)This robot comes from the ... robot collection\n"); + } + } + } + + public void componentResized(ComponentEvent e) {} + + public void keyPressed(KeyEvent e) {} + + public void keyReleased(KeyEvent e) {} + + public void keyTyped(KeyEvent e) {} + } + + public JPanel robotListPanel; + + public PackagerOptionsPanel(RobotPackager robotPackager) { + super(); + this.robotPackager = robotPackager; + initialize(); + } + + private void initialize() { + setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + JLabel label = new JLabel( + "It is up to you whether or not to include the source files when you distribute your robot."); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + label = new JLabel( + "If you include the source files, other people will be able to look at your code and learn from it."); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + getIncludeSource().setAlignmentX(Component.LEFT_ALIGNMENT); + add(getIncludeSource()); + + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + label = new JLabel("You may include the source files too if they are available?"); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + getIncludeData().setAlignmentX(Component.LEFT_ALIGNMENT); + add(getIncludeData()); + + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + add(getVersionLabel()); + + JPanel versionPanel = new JPanel(); + versionPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + versionPanel.setAlignmentX(Component.LEFT_ALIGNMENT); + getVersionField().setAlignmentX(Component.LEFT_ALIGNMENT); + getVersionField().setMaximumSize(getVersionField().getPreferredSize()); + versionPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, getVersionField().getPreferredSize().height)); + versionPanel.add(getVersionField()); + versionPanel.add(getVersionHelpLabel()); + add(versionPanel); + + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + add(getDescriptionLabel()); + + JScrollPane scrollPane = new JScrollPane(getDescriptionArea(), ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); + + scrollPane.setMaximumSize(scrollPane.getPreferredSize()); + scrollPane.setMinimumSize(new Dimension(100, scrollPane.getPreferredSize().height)); + scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT); + add(scrollPane); + + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + add(getAuthorLabel()); + + getAuthorField().setAlignmentX(Component.LEFT_ALIGNMENT); + getAuthorField().setMaximumSize(getAuthorField().getPreferredSize()); + add(getAuthorField()); + + label = new JLabel(" "); + label.setAlignmentX(Component.LEFT_ALIGNMENT); + add(label); + + add(getWebpageLabel()); + + getWebpageField().setAlignmentX(Component.LEFT_ALIGNMENT); + getWebpageField().setMaximumSize(getWebpageField().getPreferredSize()); + add(getWebpageField()); + + getWebpageHelpLabel().setAlignmentX(Component.LEFT_ALIGNMENT); + add(getWebpageHelpLabel()); + + JPanel panel = new JPanel(); + + panel.setAlignmentX(Component.LEFT_ALIGNMENT); + add(panel); + addComponentListener(eventHandler); + } + + @Override + public boolean isReady() { + if (getVersionLabel().isVisible()) { + String text = getVersionField().getText(); + + if (text.length() == 0 || !text.matches("([a-zA-Z0-9.])*[a-zA-Z0-9]+")) { + return false; + } + } + return getDescriptionArea().getText().length() != 0; + } + + public static void main(String[] args) { + JFrame frame = new JFrame("options"); + + frame.setSize(new Dimension(500, 300)); + frame.getContentPane().add(new PackagerOptionsPanel(null)); + + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + e.getWindow().dispose(); + } + + @Override + public void windowClosed(WindowEvent e) { + System.exit(0); + } + }); + + try { + SwingUtilities.invokeAndWait(new PackAndShowFrameWorker(frame)); + } catch (InterruptedException e) { + // Immediately reasserts the exception by interrupting the caller thread itself + Thread.currentThread().interrupt(); + + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + + public JCheckBox getIncludeSource() { + if (includeSource == null) { + includeSource = new JCheckBox("Include source files", true); + } + return includeSource; + } + + public JCheckBox getIncludeData() { + if (includeData == null) { + includeData = new JCheckBox("Include data files", true); + } + return includeData; + } + + private JLabel getAuthorLabel() { + if (authorLabel == null) { + authorLabel = new JLabel("Please enter your name. (optional)"); + authorLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + } + return authorLabel; + } + + public JTextField getAuthorField() { + if (authorField == null) { + authorField = new JTextField(40); + } + return authorField; + } + + public JLabel getDescriptionLabel() { + if (descriptionLabel == null) { + descriptionLabel = new JLabel(""); + descriptionLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + } + return descriptionLabel; + } + + public JTextArea getDescriptionArea() { + if (descriptionArea == null) { + LimitedDocument doc = new LimitedDocument(3, 72); + + descriptionArea = new JTextArea(doc, null, 3, 72); + doc.addDocumentListener(eventHandler); + } + return descriptionArea; + } + + private JLabel getVersionLabel() { + if (versionLabel == null) { + versionLabel = new JLabel( + "Please enter a version number for this robot (up to 10 word chars: letters, digits, dots, but no spaces)."); + versionLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + } + return versionLabel; + } + + public JTextField getVersionField() { + if (versionField == null) { + LimitedDocument doc = new LimitedDocument(1, 10); + + versionField = new JTextField(doc, null, 10); + doc.addDocumentListener(eventHandler); + } + return versionField; + } + + public JLabel getVersionHelpLabel() { + if (versionHelpLabel == null) { + versionHelpLabel = new JLabel("<-- Make sure to delete the asterisk and type in a new version number"); + } + return versionHelpLabel; + } + + public JLabel getWebpageLabel() { + if (webpageLabel == null) { + webpageLabel = new JLabel("Please enter a URL for your robot's webpage. (optional)"); + webpageLabel.setAlignmentX(Component.LEFT_ALIGNMENT); + } + return webpageLabel; + } + + public JTextField getWebpageField() { + if (webpageField == null) { + webpageField = new JTextField(40); + } + return webpageField; + } + + public JLabel getWebpageHelpLabel() { + if (webpageHelpLabel == null) { + webpageHelpLabel = new JLabel(""); + } + return webpageHelpLabel; + } + + static class PackAndShowFrameWorker implements Runnable { + final JFrame frame; + + public PackAndShowFrameWorker(JFrame frame) { + this.frame = frame; + } + + public void run() { + if (frame != null) { + frame.pack(); + frame.setVisible(true); + } + } + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/RobotPackager.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/RobotPackager.java new file mode 100644 index 0000000..4dd5214 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/packager/RobotPackager.java @@ -0,0 +1,233 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.packager; + + +import net.sf.robocode.io.Logger; +import net.sf.robocode.repository.IRobotSpecItem; +import net.sf.robocode.repository.IRepositoryManager; +import net.sf.robocode.repository.RobotProperties; +import net.sf.robocode.ui.IWindowManager; +import net.sf.robocode.ui.dialog.*; +import static net.sf.robocode.ui.util.ShortcutUtil.MENU_SHORTCUT_KEY_MASK; + +import javax.swing.*; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.List; + + +/** + * @author Mathew A. Nelson (original) + * @author Matthew Reeder (contributor) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + */ +@SuppressWarnings("serial") +public class RobotPackager extends JDialog implements WizardListener { + + private final int minRobots = 1; + private final int maxRobots = 1; // 250; + + private JPanel robotPackagerContentPane; + private WizardCardPanel wizardPanel; + private WizardController buttonsPanel; + private FilenamePanel filenamePanel; + private ConfirmPanel confirmPanel; + private RobotSelectionPanel robotSelectionPanel; + private PackagerOptionsPanel packagerOptionsPanel; + + private final IRepositoryManager repositoryManager; + private final IWindowManager windowManager; + + private final EventHandler eventHandler = new EventHandler(); + + private class EventHandler implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("Refresh")) { + getRobotSelectionPanel().refreshRobotList(true); + } + } + } + + public RobotPackager(IRepositoryManager repositoryManager, IWindowManager windowManager) { + super(windowManager.getRobocodeFrame()); + this.repositoryManager = repositoryManager; + this.windowManager = windowManager; + initialize(); + } + + public void cancelButtonActionPerformed() { + dispose(); + } + + /** + * Return the buttonsPanel + * + * @return JButton + */ + private WizardController getButtonsPanel() { + if (buttonsPanel == null) { + buttonsPanel = getWizardPanel().getWizardController(); + } + return buttonsPanel; + } + + /** + * Return the buttonsPanel + * + * @return JButton + */ + private ConfirmPanel getConfirmPanel() { + if (confirmPanel == null) { + confirmPanel = new ConfirmPanel(this); + } + return confirmPanel; + } + + /** + * Return the optionsPanel + * + * @return robocode.packager.PackagerOptionsPanel + */ + protected FilenamePanel getFilenamePanel() { + if (filenamePanel == null) { + filenamePanel = new FilenamePanel(this); + } + return filenamePanel; + } + + /** + * Return the optionsPanel + * + * @return robocode.packager.PackagerOptionsPanel + */ + protected PackagerOptionsPanel getPackagerOptionsPanel() { + if (packagerOptionsPanel == null) { + packagerOptionsPanel = new PackagerOptionsPanel(this); + } + return packagerOptionsPanel; + } + + /** + * Return the newBattleDialogContentPane + * + * @return JPanel + */ + private JPanel getRobotPackagerContentPane() { + if (robotPackagerContentPane == null) { + robotPackagerContentPane = new JPanel(); + robotPackagerContentPane.setLayout(new BorderLayout()); + robotPackagerContentPane.add(getButtonsPanel(), BorderLayout.SOUTH); + robotPackagerContentPane.add(getWizardPanel(), BorderLayout.CENTER); + getWizardPanel().getWizardController().setFinishButtonTextAndMnemonic("Package!", 'P', 0); + robotPackagerContentPane.registerKeyboardAction(eventHandler, "Refresh", + KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + robotPackagerContentPane.registerKeyboardAction(eventHandler, "Refresh", + KeyStroke.getKeyStroke(KeyEvent.VK_R, MENU_SHORTCUT_KEY_MASK), JComponent.WHEN_FOCUSED); + } + return robotPackagerContentPane; + } + + /** + * Return the Page property value. + * + * @return JPanel + */ + public RobotSelectionPanel getRobotSelectionPanel() { + if (robotSelectionPanel == null) { + robotSelectionPanel = net.sf.robocode.core.Container.createComponent(RobotSelectionPanel.class); + robotSelectionPanel.setup(minRobots, maxRobots, false, "Select the robot or team you would like to package.", /* true */ + false, + false, false/* true */, true, false, true, null); + } + return robotSelectionPanel; + } + + /** + * Return the tabbedPane. + * + * @return JTabbedPane + */ + private WizardCardPanel getWizardPanel() { + if (wizardPanel == null) { + wizardPanel = new WizardCardPanel(this); + wizardPanel.add(getRobotSelectionPanel(), "Select robot"); + wizardPanel.add(getPackagerOptionsPanel(), "Select options"); + wizardPanel.add(getFilenamePanel(), "Select filename"); + wizardPanel.add(getConfirmPanel(), "Confirm"); + } + return wizardPanel; + } + + private void initialize() { + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setTitle("Robot Packager"); + setContentPane(getRobotPackagerContentPane()); + } + + public void finishButtonActionPerformed() { + String jarFilename = getFilenamePanel().getFilenameField().getText(); + File jarFile = new File(jarFilename); + + if (jarFile.exists()) { + int ok = JOptionPane.showConfirmDialog(this, + jarFilename + " already exists. Are you sure you want to replace it?", "Warning", + JOptionPane.YES_NO_CANCEL_OPTION); + + if (ok == JOptionPane.NO_OPTION || ok == JOptionPane.CANCEL_OPTION) { + Logger.logMessage("Cancelled by user."); + return; + } + Logger.logMessage("Overwriting " + jarFilename); + } + + String webPageFieldString = getPackagerOptionsPanel().getWebpageField().getText(); + URL webPage = null; + + if (webPageFieldString.length() > 0) { + try { + webPage = new URL(webPageFieldString); + } catch (MalformedURLException e) { + try { + webPage = new URL("http://" + webPageFieldString); + getPackagerOptionsPanel().getWebpageField().setText(webPage.toString()); + } catch (MalformedURLException ignored) {} + } + } + boolean includeSource = getPackagerOptionsPanel().getIncludeSource().isSelected(); + boolean includeData = getPackagerOptionsPanel().getIncludeData().isSelected(); + String version = getPackagerOptionsPanel().getVersionField().getText(); + String author = getPackagerOptionsPanel().getAuthorField().getText(); + String desc = getPackagerOptionsPanel().getDescriptionArea().getText(); + List robots = getRobotSelectionPanel().getSelectedRobots(); + + RobotProperties props = new RobotProperties(); + props.setIncludeSource(includeSource); + props.setIncludeData(includeData); + props.setVersion(version); + props.setAuthor(author); + props.setDescription(desc); + props.setWebPage(webPage); + + String outputText = repositoryManager.createPackage(jarFile, robots, props); + + ConsoleDialog dialog = new ConsoleDialog(windowManager.getRobocodeFrame(), "Packaging results", false); + dialog.setText(outputText); + dialog.pack(); + WindowUtil.packCenterShow(this, dialog); + dispose(); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/LimitedClassnameDocument.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/LimitedClassnameDocument.java new file mode 100644 index 0000000..be2b543 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/LimitedClassnameDocument.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.util; + + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; + + +/** + * @author Mathew A. Nelson (original) + */ +@SuppressWarnings("serial") +public class LimitedClassnameDocument extends LimitedDocument { + + public LimitedClassnameDocument() { + super(); + } + + public LimitedClassnameDocument(int maxRows, int maxCols) { + super(maxRows, maxCols); + } + + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + if (offs == 0 && str.length() > 0) { + if (!Character.isJavaIdentifierStart(str.charAt(0))) { + java.awt.Toolkit.getDefaultToolkit().beep(); + return; + } + } else { + for (int i = 0; i < str.length(); i++) { + if (!Character.isJavaIdentifierPart(str.charAt(i))) { + java.awt.Toolkit.getDefaultToolkit().beep(); + return; + } + } + } + if (offs == 0) { + if (!Character.isUpperCase(str.charAt(0))) { + str = str.substring(0, 1).toUpperCase() + str.substring(1); + } + } + + super.insertString(offs, str, a); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/LimitedDocument.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/LimitedDocument.java new file mode 100644 index 0000000..5d64e37 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/LimitedDocument.java @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.util; + + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Element; +import javax.swing.text.PlainDocument; +import java.awt.*; + + +/** + * @author Mathew A. Nelson (original) + */ +@SuppressWarnings("serial") +public class LimitedDocument extends PlainDocument { + int maxRows = Integer.MAX_VALUE; + int maxCols = Integer.MAX_VALUE; + + public LimitedDocument() { + super(); + } + + public LimitedDocument(int maxRows, int maxCols) { + super(); + this.maxRows = maxRows; + this.maxCols = maxCols; + } + + @Override + public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { + Element rootElement = getDefaultRootElement(); + int i = str.indexOf("\n"); + int newlines = 0; + + while (i < str.length() && i >= 0) { + newlines++; + i = str.indexOf("\n", i + 1); + } + + int currentLines = rootElement.getElementCount(); + + if (newlines > 0 && currentLines + newlines > maxRows) { + Toolkit.getDefaultToolkit().beep(); + return; + } + + int lineIndex = rootElement.getElementIndex(offs); + boolean done = false; + + int carry = rootElement.getElement(lineIndex).getEndOffset() - offs - 1; + int lineStart = 0; + + while (!done) { + int lineEnd = str.indexOf("\n", lineStart); + + if (lineEnd == -1 || lineEnd == str.length()) { + if (lineStart == 0) { + carry = 0; + lineEnd = str.length(); + } else { + lineEnd = str.length() + carry; + } + done = true; + } + int lineLen = lineEnd - lineStart; + // Increment for last line... + int currentLen; + + if (!done && lineStart > 0) { + currentLen = 0; + } else { + if (done && lineStart > 0) { + lineIndex++; + } + Element currentLine = rootElement.getElement(lineIndex); + + if (currentLine != null) { + currentLen = currentLine.getEndOffset() - currentLine.getStartOffset(); + } else { + currentLen = 1; + } + if (lineStart == 0) { + currentLen -= carry; + } + } + if (lineLen + currentLen > maxCols + 1) { + Toolkit.getDefaultToolkit().beep(); + return; + } + + lineStart = lineEnd + 1; + } + + super.insertString(offs, str, a); + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/ShortcutUtil.java b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/ShortcutUtil.java new file mode 100644 index 0000000..16f5af5 --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/java/net/sf/robocode/ui/util/ShortcutUtil.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +package net.sf.robocode.ui.util; + + +import java.awt.*; +import java.awt.event.InputEvent; + + +/** + * Utility for handling shortcut keys. + * + * @author Flemming N. Larsen (original) + */ +public class ShortcutUtil { + + /** + * The menu shortcut key mask. + */ + public final static int MENU_SHORTCUT_KEY_MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + + /** + * Returns the text for the shortcut modifier key. + * + * @return the text for the shortcut modifier key. + */ + public static String getModifierKeyText() { + + boolean isMac = (System.getProperty("os.name").startsWith("Mac")); + + String text = ""; + + if ((MENU_SHORTCUT_KEY_MASK & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) { + text = "Shift"; + } + if ((MENU_SHORTCUT_KEY_MASK & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) { + if (text.length() > 0) { + text += '+'; + } + text = "Ctrl"; + } + if ((MENU_SHORTCUT_KEY_MASK & InputEvent.ALT_MASK) == InputEvent.ALT_MASK) { + if (text.length() > 0) { + text += '+'; + } + text = isMac ? "Opt" : "Alt"; + } + if ((MENU_SHORTCUT_KEY_MASK & InputEvent.META_MASK) == InputEvent.META_MASK) { + if (text.length() > 0) { + text += '+'; + } + text = isMac ? "Cmd" : "Meta"; + } + + return text; + } +} diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/html/about.html b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/html/about.html new file mode 100644 index 0000000..84d226f --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/html/about.html @@ -0,0 +1,135 @@ + + + + + + + + + + +
+  Robocode version {$robocode-version} + + +
+  © Copyright 2001-2016 Robocode contributors. All rights reserved. +
+ + + +
+ +Original Author: Mathew A. Nelson. +     +Original Graphics: Garett S. Hourihan. + + + +
+ +Running on Java {$java-version} by {$java-vendor}  |   +Download  |   +Java 6 API documentation
+ + + + + +
+ +ReadMe + |  +License + |  +Home Page + |  +Project Home + |  +Versions + |  +News + |  +RoboWiki + |  +Robocode Repository + |  +Robocode Developers +
+Download + |  +Getting started + |  +Java API + |  +.NET API + |  +FAQ + |  +Google Group + |  +Help Forum + |  +Bug Reports + |  +Feature Requests + +

Main Contributors

+Mathew A. Nelson: Original developer (2001-2005)
+Flemming N. Larsen: Administrator, developer, integrator, lots of features (2005-2016)
+Pavel Savara: Administrator, developer, integrator, robot interfaces, refactorings, .NET plugin (2008-2011)
+ +

Contributors

+Aaron Rotenberg: Robot Cache Cleaner utility
+Albert Perez: RoboRumble@Home client
+Alexander Schultz: Reporting lots of bugs and good solutions for fixing these
+Ascander Jr: Graphics for background tiles
+Christian D. Schnell: Codesize 1.0 utility
+Cubic Creative: Design and ideas for the JuniorRobot class
+Dan Lynn: The Robocode Repository that is the central place for storing your robots and also find other robots
+Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh: Score percentage in results/rankings
+Jerome Lavigne: Added "Smart Battles" to MeleeRumble, developer and admin of the RoboRumble server
+Joachim Hofer: Fixing problem with wrong results in RoboRumble
+Joshua Galecki: Added the RateControlRobot
+Julian Kent: Nano precision timing of allowed robot time
+Luis Crespo: Sound engine, single-step debugging, ranking panel
+Matthew Reeder: Editor enhancements, keyboard shortcuts, HyperThreading bugfixes
+Nathaniel Troutman: Fixing memory leaks
+Patrick Cupka, Julian Kent, Nat Pavasant, and "Positive": Redesigned robot movement method
Robert D. Maupin: Optimizations with collections and improved CPU constant benchmark
+Ruben Moreno Montoliu: Added paths with buttons to Developement Options
+Stefan Westen: onPaint method from RobocodeSG
+Titus Chen: Bugfixes for robot teleportation, bad wall collision detection, team ranking, replay scores and robot color flickering
+Tuan Anh Nguyen: Interactive_v2 sample robot + + + +
+ +Thanks goes to every contributor as well to all users reporting bugs and suggesting new features for Robocode. + \ No newline at end of file diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/html/transparent.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/html/transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..ce0ea771566a755210bfbc720330a57613dfa56b GIT binary patch literal 1202 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx3?wy9o9qU0ii6yp7}lMWc?smOq&xaLGB9lH z=l+w(%D}+P5a1Ky3KSm&qaiS2LtwMPmkv900000 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/icons/robocode-icon.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/icons/robocode-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b82402a17e5d50d7c902df6a6f3977682c6999d8 GIT binary patch literal 2243 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/.cvsignore b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/.cvsignore new file mode 100644 index 0000000..085e8ba --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/.cvsignore @@ -0,0 +1 @@ +Thumbs.db diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-1.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-1.png new file mode 100644 index 0000000000000000000000000000000000000000..61ac8efe8e8db0c4cc69df6745a5e172164e4ca7 GIT binary patch literal 1513 zcmb7^i9gc~0LFhdVVf~IGUhDTr-aCrtK7#NuQTVExuy(Dg!iSyT&WMQ-W-M3^(JQ` znT*NYbL0*!Ig*<&8L$3?p6ByC&*$^}0pDa>Yg0H>1PTBE+}zCQkJF9&6)uj`rs{e3 zo(_kPrKu5c^2-G+WtpcBgkW|v8~|YazrqIO63A$uKPiIQ14XMcb+J%(f+i);ip$t?y4 z5D65P-65?=fW8&Anz^8Z)eXWI5{GT=-7YwXeSE|jOv;M#@yPD~4!(DY%GVte&I1ul z)ccKmT;z#Sn@|)-=XE!*qz5>(_PRIDYgE25N|M~G(|ZI^r#~- z5Xs7#S(N8|x?ULWucU!qit@v!jGKT*W^M__sp2N|cj=m@Wh*xcUxQL|mA-s_`qxqh zUX*l+eJW0PkUJ|LiBVF9SQ%`HyX2kl`VG;ts^$#8JP$OfMit+2QwTmE55diktc{%9 z0>i;#R&x;$(>;AN+9>5J<)Oa46gY+>jY><}5A)fLom!trY{jKCj+eDJ$Z|1)?&dNo zC)q9E2VqyT9Z}4cIifrG(*aCGLK5-`;?5>I(3zPw9_w>5G?ZF z2R#u%11$b}u;riF+6u{84ssum&NLjJMa7?r^#~HoyUR={N)<8AA_LQyJu@is{w(*L>@*P3#RE zb89r+C|Gh`o9a1{HtibEt>6r}#sLo=La{S^=n7L7TWdJj8}hxLGoGa!b%3uD(J^2gb0?EQwhMF+ zqE)IlR>@Dfm-C;xYmstiR)OKxB5R=up4g;etNLJ?yIR*#C*>>B33$n}dz>m(DR*h_ zd9_xKxTMoQD5NBAJU*W?Xyef3Q1!aH{kT?u#&Qm5Y~GZhW45VMtCtz`sKn>i8E&&4 z*6S>J3Eg{QKhPC{U7j}mMGIcU7v)~u_QeB{Jo*Gg zs17&rPI?@Zp?Y@jC;uUEB+pf5QIj^=^Pl}j=j7n>Z$oT5n#p6(&J-Qlj$1p0GGK0O KZB%swbN_!MVzTJ~ literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-10.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-10.png new file mode 100644 index 0000000000000000000000000000000000000000..ca933a4dda630afa9c85027cf08e0223177050e8 GIT binary patch literal 19762 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 KMNUMnLSTYA0ey@B literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-14.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-14.png new file mode 100644 index 0000000000000000000000000000000000000000..4da1cc7a78aadca8dd0c704474f48572d9a35dad GIT binary patch literal 28149 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

d78N9YBnWf_%On1(yIwxSK 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-15.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-15.png new file mode 100644 index 0000000000000000000000000000000000000000..83016457e86cb2c29140b291c237bac0b52a6932 GIT binary patch literal 16242 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-16.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-16.png new file mode 100644 index 0000000000000000000000000000000000000000..7bfa886e5cb081db0cb5a0e9b0dbe42c373cc8d9 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$lc1=I>B27zJAguAo-U3d6}R3VG-L$w4lVfVpUWe^ d0LY{SJjiG0XJG95*<=SY#naW#Wt~$(695Z!B%c5P literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-17.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-17.png new file mode 100644 index 0000000000000000000000000000000000000000..b63bc9a987773fd800b05b0dc80e0d1e860f05a0 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$lc1=InZ@5gCZJH5r;B4q#jUpo4H<#FLkqt8=kmxe d05T~75AqrM85p~MHratp@pScbS?83{1OT;`BijG~ literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-2.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-2.png new file mode 100644 index 0000000000000000000000000000000000000000..4a5abcc7e3b188e0bde9f44d2c79287ed31baf09 GIT binary patch literal 2390 zcmbW3i8~XF1IITrR~uz$n=9oEHTN;b+{b9IE3p_#k*iXh3gs{$45B_=o68{xCQ3)@?rLAGTsf%hDr4{T;wm^3p zPwk;yBWqnF*AQuZ1l?Sd3mYvI0{0mrej0&fl}QGxkvxF;-prFY%~R~+Y}#%^Csc(e zwM>Pj6<~tObMTM*Gyy3zD#-lh*iX5#`{rDO0<6)Le?bgFu)!8P?Qj=UxrqI)1X`)< zqp@y8{8@2Cxd39T7{Y2YNbP$n5s%tVP%U@_a|G=f6#An(prCwxMqm#&hw_m~X@Wf; zh3FXyUvEcfMCe90F6A7ps6}pXUQX_;N~RhvquaoE*K6M%V6a3ry9{<=o zvqHx8Z#&8KxxAKjW;Y?5gVsM_M^t4NQvn41y1oYngPsDANpoQma-e|c3HPQ*?X4u( zsSzW-OF+`Mk)atE5R!;ozXMkJ1=iN#8&t3KI3+#hdBWM&yQOfwPi7m5#exdDUMFpoW4Q3V5Gs&-m+#( zCOGD5M)|a<{Pt@<(>!FjzZ$}5?vsf(q$-O_ndWp!_w2_cuZUFaNP6K7ZStR(Q*+7T zC*!q127)-yp3&-RWn24j=OP^yUeonz}y5yZNPv#ZWGMH(gPPr+pdj!Yz_MrZ}5IIywQ$drPbZ*3oy;z#Ez-qXk zHaqW_4eZyB;x=YPsI(hm5{g|? zaf-?P3wQLVxfBho{?f8|X7u~%hc!MT*H7<7#sfcNuB{FIZE`x&62S$Uxc@8TqVeezrhYD@Oh^6;GNU6E=P^h?V< zhMHug6dDaUj)F+OSM7MH+pEs=YLY%Y8*Iw(Q>5wPe`($b3;3+&f+s9baUL)Q0SuSX z4;2Z%0jL+&Xf}O03NArj<%aK#)Ie@~Xk3L9JSb{&^JmlwY?{$n?Y zFNf+#YaR-}^t`ra+Hz2sa)2&FMRKtH>4JS0=*7^xypyZUABNRqWpkyCiLm6~-6Iq4 z=bvpVGd6zb#jtwcICrjN3a~dxK?h!T1@MG~MAf^Kl&ssGxCMJK=?*|lOlBxHuSAs{ z1fGl(6c?&&fF~F$7n)h_`t{cse*p@PpH#|`Y!KDv7kBUO6Lykv@Uc5V(X7QPGnCA9 z6})S$0D=zvup??&IwpJ5lIneiG@ez1`!_(gw|0Hp>AFYq-WkjpZ`j4?O5v$ zng*)=>SKD1A;z7pEIX>*uc?~@Rm@NfgNLT~<4nk@?33VbOoqy1h{!5>9cB&qa**?WyZDo=^g%(p~A*U@m-=c z@?W8*v=fBClPjaCWRBfec?^hpY#|*Wv3k+C4~4mu;2vkE^VDc%UQfJr%&n{~>>+)V z5#d=9ZDhQQnfkqXMYbe(>{~T{wo*-WZ}16!w#i%WJ0N*b5gwHa;Tw_b^1s)__j~Kq+*><{ZdZDOHeAb?{UlRnwvUK)ORFMV5{Ob% zRQ@6sP;R6BV%Y(z;i|hEZP{LfVp|~MyIZUt^c2|6@4t2^!upx_+U#D)T>oX-aut27 zYfU?B4JIl0&MgJeAGg1EtE9g>G$SZnCuD~T(6k(d*t4f*ZY(a1{?i<&ay}zX^lwgV ziollN5rx8{NwF|!(C6_`75EqBBxT0Er_ujL?MLJuoakjaa=6bO85c@Fr{qU#%;tT)RjF(Ek1$u33ip~Wr+8r7Yz}np2tk#4W^FM+$ BPPqU8 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-3.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-3.png new file mode 100644 index 0000000000000000000000000000000000000000..ea053bda1a403ca507870c2ad027ae6789b6946a GIT binary patch literal 3464 zcmbtX_dgVlAHK6L+ga(*g%c{uI2niJ?2(<3b;!)l9!D9GLqtY79Fjc>6&Z&+dlnU) zJE{?es5^M;EDX z9{Qd9)6iEyJGyVj*WzFTu@km`XRH!r+jQS%;Ff%B#ufDA=>Z0!NutWi0sy!RL0%3V zdK5*J?%3dVp>=48Wr1zt>%VSJXGzXvyGj!0O9)}x+u{9Ay$ym(={N9pO%I@0Y1kd3 zp`bsf4zqALt2zhW|8ru)5qOuquG(rMQDpo{+D6ug;0 z`kJtCQ?GLw+PzXtQsw+mbY$$;PT>niq^bo83`JPxs2nxZt9_OYODJqcG{=7VNN$aF z6Kqj@q>d)>SH}Z>&neq?uy*F}y*Lr+ob|_V(h}pD!B9%?4LFaheuJ$JFB-Im33Ike zRsq?8Y)7R89ul4H_nWld%;vf6021;s+f^lDz0$|=iIv&>_f@J+-hqmCfz->4YFwWW zLckz-)VgN8qK=M@v|w(-E4Q}~4RXa^sV5uI-(`f@$TqymgD2r|Z!h(akDI^Q>ChN5 zt+j=W%ZRI>yen*n?8pkrwPDBn1G#1M+ZH3=^J+aWAeWW@4)Z5JLM>VLj~jHAXuU2~ zaEhEPp7WNG51b^37el_{2<9)mG>1HznvliFV<1w|GHdby(U{p~o#3o*I)VFuCvfh@ z`9B!l=0zx(rEj@^zYqWBpX8Zv$Nb}-?`)ELX1dGc5AL_PMvRlJUj#4~N}~2eU6j%! zS51V~bNLF9p%)j;Qko%r;1dy43{pxv)b2`K0-p0CgCw)e%aV0jOu&K(bd1kL84?gF zwYqQFnYfoQ+)#}YO}eJEq93X;hT%+p&8x9u>;p9UP*GYgJtLFM;}XC~u{0*$m~&I$ zDat~&B)v7}Msuogd~$ErM?s(Pnc`?&G8T&kmJ|3w&>SiY#oC-=(v zogvo7=N35(*8OT5oa5;Ic+bwqc~Q0Z$YciiJY)xz2%AY1j~5n(bLNLB9Bz#$)vyU} zdS!BTbD+6YPboDL^75WdZh73xm%Jn2bUDB>F6vIfWlm(&tYTXgv8;mt;%y}dAcMHj zR654dgYFllo7&P7P0_?8`n`pBZ3#EtlwKBj`U6Ke@|U^V?Q~1-o|ilnA}?jzLPnT- z^1ZdEKfV+f6LoVTJ|05PyfhZ*vP)ARdYOEVHme?ZpbRRYl>)e-t+7D-1jm{OAbH&x zN{Cf)-^cp1Y~2mv*mDhu|8uTbplpa+Axy3+AT&`Kt?@0SvjN3mvmGUfL$z$>20b>) zZuBy2E%5Qa`!l3!;=GLIpY)fx0}pH&-hiZNZUSfi?!tD0Dh*>C@>K0#B^1$ab$Ekn z1UnAvNw?cBuBC2R6=qyW!f72B2t$kU7jD-o+-<;!n4`H0sMa&)TYpTtu-+LDQ`}n( zTH6*YA#^d^ zWm>$2u_~U)55-8bv~9@i3o7CL(Ee0r)o&NEdNH=ggZSmxHt76slU$Ul;><%XtJL|$ z;Y;C~m}EAh!Nu~!`qQM(&y6kp`59Z@ZJAnE0IEa?y!5XFr9awtPlw^Ga5cQ4HE@-H zoY>ZK1;bq?KMzw2NI9ve5nIfhbsqLqA@M8o^bCtd*$qMQ7W)c2n`*!Vb?S9~XvK~HBRT80z-o`aW+TU%t4LqkXugW3fG%C8?rU?yzHJ7-)2EOxbX5Rm>QBTVE)Z96)o5kZlfkUg%vTg~luY1)o(_j_ur#WmnJ>R7)0} zDy3rO*I#>nv)Ok9X-PlpJY!jOe*PRRwUA{NiS5Z$OyNM6Z}DP|7%(P{uzpb1;VVLj z_$+|Ipe!)vV#z~692#kZ3*x(;UQt4!tK7@BR5M3sUg_BDi(s3$LFfmL3rZg<^EDqF z{65#MG`!0p<_L!A#!lwJ#`#vKYc18Q=QyahLj=fX3G9YOWohDeiPN*?6SQnG+CV>! zXT-U{GHjCmM`yz*Vh5Qr8Ivrot6nlE2gLC zFy0Wg@eV8ROZfDr@VvFUU%TriGa4|GA3}Qajb*l&J<(1poD1Kk3kWtk=2;^$u1?48 z(q@s(kj@xG;&F#e$eOhSGY<**hkIb-k#?K)IE5`~oK3a8?_9MmqAL|@bZux3@KoW> zCy@gF#;lhtxaIpfgP9bzrvOA$=D>AISj33G_>F~qw0cw_>Nh$~Id~VmO`>z?ly14~ z4SnJUD#awd0H^g~=8G1$B1^y0Th`KqI!4*~9o|E@>Gjq5y7NYH|8PG8Bj~o@7%!%Y zX$+QVq(>&)&QEH&$IXN9t*djKH!5uxHysip^(SC;L_PGWZS_3|a)zy`en%%Gk|bcJ z9<}KY=X9dBN?H!P|2E+MKHp&gB+KRdSgTouX3-Q&2P<~!;-rXfv&5KTw~5J>DV5z$ z5Q`e^w%W3m8bHa9!ojpBVdJ|ndAXHuRIkt56|+DHY*b27e|HJ}m@Z^RH02rIM)Q*P z;I$`EmeFNi%k~jv2MkGrG+RDR1s~I{33z3l7L@%&*5A7pzMoI;W!szFuT98^c^^c9*Cm<%uX_=G_pH_KRbzW;Bp2Rpo!NSSJyzj)se`$I1h z6djY8SlDsy&M&%sccv5niLjsEuodVZJy=OQGz1rW`<27E?EtXp>`PpbtiM{z3Iz1gvTc!^nmI9NXw zazHwt%YAzgHW0blD_2BQaE!!u)G}`SAibNo@)jY zRoqLiueGu{a-U|@f*I4kG0Gh7x2-naoQBh@3JULnQ@;z*-qvCV3H&ISAST_@GhB?F zFQh2=%y&tmqM_X#Q6r10;r~R)_OeE1C{M%eRV|$X#WYkZ|tV zvKlv!i#BWUTdLD%!>IFh*SYF82nfDp`M@%xH~cdq?@M9eZ?ae30UU1wABaAn1;o9F zcg{TO8A!e0fjVU4T(Oa+moCd9=wPew=%f%NRpqDgqt{r^1c^>+D0%-Sc&w+gR#Z>x zpc5}5gBSL-D9hDFAPwr??yX$o*y=wZLLKQ6?7GH}7PCOZJM(`ePnp&`q$O#C;iCRV zMW#RvsFlsk-a-U4t}m{EjuD3)fnsvG;Rdl=iGUBXs@fB>a#G@;@KKL z71($hLKjg+Lxs_8deQjk`!tF2Ur*N8=zJog%P&3>5galfFRJ}RVeZ#XQ?1fmyGmHx z^+)W@SJi&K3f?+}{QP`E)@&Pb>{H_c9-rbk91ZKDZFiMMZFmq0od4?joYmpyR!OTi zN^A72q0iy*V-WL>ckouoaI??R$Ao<^9ZDf0`pmK}GQ@|T|Nj~n>O8-1e>3GS%LAs4 R{o70cT}>lo&0WX1{{h`6U}FFP literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-4.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-4.png new file mode 100644 index 0000000000000000000000000000000000000000..410627fd0d4cce78341bcdec12d284da7baf5a11 GIT binary patch literal 4771 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 a@s8&9eL56N^8tVBBqBJ}OutFjDegbT;=Ek| literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-5.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-5.png new file mode 100644 index 0000000000000000000000000000000000000000..3a1398435db3f24e774ede4b55f3ab7c2418d34a GIT binary patch literal 6418 zcmbtZ_cI(0)8`yc=akcX@1mCwoa6LPPA}1W3(-z5aRiA7zG?`fNAJBy4H6PvBm}4B zPPEtaH@v&EyE8jGv-8>6AGV|z>T8k_GZN$A;E=(!pvDgt`9A>>Jm?{1hp7ic;HaYs z#kv0<7x#R~e((_aX*~_Z!6BjkpWx!;70^F834`Ez8iY##Dq3zq;TtkN931*0I8@a% zboJ;zon#)1yp8A$c|J~`@0z{UO{^YOm$|TG0X-)rvLEdd%>?02^h0SSKwAdi(e~#A zac?IPC-qJs5xvsHTfjE_e60+-XB2l|D-z=YSqLp^vBE%c%0^DZ9XwFpQ*1qOfi5&j`J^s zt&f{#%WVhiqvFFV3$o8Aiw@$BK*ylts2y6tcL(9A-?TSHrcDic1MiU9X|ua zgwjG3oi+%g8jt^qMS{a#Y1-y$ z_Hm>W9 z^Ac%1`ydWzIsgEgfD%=~^6#e;L_J#|gdR@&u?vN}R1~ zX8P6uFm~~faNO=r@`6ZkN1-O`3}-h(=rzAGg<7a6kdkZgC_iI!W}R%r z4$g9Ii7mZyVZ}|Yy`}D`^-5x}^q_XEdFmtjM@rh#&8<8vD`_4&HsL{Fzih3}1L)EW zU{AYIHdaleG!(Wipkw°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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-6.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-6.png new file mode 100644 index 0000000000000000000000000000000000000000..faf33e7e28964b8e1a760151f0f89ee52a11b81b GIT binary patch literal 8845 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-9.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion1-9.png new file mode 100644 index 0000000000000000000000000000000000000000..25e83b9d5d598c4e83f106b0e6f4ace92d9df566 GIT binary patch literal 16936 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 bpJ3gg*!^PS{*QrYIxu*;`njxgN@xNAG?wxN literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-1.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-1.png new file mode 100644 index 0000000000000000000000000000000000000000..480df024b07f068f4620a119f39e7ab5fa9eb14a GIT binary patch literal 743 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$lc1<7cV(Xr&?u%7PZ!6Kid%1Q#^*_giX8v=ey1G& z;|XrQa}{1Sg|G1f-P`-(b^G)nAsbJd+KCJnbyE^&DW70VSj|6=<+$kn zH~lwkGj{ygopw>|UHz^HpRP;qo3};qaxdeJTZiXgn^QF1r2atF2gA@ehG)Eks?MsV zEjc>B#%$j^Z;n-USN|6t^?#nc=;xe^AEFoiZd&2?Bx1wOKYs7#6}La1^T}QFsg=?u z#v9A#)qi^2vDdo&$tT{}e|;VOCt_Kbsunt|YPQVpxM^yW*I0J@zxONuulAlc6%m`g zzAMT(^)${p#3#tB%J<@$@B`;*-|sz7*)M+d;(P|6A1Z96jdYZoxV$a|PHyOvIyE7S zLG!&qPuE42yXSbeHN3qT(weCAGKuf0e30ZsNx_W^k2D>cbHaO->+$K~dw1}CQ)f8d zZOR4H=9WJ-U)z@LNjW-aj@<%pYo1S1 zulDb_Ij49>^*QgbkDm757;Nvb_-XrPK1iCL_rC1G>D4}aBLjQy7ai+boOyft)B^qc zOnLVi<-+H@3GY$sT%R^GeexN>*>-CitEC(MH!*a6s_%9nHo{e2%Kj4X)V!6uJ@IlK QFiA3ay85}Sb4q9e0Hn=Pt^fc4 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-10.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-10.png new file mode 100644 index 0000000000000000000000000000000000000000..11183ee19d7706c8aa62fb1851b250f2dc92201e GIT binary patch literal 2075 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 P%pCy2%-WP>?EdIKHN!Jf literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-12.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-12.png new file mode 100644 index 0000000000000000000000000000000000000000..eab21ec9b1effde06cf4d6a0d645420fcced7835 GIT binary patch literal 2494 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 bpZ{^kTvU290skQ3h$jJ4l!albzH`if8n_iv literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-14.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-14.png new file mode 100644 index 0000000000000000000000000000000000000000..30cb78bbb160fb5c7bb08f1b093c2a553394aa2f GIT binary patch literal 2939 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-15.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-15.png new file mode 100644 index 0000000000000000000000000000000000000000..d01ebb74b1b483b130e7a5827486156465c89ecc GIT binary patch literal 3159 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-16.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-16.png new file mode 100644 index 0000000000000000000000000000000000000000..c879e83ad6da4749ddaab56457c1a5c308ff57e8 GIT binary patch literal 3388 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-17.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-17.png new file mode 100644 index 0000000000000000000000000000000000000000..28a3d654d01a773a68701cdea9c34b45f34b7e60 GIT binary patch literal 3669 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 OfRVnb-YXrKxc>on@4RRL literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-18.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-18.png new file mode 100644 index 0000000000000000000000000000000000000000..03333bdf441d07a8d21df56ca2588289c4b09e2b GIT binary patch literal 3924 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 V{H6MG%fGJy0Ha}`UZH9e{y)I(30wdG literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-2.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-2.png new file mode 100644 index 0000000000000000000000000000000000000000..8455a9342409ba49c3daa563c9704df51412f698 GIT binary patch literal 851 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$lc1<7&+}J1KQb^dJ@9mK45_&F_J(b~OsGiv$LHtH zN!b;Nc1wYYof}rDk14!6SHfV zB$8(wv1;MWsd;c+-$-oPa*1AV88ykrIzcN-fBuc@zkly-TUBiiL($DYRfmqDW~Y$|0=Hh_ywgqybNnjUb@7k!(^(# z-|+w5^UE=4w{4iSXV(-Mu0v(m>yo?O*|FvDFA@a=PcB@IFu~;EZT7 zzpp6}sodMW<$ZX>`sZ~{YLhqqeBBth-o@vcL~FJI`x%DR1x4HDvFjZODQmUkE=gN` z=R|#`nlgiV!?nOu8-i7roVTxh%dy1&FPEzSymYS#OH(C8c2;iAU??(VYJ*P9QZAmzAdbjd3l`ga-zdh8#9KTGZ?;}_)|39>#JblALHfx4Y>)zH>{$~ z8)G@{EH=9HaLN6|xBZRF8*Jv3G8@+YFP(pCxo_4(_ieND4ejHWZsVWQpvS|P@cMzG zVU7EVe@`DgE#pvpw$E&GF~38?|J7P^+t(Kb?QnabJgH#nggplg$~=xq3%m=``hOt4 zI=bf1*?Ej79;aS-R@GbZMQQH_2c11mieWF0*=|+z5BFjnP;cXd?mh8w*SSMIhR(KMXcNYx$fuU%?d~OPb4Mpl#mu#+d*t<@~pb{ akA2eCSIatnFR%k9e+ExiKbLh*2~7aF&wOtH literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-20.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-20.png new file mode 100644 index 0000000000000000000000000000000000000000..244324df37a0295563680fa1ae21cf35580f0ec1 GIT binary patch literal 4496 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 XtQ_qmcG3RpP5_!}I;yYl*+%~l^y6X4 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-21.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-21.png new file mode 100644 index 0000000000000000000000000000000000000000..b694fb70cbeb24e706309fea8349ee81beb6a4cc GIT binary patch literal 4817 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 V$I!Kg|Cc=jP#XH`^{VKo{{x%O#k>Fj literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-25.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-25.png new file mode 100644 index 0000000000000000000000000000000000000000..2b3abbf70fc6b7d236398624e403fc1312d259b8 GIT binary patch literal 6255 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-27.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-27.png new file mode 100644 index 0000000000000000000000000000000000000000..6709f409da92956617d4ae0f03915be388f28b60 GIT binary patch literal 6974 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-29.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-29.png new file mode 100644 index 0000000000000000000000000000000000000000..2f65762cfdce07193aad4618cb1d0832e8279759 GIT binary patch literal 7822 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 TzxLnf7(+uvNBNhcCH(&Y7J$N4 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-3.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-3.png new file mode 100644 index 0000000000000000000000000000000000000000..836636aff7defe0e0b831e97b4193aaa140bc0f1 GIT binary patch literal 1138 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 TT$AD-qz9-gzf`JKunhY@&lXJx literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-31.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-31.png new file mode 100644 index 0000000000000000000000000000000000000000..bc98120950bfe1a008ed8896892ec4958bb43ece GIT binary patch literal 8580 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-32.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-32.png new file mode 100644 index 0000000000000000000000000000000000000000..fc22f0da096bfe9a148b6acc4eb68f04237082c6 GIT binary patch literal 9082 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-33.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-33.png new file mode 100644 index 0000000000000000000000000000000000000000..69275c6ca02eb5bdfb1051ddd656d32e76932e69 GIT binary patch literal 9505 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%0D|^iTEmD@A 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-35.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-35.png new file mode 100644 index 0000000000000000000000000000000000000000..2d0ce7bb161e8472c2f2292d7fb3d20d57b8c509 GIT binary patch literal 10475 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-36.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-36.png new file mode 100644 index 0000000000000000000000000000000000000000..31c873a87fef5522ce095cd3e764f69024752e70 GIT binary patch literal 11068 zcmb7~mp(q@-(UBp0MXxZmIX z3+_F0=9zQm^}Lw*%oD4pqfUTJgNufSMxX&vG5D`S|Cd1Q|FmDuX8gZ`ZL6iOg7*Bs zDC{cx^j`<$1u^wSL&GEeU!tSsOigoalVZ9|(w?SwpZjwdOt^{5!F+%v0|eIeo#f92tr9UWXEyyOB(i~jss zb%+vZuVSyV_x8(?|3gr!(A#3ml!CXPo>%Hj9w!R2z{ps#PWktI zp0#+jmeK(qi#Xd`A5Fu1J}haUAu_Y^xA26vWl{I+AOukmj3^qG=nIQXwf4V4(ol-Y zcJNIu6HMZ{PZGHrbbeU+Xd27ZO$_UqBCRICx{I^-e}fupweKOu?|@0jw-34Lf!gVV zJo1{4-GV~pThJa+ar=DT?^Oa=KuB4bIM||t?e>H=Eise)O9Rs(ca+(*Y3gw%jjR!x zD7rhATHw95R=F&X@O!yNfc9{=aA%%b(0IO<6~8-EzR6~fpZ-O3tWq1>};_gf1J)huhY{V{+bBO}RwPowvOq78m&~k4EEOcfuA!^c=m) ziGN*BksE3mRu5fvDuU+&pyw;CG{#H78An``rgu}-(wBieYG+(>+YaV+RTZu%(^tIg zf#9ih5=O|_>UMwHRM`%X@}=Qk1W4AWdh&Y>eoukfdM5^@cV~E5xqB!*zXhtE(DOHj zEZb^a^$|ubWHBudr?yVwmq2i>)wM0XI4fdfc&~0jgtzr0BJtTM^N&7S~MhmjeU}JDsX_hVQ7FSkQWYL2vMYUX^Hhda3n(n0Npq zDg}@xk$JpynEw*`mdUw|;D-Qeo#e%2P10_~ik_41GFjdt9%?Nmov@Dsi31c@h)-x3 zb>`2s_;CymkTF9p5+mwZCBrmO!{Tf`A9bdVB0CGo+xEyGWJg(|zFnuMvZ27i-Lc8$ z5+c#b6ha=ckjd>6x(w{G78HwG496|Uy1)L@iiHfp8u00o-|d?`j`x=--Xhi9=0{z4 zVh=KOy`;kM7l3`cPlOD2jwJo?740MM@5i2xZ$t=Ru66H->uAiZrAWlIvs1+Q zlbZF)JyhCn@!}bI%O_0zh!wQFu+JXh10Sg-SPpbZ!e;_LGsUKKM^L&0+-Y#((HSsO z?ZsbK1BNV@!r1W!TK0PY-y*1WpSxW)o{WixfoA8zh|-i148LAyI)=~r4^z~h1g9r$ z-cOSeJimQgv@f2`-AGGXr!4G^@4?au0++0{mAa_Chf zw2ULJap~R9su85?&%1&&6nMMPnu|R=j<_~4(-*!gY*5Q|%yKKHBo1^_`LiOi43v#- z<3oXs5dT1>gldF&Zr1;J@<~*ZO;pG(*cyz1siXjkD%mk7T!kXrX!NWfm9goLGZeZFF7!(on&zf6JsYRT4oXIDSS2_ui`52Wf09f7 z9hFK24p2ngc!eONE z$Z#=D6LUed4k(c)P?*pNL0(t1E#_D8hCXCPBRrLoiWZq(DvXwf2*yXk;niBod3_h6 z%j=xUPcdFT^t1%2*KFS`SW#L54bfXXtp1+@U$PJii-~DIU1iPzI%AQqIGM)H0NbXV@bmHxX)rfowueiluc{$fxl`XF6~q0=*8-ipEqNJ$k*;WS3E zVGAZG_{#z*Rj%-SW}&5 z6)N^kA@dU1h?=Ls5WfQ9RLNsEP zov_qOUc=j}szqr#WpEOK_teLZjvxswj?<#}T#1jEj!`BC2?E@wG&z%*2^%e5R}HFY z$pvT&0(klNHBgmdr?#PxBQjm_B5J?y^7oYKex&?;f7T{P)*PZrf#0QsfZ~ zXXCg&W#@5c`F6Yl{YfP0`42;05VLYe$Lhh&NW24#n8y2qvQ-o6*L?h(8v#^o3f8oJ z|KT;egBf^0h!|}gA)|-(fB=+Mhfyv(%T$Fzto{+OC@8W<4^bHn3$8}516pyjO0C`5 zAHM>B`4xRe1fWf*X+ukW1f_(k$?9L;aY7!LBfGUlmrGvBjQjJ2y)o&&-tgy|X?it8 z)PAXM$1l$SE+3{shwxjG#5Aah+j9Mom}6=Z*eYe47o>zze8xGWQ(=Dpfp6r(dPsav zK>(feaCjE6lmn>MS!r>xtwzVY3ikfDZlGQL>FRIky(L+H2rxBTLBX)s1@o;*I7+l0 zqp0$E(pI~;OEX?ZnrLX?n4Iy`L-N5mxa*x-bH?8pzD2xTcqLQ*<-n1Dyg($j#K=h< zUaduHLU2x3VAcy+f?3Xl)6GY!uTlZ}AkPg2i>f7W!X<_QRr20Lz=2T?%!8dczY?pw zGCNtG>?Fv#R*c}^eM_zUMiD<9ngNo*3uh7PfbLF^9r@izyHMxfzfun4jwgA(0}gA| ztGicli2P*UV&5@bG&pB>L8P{)W%%Zk<#|ojZYB$EKzok=T^dsQSx%|?c&(V(Ha`6iU{EZvKjlHZgHsz!zU zA<&*mAT8o=i{8=nFs>~Q{ED@Tv2{ib|L|G7;xXPEI~9hIC%6W*1}47&Py3`j-};S= zk`F)U1@t8C5gc#F0e+|AJ}(DOEIEqmzhE0@rTGgEcb%DWuQpYxa6oCLi&9ZfL|6!N zv6cOplEty5F0I7+p;v`+499Dk3SHY}e`)$!JFA}J_v@4kPwGGeyoI@f+R)oHe}(n#S{MlrKN zJ{>mrXoC6cclV%~c6a$xkBxTUvW-K{HTUvo0dOs1K^ICfS>(*(fT4;hly4_=OOv=0 zd{90(8b9{HBX(z-0~KGu+TTd4uNLC5A8rQz7Pidb{s`k_u?Fw+dwF;#837ni1U@xJ zV2KTTZH1D5vvK`!v^xO!sYwaB;Yw`d)ohbPNJJuBwX40~*e0vP3% zyknf8{3}##a3DW%C4uH0HzT3n-Mr?|d@-^sbq|MnRipF?<9~10H`ZN zk7RoTt-}c8EEOS1ng8u!awF_{CtIsx19r`!1*_&5{%K!ZZC_TT@oTvw=};%j97L{V zS{Judx8(b?bMJazgVi~#CFhUHCt0-%c>n0P69MBG44f0(tm)wnqb-uX7ZYi@j++DD z_Al6d$=D=lF!HRf6N2+?cbrSv1BIC`KTp*fjhwBWHhk? z%-}RC7AtoZ%M(W?PsT!WYHV3i8T#av{I$KFa(H!NZ>DD`^{>fc$QNYyfyIxa5l-12 za>Joz$_8w3mDOeZBJR5r+D2g<-5{#lp&$DeTX){$4Z@-c@FM3S$aQSGk|?DDZeAj) zdDoI6;5eX-+uCodG;Ms~-o4#^e4w)#|L$3YR1A0jN^@8Pz2Jgbd6+4PfZwfn38669aW$R8{@E1mom z!%CJRJy2wt#}WwPx_hsBp7uIM4IWPt*RC<6m#)Ti$)b-E9g-ckWwm!F)OpVw<6@)U zl5$l<7wX5w$>b6_zbRDfO|PWcLL!MRU273R%9mvxjs+sZ#xp@T!fhtEA1f+l=hnQZ z*K)K!_`v6UK%AQ|f6HLeak>%mS3?Ay0U2libOYGm!*VYEbEE7-O`HYz)aE@Z6XoD0 z7hS5s8RdbWSnu})Qzo3h9HNM(@Odn13E!TXrCzY}G>SK>xn&|ap=*{ZeAME4CfB?p zS(b~4(Xs7!P%T4&oU$mRbs!c;{hNZir27^{5^GK#% zZQgy?qz&n8`l-wKh@J8ARlPET|3FTIhADk-=VO0zCjCNfpiDuP^zFeH1fFcK^u}l2 zkZPduOPA`{*RU3PjOnPt*ar7zD{Dn{8F3;<%EMRY5fNB)rW+#_|B{JhJ?TX@b=Rs& z8LT=&*UNuqlGO`#MFG2~q2>>Gmt*XumMVwA_`?Lvbd5EbL)#cSn*6JetH$_OCC1O5 zczs2M)EZ+AEb(^fkg3+llE@})00EhAwW!Oc!2I`{y&{W;&D}+41p8V{&oj@4KH_&< zn_;r~Z;o-s8Qa<)V&W4{KPYrw3RbEbbEw3=6Z#B~Wy5+KOwx}q4u2@JuPgCVgGA&Cr>vguf9MJI9r{30j>WuUTb<3;3oJ~yv1mlzFzu6T?h0%U+YB!f`{8Y`N zlF>i$kt!V;<5d|h3g$^U&Ve!+E<$D)7edjBYrXF+I@i?q0r$%Ix4W2;+Uy$NP#kEq z5%Ky`g_lCOk$;n9qNS;c@FZi)jh1q*@N+2aUd2oAFtgB!4@8ehR)gxzotr}mm2qh8 z+GWGP&?Vq-V#uJ+tC7J0srEWreNjk!)F#Svy?o0gDtw_9<-GBRKywoyD=13AGP2zAC8IWqz; zYKew}Q5N02yUIG9pae3mGkv+CTtmnYr_>Zc;mZK4TxiX*ht8MM9S~UVs{Q83TinG_ zu(I9F(sI?lYX2AJ`ewRf4jnUrk(AOt5KlKX=t;}u#64iMG0X?(wF%o_U73UWCqU^~ zj$&Dqd1NpWw@f<&<5akF(0K>mD6$_Sw7y9+4(#sd;yBH7R9UKv5yZUzdXZQYbIO}V z0*9o^4QoY|OMm)ul~Bq_Br~xCGAEQft~~gy?=o4w3x%yxK&-YNsRW)#s_qA9jF#(L zHQzwL>jkIHn)HlY2|UQvW*GtFa}XV`T`5%Oa&H9V6VFylgQJCl;EizrGKYUHfj=#s= zqZ9R{b4+lx@%&wJsLyxX7?fXDZ>aExFb`2&EtT<=&UTHMc^L2xh9{EnVv#gT)lrCb zm?%@0vVfR?3GsI*$f4~Lq^?E%gREIw=Z_E9kdye3R5Hbz?a0e$C8;p34Bo@sz}3hw zqIRto{Kvv;Of_=q84!Ns@~Jr&FB!HPHojfnhGKmLIi{uo%nde%yY+4N{od{2JnJ9Y zfJ?Qj=<)os?(Gp)T?$D}OJOjUFdg%wnC2?`hnpqMs`a3_9DpT*n7MFee?_kl2ej@V z#b499g2u+Hz?1V#3In`~@Yrx(Oh<9hF7_>-eM7Xr-Fv-yI`Ra}{+8O{1GG5KShQk4 zKpjSK#r98+(M76a(ZLn4(lP5UzmDhhq|L^>h_jiqw58(sk?EB$GDx;5iPlVp7qjH! z0ob_4wy3=G-%M|5d0V+g5m_*>2YpX&$g^aZK{Xg6`D;mx{RL~kK+xQ;y@IBHVLN~T zC+sJB!GZuk-&pqmxKBHi`Z9X$r;x}`>;f%J&vU)3!CJi!=*|dlDq5q)O_NS40vF87pMu3^pb+X?%@e(og`EI2iz?;X z?W79HEF=Dj{w7N4wGPUz z>dA8F!m^ki7aPeE=ah@TLwqK~`R$EDn~QExj$yJ(2h9Q?rA1@0uD@nGra1rZgGK$5k5eIrE%Tzdq}lE0)%Whcftd0rNH zAcmEJ?{~3z#ax(mCAbK)GvbmZoR}m%n75ia1S=u+Oo$4K`C%j}g@pn&4_i(_3%dm% zYO1;$;nR-TUA@o4< zcnW+9QEcEK3*?SjEcw^fieGPSx@5 zMlqK^v28r)0Y6tcpW7f`k~`q}SE2MXK>@X(jkl3aHT$Vs1;{~- zX1tMcX!1&qx9-Idr5@(*;a*Uva9StaHnb4PLO>At6Mtx32}kIAaKR0Z04uA6!=cHu z#}{Zp;%Q8S!$*8C%(vGE4E< z7^a#?Id?|Gmo|MpnCNPBuUT5;hU3>tc-(ue{$0u*BrBLMYHbcN9Pd($rgVC>kIXum z8YO#tiYQs*z5nlRh6kB%WiKNceMbgfq*BN8T%k%u+Q<0hr~$T%m(9K!8j-(rv~SVC zjhdXtCcAQzrt`15?;2vBn35vX@$jAUSg(>7c@`(O{_$_+_lDrrMibq8{__`r)w-7X zFNbGDZJT=^+eN~^6b&!s2Am6NKEsM1C8emgJHG;XHhb<=XVDk}=ohI$8RjJJqMFeO z+VO%Otl7$U?9C^z*Z5;N3Al+4v3`1AfWrKRE&d04x^q1>+6Yl0QOkgAT=!-5b|c3f zKj=!doZ;^c*>Oec`r$?rZC0FP3|hS3fB*f5huhLge~otgTy$3m&aONh zMe25rKC`Y6W$u)@)kOEnOs!4E6KVQfoDJ1NT)heBW6zaF-}He3?Gmy%NvfE1Sp&hY zx~!^iwD`z*#j9A&T89O}^~Hn@JUfLRUOXv}Q+5TDr^3Q$9`hniR$>0jF5QNMf6}8x z)%2qaYVJMtbD6?M@U=%J=+(RYQ)&Aqz;4Gz$wg}_u{RC(*o~dB({1|2>f<+~7MimZ zWV*D!+&`YbLMT7zk}ii2)Ir8rN);2p+MOm?e@QrL%1k}_Jt%zqI~9rxxsdC`*IG_F zLE7bV+xwe#L6=%@@ldD-MS55boeEJ$0pg4IoBTE0%~yDCb#l5R%E4x{nR6QzzIQP> zz>b$iIni`-#vkPh6a=Dcn2!@|e1YsYUQhh_D*?XAEXyoE{WS(t>gjwre@ZZG{#tE# z?3ElgH|{CaVNx&yW>gnaa@m8!-L}WdB1ZR~U!hPO1`jPF-=Mmi0%wRXvFg;lfB#Oo^m$au)Z-I*Wq-IRu=>x6l0ANg@M0~m}(I? zAAT2kUr@&yvwjJVocQrMZNCm2$H&B` z%EYmtWN(-bu!)eOoYLe7{;vox-a4Ni6JVpZS(qxL+X~yendT3z?;Q6 zMYH{7CEWy$G-^$V3X7Ii;tFk9TYi4_lN9f=+NX)^2VG(sg zrrDvs$D(3WFQv+|G?}@iv3XCyD@G*qI5Wp>XU>^S*X(<+gXBPQ`d4uzut9Ynq(uiF zsM?5H3ombO1#aG|`BFICaR0-^z2goGxp9UEW7pwtcWRRu4NsV1Ns}fMV;Ny_F`pOv zyryKO(pHG;kZ6b{59Vsq-n$2!6Doe!+PqHfC3e$5vMK+!dYa_-{k8t(y_MrYKY35- z-Vp%xm?d?Ss%{*aDuj`#C;iP0>AVrvFgeNdcC=3o!c&dy-2_WaGohHJKk@(d{!nkH zG55jlpCX&nUzeL2H_AA&RxLzm+!b}uC3*9SVf!qXk>F$AK&T4$HTNIkjV#BWMfP0= zvws+zdwL<{>`%<`U^jeggzRfUm2~j(1o%%N9Il_?D?m?LDQyx2ydGW4f*g}XJ_N`k z+UWtTA*tZlwAlIgoW2sS(|2O%u;b?4N33yh9=m@t;8v)9>KbmRPNd~jNyuz`%+j}V zOu=|ja3&M~j<)Q&Az?~b8JY4HgHQ|ZYiV2Qu+{O&#fV1!q^T|=Wfr5cQ=u_jw2k;w zY+jtp5{;vfTFz4PWKWrct2x)2D;6uOkK|VR)*7=yIYel4{t2rz%g&ANK(`*-iw~pc zXRO-S4;~cY?_rGFXWNfx!~6|84QkBeXxs*+y5}~G=A}E4We(DX-I2cI2dJ`x-r$5~ z_VbpR;QZqpL{F6Ke^v^jO1zn649Aryj$f2hNunSaZ#i>S-fAgPYhM8Bfe&Tj$4yyyv=1q)! zK`}3Ag4&t@>}Jp|#53;Y9sZl}Wwte3{kD$P;?+!m0u^DqT&fi>qXOCyrA)AAu-H6Z z8L9dyUXE={gX~4QhF%neLt+}e3f$<|@KuGyyAPSC^q?E)`9Q6Sli{8R0X6LG@n)nc zbVnOAZsI9}@lzhtT2~Zqp@>nJ9?+4XEhaTDs|l0|^SLKHfVP)Ge};3Mt^&__6fAdY zxN`=cR)7n^u;=j+lMRxO1bxeA5nzK}WWvJ?PP z89oKvKgUN^+PmF=XSVI5C`ey{ncgt=X01MA2zV4-%8e1GtlGJ87Ulp#@k~9K2GKS% z74z$CWgoQQ$El9~DH=MJyf*l(naus^5(Uu-oH)G3ssPCm}q_C4|`w<1lQsiGeIoe$~lnMQubJp4;L+fg^53M$=I zUtc&vf8Hh-z52@>p`Q>#!`7Op?~5Sm%U6h%Dr5Q%i+r;&-0sd1b(!f|e@T_U`#Ax5G zRYB*|`)2=1;=d69bEk!KBq*t!V7G3tm4+|4=ba%P;Pu=?Ix#RgRZ&HIRt_FkLR=Ly z;d=J9p%kz5zYW5jJ|x%Auj<1zr<2%vqwGptsWoTr2>N*LXDk`ci-CEUwy0PX5pXkZiQ7*B0ix>lh;mc)c+kXvKmWStRzwArMd=Ge!0{R zwFhLRV|y{>uTn0(`4MKZ1{91L393nA)KUzyKk;5UQ@zw$PE4CGM0$)jdi6D&C)sV^ z$kthgKew|7kW*3Si`OzPX%wrkzdQQa6?uHKVf5IuFFMhc;w8sSK%>%{NJ8UfC?|0_U*yLsDrg1!WrIli7mv6Vb5GKh&Nr>GPGAfbYXgd*C6^6DP3LkxVL0Z8XWd+)}y9q5Z>f$q&MhedjaM zNsKLwxX<2Ss2>+a5su9WS7Wxb?rJ?E44SX+NCs5I`qV()smS*#nh9JI`a21^>?^Ho%VNjhC~76jcVobC^ zN+B>|z$rX~Vaex~Z=A`CH;UcCV{typqoY(-^wECjwkBiq-eEGRrR`V0;ZIYX|LdBo z!}0w%=pDM`+r=3`Ga(3)WW;g%46`v3mbdciGQJr4%(MA;|20BoVsqOf)Pl3KaG4P# zkpz>c0Nmn(+6_JoJ{~v>-UareNE6d>JGinX2J^s+uY|{{Xa!iKMU$+13#dr z6`h*TxA1cXtTxT1s&V!QHK;xJxKrEP=>6CAL}OUY1f1SAbGnz@gtzwcok3P(&Msa_fL%wRkG9Fkb~dXZO7^io!|Wv zeqV^JR4Xv(U1Q=H@*2(k>+EfiAn~B0Hs> zwGFz#_b%B9xNeh#E_&?&1Hq;-XNx4=5BEzBVWENgy>HmUV~{)YYsslgH* zPE2Mrg#z9&buj}U>y~f)&fPHDYpwo;#vC-#*khvz!{mPHsgf=I_usjaxxL&1SpxB7 zZis@ACk>@@8YxlOn-nq9wE1Ma^a#OHvdE^qZ4Fsv8RH8F+T7DdyoDNn{w=~3r2gN( zZ@jr>Z`+g+wwrZd|9O0y&FT8S=mf-~WEw-sM{}jq8-;P=Cox0vbc)%Da5DT|H?ZE0 zu#R?bLsEsTOrS1VbxYj-lV%~ZP3`9t?U7rUO-UAAtf9vd@7nkN_1L|b_IxCItJLjs z?f2$z*M`8t>k(N`xjCI8C)M2hzO{VB7~C%ijuL8QwxzKd#So4owu?&y3lfWh|;;$qAP<@O=JN8^cLkcdma(}VKUO-daGt|G#%&n zPfp88OP$?{ZLwi2q1bK2f+@N!OqbtLIhW7U4!8bQEDR2lInHG&3E9eR~C7- zN{4*~S@K2MV*W`6Li@8^PchGlu2UF`DoQBzNac6cC6*pZw2@DxeCF9HjNix~jg1;s z<1IOu%+!cx`HK%gc9i))vD#3$0khx=s>3!%>nfN0C#Rxdh9MNLmo)G*&i7{BR^|(J zv5*1Iwpd5k**dOdkt>A}A~9nec0Jw9(R|*jZcai?N7^A<)Z~kn^kOWjk=K)J;wE%l zD}r(igv6aOxoT>!nWIZxJ;pk$Bg zusXiApHJG+252tsg+aLGTKd~r_Vtl{^{de)b!^)V$(-}WtQxFqDti0pN;3pj4tQX3 zTTbWUQ#~d4iSvg_4TWxv zBCAciMmM|IGB{ea#coOH3XBEQr|;=FH$La@FJmi;!zv)3u_jMep>gle`q0=^91m7b z5&OKT0*XV$FEseTTYm)~{)l)@ZiZsgJzMy&cirJC-CM!#c zBHTq6V@Tzf@SS3u8S~k@c7oaxctg@T;-34{=0j zdaEq;+QbO#R{paYWEBKEiMgBXGiiCTQjD|ez5?8v3GNK`&5af zj{Ql?Y(=Ks(;(&&JQCqhx-X@U`^gNkV5T%>{}`pMoDv{n4vQ(-oqEhG=cI;+tEKgU zEY~MZZQ6TyKYvBwY(}nCz0Yli)uF|1UwStn5cl~cBOb+=_^lb4poU|#V(cUB@EN03 zIA84xqoP0Bsr%*=e=ddR72)vCt8I6}ec#$T)Y<+6icAc%o7#RPEdpLb+NVdVHApmY zmXGL_+vrBMkaJ>sos=FsQzOWmPJBWZbE;s1)PxTZD`Q0U(%Z(; z!4f;yQ!$}a08)xAM}{=_DurO1uJuNR!VOqBC#R-gV8&X#A2Aq@dVgQl>A_uCQ00q2 z6!e=wGn_1@E9P1zDgZ9uaO~2JWNke=JiH!wS~*@QU)L-0t_QUob>l-C@FwNU#mcp&bOll8*FA0~u&U-#3JhlddxUuM}tBX{PSci&&I zi2%N{w0QR7T~EINLwrpQRIPp;tCuG zlt#oA4c-IR63NpUg>vW_wiMDTeAivAqqGcG1j;MMDq*!oR13waQ`rl0StThJu@}_p zY=g+Kuw%kXA~BL6&2k_jjCh5=mmAr&j(E8pR1_Wk=pu`%)vJmw z6DDtlEf&LMG=&Fp2E40ivcS*)pn2jUU=yb^^4p~T)Yz6PCpQ2e%Yuq%1c_6k+;4blg;8eTv9}*D{|C1klKSJ084nEu2 z*8TcAkAKR=peUjvU2xsCy~HLjh_lzsf;u~JFB*JF(prrOkg5UZiYMW00=1ee07~*4 z;r65ne)%0(s+d>8P&_eQDMRe0*b!8E%i<7`@)GyAT^2wJ*iM!dJrSUh)I^5}Yl;b2 z5zCVE9_C=oB!jNnHp9Scs4k(D=WC^BkhM2)Cl&k6G6jFr70jYd?Tt5NhI-uQZz{;= zJMcqBSi2p=KdIkyCk06p`-&dE)?^!>7TNyEAv@h{5QRU=6DPmS_2*@+ILtgyB)v>D; zl89B`H&u5s4nXzfwl{WfZG6M*gcpimEn1!0!lv2A)7d)f_I%%J>JSFq?=>uvtk?!?w>8fIyb{efr!U!V?xzQ2%mu;F3At#dB~d{9w=aTJRUo zdxa5#@p|>KJve-tI&f^zo^VYgT{Z&QLU-@E*}j7{`W31TkN9b}b} zzef?E>s@DgqwV$T-KGTw9Px_&?m(})faCg?MFsjidhYj#>wx8J4rh}7CMf$gU*&yU zD7h9YtwE#(Jd**m=sJ`BIv?`%5jcNzSx&By9!hE))cbpNx6rrOaN=3&EXwR&FVch_MQlQ=} z+ok+#bz^6Ff`c*lxx}q5rMn|ZKSFoI1>n6V^e4NVLFGex?lq3e;jaA?^}8o&ayfOQ z)0YmS=hbSD4`c1xt~Ejl%s8u{AT_}+Qi<-=Mk_vR)??wpi&@CC*Z=kX8Vke6%U$wm zEtRzxK|9CWqXGF zl<|Z0K|Vu`2x@s1x zY?H?7h;Kvozwt zA^Cd2@D=d5VVf%)EW~cuKxYh~bS}?`(*pk#gaX0N;`q1vD2dyG=eFv;E|av=1h}Iv;j|~IIGxEre(JYC5%!Q8^_;t;>XnTF?8aE9*ZIq3z;#Ce zrE~VA2XdI6-Tpj$6UHd~2|JD4$rTu5Rsz-52U08Q5_w^6M-xUANY2v{D!3{q9ns__ z;K?%JcD`gq{3r@dRnVji6dUWVeoMqFhO-L|0eAbf-;uV5GC17Uj)J~IfcjP6@(|m$ zxD(fTv^{EilUH5(gc42MS}uliTbWdBX0Xe_7oB`hfr4ymS4dC`w_OcP6UlwLsTjq^7#LbF+=|j8@%= zXu+Kj^Bu5|w4F?)4sk}KsgVaxC-whWhf_|n;PNj#W4VkGU70XIa{`zkU_3oKcY}KB z5uEXm3akdg(W!aVn#L}?`&o6UnDz)*XCslP`cj~tfggyjAhCpeDcgU6EqJ@6lh>C7 z(!x~lk&tiT)jUqw!R0nbaWH~GowVGhH!lmB{Ri&z&=~tG*f~kLX(71Os8t#L7;U;| z$C=IZnfmT)Y4@myewqMrEM?LO>Y7Zv%Qw()I+R!NL{$8Q+1>Z`d;M5h4KiZ^>__;dBWf~W3!3T@zxd2 z`)V+;-m7u_#<@o8psA${UAlZ>r(qfEU~g5oyH&!%vunoa$Y);NT(I(z4iFGCgk_9~S-b9#&ddOiFr!LxJggUW^6_Kqjs^1W-gja-JEby1>UoqhOQwd<=cdck z^lX(;HRNAGK}%(_rlv-8gHQ)6GmnHAg|0h5p0Y5oU;eXYouIi*RFma9zHP3DHeW00 zL(O9jl>~|~3HxNZ6vF^CoiE|-2qVmy4RIWnIrriyeP6I4ff~YIw z`sf=&^w?x??bj?S<#?2W&cv3^Qq)mTpZBH9&=BebHtqZ)kF9|Q$3UEXBcev9vP@rU zL01esc0;a5$|Kx8g|AQFJK6kq5w_^S2p+V>e2)5;ci#Z?{-RSV}6phwWk4oE0 z3^tB`H|Oqi7>zd8KF&iy4BF!5A(#Re9}Yfb*7JsC-aW(}@%+6b+jh zLg-l`IC!l1qE`RpwpAB8#-k|Zh5QXkvG8R ziwe=6VU$ym78FvKW~V&<|pwJ`0XFa|2$hnco`O_R3*UgJlIlch5f z0POKo33^qv^(3lL_vP-XPIDE1lII-f`FwuQ_)F@^t>X7_hgrnn(JrbK0n~uju$kd6 zL9GdPn%QE+_ePkP;nxBv1xv-19TT6PKf=qF+LDeo5%<4WJrHsZobco2J4~8Swj!=C zA|tQ^t_gs|RH;NABj)ZynPh6yh7TM=3WMyjQEdL@w6a4~Pz=t^FQ~i2# z!ASQs$Ien6Y}mA=C2rpCG}tQp*C^9 zp!`GsQ0dLmd|2P9H@M4OqdiU&qF-ihEuV_jFE*4)8&Q97(2+q)-YjA^z|qVut{r_L zG%6PkHFCE4^pX9K#0;fpBW-qZ)9HoP(_K->N;xC#6eGB6jkLD8{>2Vk5dhX8(tx^a zbd#0hV(9nrIqV;q-J3r=#V0mmWRC2;vy}A8`NPc>g`o(a;VRIm3yG~`;G?}_Hqly~ zyuc>te{$0d!&asZV6!{{EWpj12y4;s^69$WF;puVx1h)UYA899~t0quQ~o6m=_TPkX9_C96~! z=U!<`LRI5S|DC}Lx`S&N7IldB2pzcW)us>s#gwiF`BJ!r$EL*DrD=KuYoCOo2HL&W zXCO1W`)KsJ>G%=luHj=O{ea9wL-jiQgP}U^+<_v5XvDcuo%=M@OfIXB6Kzt|Xhk9I z*7HN^l*cPorA1x&3a_l-v09@SkB~a-f+%Ga`MIdBZ~ik=4bWvFXDUc8OF!8Fe;FU* zkG(a1AvT$06Mlzrm1Z)@^?9Q={-Wu`RoYakUdJItW$H3dNGajvbsSu zI+V;3XQ(^rtT*XVe<pbY6%B2t9=J&m&IvIwhi%&ztfGP?m@Ak=da~|{N5g?a!JP?ba1+d zwF^PWsg2^3>~T337QZ}Kk8Wg(!yA4E2ZFLhc?bpkrE1?QqZqnPWWBCaq~9VjZ`tHe z{y8MF&W_hSvXZ1FQu0N!waNLe!zKOYI>_#UFdw`(<&4&$3=LMzH)gphQEx$Z0bUY` zHi0e6caCvqsC+;pHjUD;VW&jW2IPn^G?M#IpWbl^zKgcGj$1wA$QX~&uxyFd^^~+F zpNX;ieoqwqh{NTvX7{p7y77oAW^QPi-t=pA+{IUZ0|;ls+UJyUPXIe!++>-iPT* zfdmzDqRJx%rEeO-Bad!x_v^ngi7VP%jWaqe)y1OHLA?^ zSly8#`#gO9SDA2!D5kF(zdg?8c0EnXLvP|(!$g4NE&`iW_=4FcM{_s`P8_LH6;xqRO_xTmB6DdI9&8>CIu3+a|E5(74Bw&xbQyRLQIcQ@ws#(VoJ-$;c5 zq)z!H#rx|@`)gAP?h0woN@=IQ8E7(xmmQGZ=gHZY+&Hwt)tg8cxAs0q(nGQ*bi1MQk-xR4jlwZ>Q*%)85-2+$J-@P$p@wHJ`ptU3Tj5s%YEF-Qls!Q)TB+ ziOoi|=o%6R*Epj-+1r{bZt+*Sz02BdJe;R4wO+1MDPlbxIr%5fuEIVEm~s@D3xBjy?yboQC}9*YGDELBoCbs)UG?dY8Q81*JQgOzc++v35HrW#8M!-s#BgT)(BzM<39P&7oh5kI4u*UE z`bkq6rv5w+%oO{dYjGYS!pcE2pOL)zz-1N1-FV@nYm>xpYk9s)%ER?O1fw9;x>97U zIZw*mb7}*QzuYrV2Jq0PhXZcUrpIb0M~A+xM`FpP7-pHpsT^GWB%_UF6Sc z*QD%S>LaxU!e`OkQXRpTTS)s5x_k* z-;yTEp&vf(RvQ*o5rn8QJK|ZLTPDI98C-opC`F3`3}3G=-R8`!^tyg@hxkrcjUV!& zkJC?4{NCORWiNO$EAgtp>Bf)q3BYG_NOU7%sC34@vfnq(*YXvdyf*aj5O_gjcSSt9 z3c2I5@tDp|@SOD8Q56C(_|u!v;f9cN<|_1vfe6jS79h1iy1p?|$Mt@pfluaQKjd_M zoyycmi&#|b8{B-UAfCweS530z>)&?BCp7w*juPXGWEm?FQbjG>+| zgsP^fAF|;Fr5t0<@5r8fy1fI}57Tl*nd%bTEL6_DCiPB|Y=l8Go5^+}K6mFcZSGIc ztJDoN1CCH!3iX~r5XdnSA=>)~9r3pR!Ar%Dm@m=ht8zmWDbqXbY7{lJHVO(>Z--Zc zl7e0i!C@NGXH8#&lZxAPhVTXr_;yaZE#EG9@%nqBd<&yn|I^akZRQ z1Ly8dW)#|C*mq>?7Im4NIWq`TNQJq-C#r6H_x^;ZR-@$`$`$Hcoo4R1l`Oe~L&eJP z6464E(zgHk`Y=Yp<>1SppY>wZvddAo3l%f2#&U%K0YCX6!^)2teY3a*y9DC~p}v-k z1^l=C!K>Y7^ml;-vGv@~i!}1G)mqH7w&)fiado#?{q(M_kt!#ocEM`m2=7>_WRiDp zcqPUdzxh4(v}sRqqgVaOMNTI2 zIm;-fD$$C{1ZmPG+rJ278A!Xx=%R(TjBufqBAq*xS3%B<+0u<`K<(QBpGy zdYgv&PkRPl=M`Y{UH6Z(%WYmHvTyFET7%soT%O_wgJ*M(puw zH%bA$_A%vG3>Xgt>8cl%D#=kS1j3b!um#gwEPn$>di%^7690F zYnx)?N_U4ruNacd#L242Vfpg}I|KOCxf`m%7tCsWAOp}wVDE`af5ji;CqOWb3cnR& zBYN|1?&OUMDizHgln_hw%q}6Bz^ z^F$MiU*#e95nu%_y5}x7SI+j6TTvG3xofCmmu{{%tO|${Y>hQsfQFE78HqDAo1)EM zx>;uD0fQ*HjGUA|?`M)JV7Q~Py*a;v14=Yvwi(K^^L|sA9-*?#2y*b_jVg=$(3Uqz zab2;Y@juBGef!g~^}`PKIbaQgVmTMOsYBK4q{QIBTB2Qk8vdaD=(;5}jJg#m7dgX4 z5#>j+&y2wG?2NC&-;@|~cQB(rcUIi_Z2tZlxxWh<;5T#KYJqc}Zj9r!>I1#^qRBD5 z1$P9X%<^q?#8t_=0?3tUl^~7uHL!Y*T>O3vqgTfZ;fS=qC+3DP=b_51o&mk{pUI7R z3wWww-6tMQEb)F^PK^u%mxb1_&nWAdBVlE6IG(x6zh$f@MEtrErR?rji{(G({ijr@ zC9r#reA3Te>!&Cp9`95M5ArRtBZ{;O*cy|T~|lrN0mpnO|)@)8RmB19ktvr`$c|1eeML8~QP*<(?=< zCiIiAI*~9d5q0q)bA%ELS1>FiPe)9x{lXC$l2t3TZ`BU?qnx52jltJ6Eb@(cpv|YK zv>%fN=S4=bRe^X?Pw=9#m72;pi-NpB~ay@gY%ipsuU8^A4w^KHjt82Td8l* zs>JnC#Bi=}ZAxBZWblmc+n(qktk#d{KnCo(v0tbdNra)6ctc#QiM^6(l`|WId*K5& zUo19$#*B2QJRWRu{Pm}^nDL$?93`xxX*HsmBXo&mRT!v_t|~OJNUZ0&fd-#LAJvp= z6taV*18QUuM4Ej<(3Ooh zPPS+Co3$odxpCbM8RRPxQRga?zXjIAD+@?zi`4Tpewa$Pb|k)g)1nBTG0_ zF80E0?qFazmaN>;@}eW5Konvhi$^`kI~(l(+mdpYDnAVSd^pLMEjeZJk)Wa#-k3ly zYxj<()AJX$=Qv}tBZCEh_hAO>iQ5Eg!Z55u zaN3L*Wf&n5m?bFsl8q!v$A?AcTR1Q5fwK)hE6LfU@K?#QlsCakk23W^k+~!6d@}Fo zHtD%*aLfnsB%6uxlI}R;FeS{ZqF~7?sjp1dBc`X4zc&I)R&}hTI;Gv#rTqLx*DCG} zLx#4egklW#Od>V9KC|A%)Xaq1yTntYnXMQY^d>Xe1G z`lzq;k7pV%6#n;D?GG%O?T)QU87s~^Ks8e8_*9(oJYG6sZlZ#iTg`SAK~cF_yrN!l z-8mDL#3>99b;Nj&HgQejZSdO}Wy-+qKbb0os&0`!k+rWCtL)-3Fsh1d2K)V$(tPPT zLK41QVaKMOObI!nd+$xfqtAZmwl+b2wG%L8UBzzm)Nn`v)eA)v>2j9H5z(aa4{K=A zm597kvR8lWUMn%gXO>GtvEpW$E3u)n?zwU|lxw^m#^|ob|DRbh?fD;dM74_{^IK#o zm=CIO@gFHuX)3pq_7*G%7j_Gp0=E(wz<5}SNKAlcX6@&k?~ra<<*!g1 zqLLMu#ZhHhZ%K2qr&xBjUiZDKWP9plW^k^zP+4dkF%8?J>eS$xldu*85%7I6fP?^u zpZJSSK-@3V;X7@%iW8pt=nikG1+lEX^RTy2vYm3Sfcb1RX;;Pa%IJ#jXSy-_CJC!= zs!Ye8YPSB-Mm9A^EzrrfJR*srIZpQ$CudPZ8+S~DmQs$emkQ&YbkILgppNx_?w9CW zBzu=2Kh*NEa`M4BGY;x+#pwno5$Deqj!_o5ByRmOgQce-qnPqaBK;CCa(>bCHdy`C zbc`T(>SMclo%7d7A4pnUwW2SG0bCA7Jm5e90x}To6VH_l-o>yV>heF_usET`e}5Y= ztE*yUcIT6RI;Ls&K?ExZ)UW*9`g0^vK$@_-?ui-k!buPx!b*dLQ}#~LoOkjL3sm+QKVk^s>Z5!4Y8Pu|Z7O>Xi(a8;=VXK<53Df4p`E0 z=_h3)waW|@%Xzldw_AlU;rS$VTRS2qNYI-Vb+zq9 zsB7K!eE&E?HrtM&!r0?2#aX(o59?m>9MxONzy4MO#>%T}zgPUZ@=C#jq>9t85#c$E zt9${MW}hjp?u*s-GRpK;Wdtq)nojop&I>}PWNxFeo~KEX4ZU|A$;b==?h?}R{kOH` z=q7xgW+VCP}bMY0=+7nbzuc8bNM1>v08C-K?(XjHPJrO<4#C~sf(3VX3oIH479hA=a7}pwI)J)Cvoa*iqr=cc~hD?kM007Vw6=byj+0g$KjQDRJ5i_6qXAmuvus>&iQ0kQCCx#$wgjQ{`&fTE0~j^Fy_m$j6_ z)1aLv|4v^)#|9SsE}J%jj=XH1bSg@{{aC3(09+;sypu|!$EoBFs3%Xk2 z+WLy02)zH4^=B%bzYBETsAQ+i=EP7d!<8AY!Z5DZW`^Kg>=lmR+yvwkU=X!maSxc| zI`IqsxoJt!A9T-;4BGFpejPhU9x&w&cGWdkPGUj5HK2YUuk~+@`8!}8!jKZ7WR0kY z-Km!{pQ@~p&hM{ycUke|qR205Up)>Sc9G4=K<1r#d)Ge=qQCc_vx0Vte;t0^zZASy_js3l^+CcIAqX3WVY5{)n>sJdEN?zE0!wItZ9S>JS_n{PPlB!uNd1nG*=~f(?!9B! z6lh!G<|nPBFHJX|{ap^NBHQYEID3=Om5Hz0y!%sah#m!|eBNo25gOdB!JX|idnKen zG4YblZl$uim!>tsxk5)4<)BZ2$Wj`G(K1ngSCUB`zmg#u+?T)>L$k#>Qd_Q@$aohd zc9m?{s6?k}7D9hBHiwYiMf=hEi)q>GX0P)Q(@jKM7_Y=p(aLxcMrck5zZ>oyY44BHU^L^3Ow4zd_*VQ;>Jka^)Xl`(QperYu8I64i+ z^n-=dY~$k6Q_+>Eva5djL&iF9%cQRmM9xT1b7E;6pW}SP8h$}_ioI#SoRQ;KgON|P zNxVsydmRxF$%48*2->q8-`kmoJU-<@>J%l9K$WPdebGgkAZGii(BI+4O07)I)j)*Z zI*EGbZ|*Y_R`Y4wkqx|x{MTk>o}gQ(vnoD$s_lvazu+HPMivnb0)1l5mD1{YPU^(j14ndWJu4ZAN~>132% z5H3U`yHESFB!T2uYAwrQE7|6P5e*lzay}Rzd?2MMx^)w&ixy~gtaZ1cg~N;4WKDQq zw2G zW_kouMf~`NVbcIiHf`=V&FqB~Dr7uQUnWguEKP6hDdj`8dA1#TlPz10&<>p&jyQ&| z&XK3oe<7L1<599yZLt`liHVdlyZX(oG37~R(xuu?p$&`z81^9ekUR>S<#2Nn#u$}S zS|k6s;xPw%tQvZTI5c8r8aCbT&CoOk3LQ8@q4Zt%Q0-K(vf%}{wM_MNlua9$bA87dqq%xw;h5MGJGo~2+bnN#e`289) z>8)U_+=@M;fCGZFDECR0D!aPYyWDg%nony~pqD`_(trl0t$YE^k0 zxGS8BY8Tw~aqbVEsI?|q`cyg~ZP|AnlVenx2C}gzW*;Q$gh5zkCMYr(LyBTu3@4Qw z6D7?Z`GVeNVXG4Kcq%XU^)r|yQP{*a*vO)iFwRC`dpYWExm;A}BO)zrs}2m%lId5` zawN3gKd#lUVk+@d2=^j2Gd-L;)hqW(~PrM>ECG_#Tg;e=KY!X{4Vw5_c`vO)Jx~u^uwj-gM))W5n zM@)zjU45sSH=L={kQxFB&JA2aghA;1_jt-Wibuw>vv*M@h%Ius50Zxpr_J9oq9sm; zkkm1W2_(LO?P>YS!JjRrmHXGDI`Ey2+=32h!vn*l5Uf&HPs9`lMs%`PXCue{qJGYD zo5e~IG5$42#RPK#+~9|!Kwkx@&hG8|ezgnJgW=?^uw^@wS1>eeVt*h~zhSX=evl=B zxq%xuq4}Zc&LWJ<((mq1AhD<{G~eS&XeH&Et0{bcPN)F4bD%mT@pSPJd(6Zc9K+rH*(=xP`jed-xY38BUQ2Id3N8KYQ{ zM}ToNZ)>wloEwYj&CBb@K}k9QMGJ5_R7$J*SO0dz!f>3B{Rtz#AYe-?mE$6@&) zmA&h%Y8H>$dPj%{4(>>HhOZg={QUp55=Z0($xrA*>I@IhLkI|_=vH2F0^XPud z_NXesW~ApL$Yz4`BK`(LC7+C3WFN#J4}5^ri1BNJp1f@}lt4KFFwg94KUqAAKKQz5^h+N>T>Zb>I|hURQd^{E}x8zY0^kDYY5to z%-)$@oL^@DXnw~}(VRMt`REX5S(7$E5cUfycm@apl>U4p2wRjOKLJ+4O*1ubihOq3 z?%V92`+;sL{zH6Y;k)Xd6NX++-kcYSb2`todYB1^pchHVA;Cr%LqC#5%&-d4W!C0< z-}*!mUC#Z-!7keE)mpJOF^NKK*_&nBNwr$oY~{YBOS4i-={s%Cp@hB*UB~u?^-3`& zbEiES9p$PU4pK>Fo}31fIL8^zo28zUPRH_)3iD(Knr*;Q!D!XY+apQy^kUHN*L(Fs zPL5d;3KqW4-br+j8Q;F~i}vD%Gt!vf6qB*CIVKy_H9ka*iBI2TZm#Dtjr)zjx4%6B z>S%zJUwbP%%l-cHcMU>KKZxV(U8Wu1J${B@qA!6!m|)NfKW`2@ z(^Z$na$FCueOfkasUCqdLEH$0gB{y|;#Xcj>V<(~If$K2(yP_f%#aWJV``A%scNo_AR^1^_a$(|MMsNPyP*Cxpd#w>A`}dy{{A97hL5Lx8z*E-*>C2 z4IUU2wcE#NAO4Lb4;kpa3mN$E<^IzGz#A)O_x_rhEE%nmXBC z;V^-Pmc5kb!U~@i1=Ic#H}7W}{KuJ`&rXC-{F*{JFqJpNxHlf5jm=n>;6A%XOTaPbwXBbp&3BbF3*tgEfa5^r=G-vZML(}&T%lvlZYN`Bcy9?!Ms~onz z&Idtn&Wx`gH)ndHdm^Iu45?3bJ<+&lTDMthYC6(?caU>!Ma7YPx13hnF0*AZA+5fk zVil{zCaE563sAfnuca}*m;7;$HP?g)hAy3l_f<$>;6BebFI?}^f0mEG#x%~4LA55gJZ;6 z3c>+bCHu1b{*;|NV%@gBmnrD?k)Pdbo^uatz3zW3io_}g zf$?5!m6$X3iQG{6do?Q1O=U#=>^ubSJiGc36Yt&o*~J8r#cZ3N)c)6_cySWP?df;_ z5)sOGE}#A^LO>m=W@ZR2tpaUv9{kk`sbUoW02|RNZr_rLUGcy=+sLgKjhWTpLviEi zi`K~R`2v%WW!#|n4=q0~z{G>rHSmvL30lr5@enFP6zaOibRY$;oR^^CZi~3|_uyb< z-TsW>{P)THY|6x#A|C*l&<&{G)Ck+j0ByQpZNGBGD|hs>4jr9&VoqKn)%2))s8?S#u@GFpC_RJ*a*^F=IJ3`KTMoq20&YNV$jOL z<8+p2pem@ZaD_OzVm#S*jNrQ6!ma8?_)~(6>J6U1ahc%agZIP)_bsiY3-y?K%O9k} zEA}DR{Y3gKV8eS*S}~f8CMgQVQ`YL={*1lz>W#L9vX{KA4rj82`vXtgy}=N)*`@;c zTiw(q$}Q&hCC0m1V#NU!mghhQVV1SXXJ#w{KHTe~mHr-D2TT!vQ8yUf?zn9C4bDk{ zH|{cZ1`tmU*CL0;2z32@XxEBVM!$D<`I5jJSj9?$DDD&(dNe*s%tz)opBuThE#?dq zog)U=kGxa@A!xO_w#-=pSxQFbCls4Nf4@k3*VL$3lp`|odyulQn=*KyweXi(t%GMM z>W$1fB04K3uEb3hw2#45gndn_Z8IHaKOCHgDG=uI24KhMpc{(Q7H|(+%C@M0XErf7 z+w8>eCUg)p8y==hDITMq-;Nck!Bg0 z0~2+$!m<{g-EK;5&a*bs7cX(}q9>TT|9<&bF&ugTY**fL^1Q|DJ>h;MRW`9b@;}I= z6jVN1*7SgsQT4hPI$X{Uw<}Vw4Wzw%Uwx@ft6#%+TK7Bp6PpV+Z&#;>ra%rw=xzq> z#0~|(_Qw6UcM_Ugqqv-#A)k`Jn^I8?1s&x&A!O^!-sK%XUj3*Hty5P)Ig!rz@Bi5D zr-My}FxlDkg;mpZV0)XY~Bi-QWMwct5VoCq;U|l zYRn?UCu7enEQ)@|G4S!eOT~*7?bm_+eZei`+SLH>rQu6$q^l?y8=Lh@cajqDy}K@l zYmTJvf?J58|GR>)La|$_Ks8AO&FefUEOK~f zd*_d>%TiySN~R-n6I_cc@xZ&4O&a;kmJ}{emM-BIh^TVv>I|&iKEG>1Mt)zKk-m!O zC&0&=&^V6|?C;KlFYwWRCI-@@v4T!dEX{T1h*T zZ5K^SW%hC=z^Tggmnp|R-$?i6r(IzeZ$T>&!#xc_IY|aNDVHYO)FqytNAA8?SRBek zp$IVeqwr_cOF{d@!A{;AbmP9PI&1Eoos>TYumgCMDx#Bi_=OfODyj0~sIrDN?oI=0 z@dUE9tP-h~ zqA3|!*M@t=vMzAaC}dP_NU4I-=kE863I5c1&SvEIsf^GocOP!fnsq7*IM5t7iXIhX zGdcw3l{VU!>nqRZ0AHMJKed=h&BJd|=UwevByk~{WU(|E4*18=TO$^|1fMoAhr0s% zs3irnV>_vuP-}Pub`aNTWOQ1S?hpf0MxjPXe=gT0_nqLwuZ;Jt$K5!QfJ+?WKkXLU zd#=-Em64&(}pa*`H;GHq#`EMcn>J4BpqEdKrZW05|RCyw>G55uzg%iOs}d<$Bm~7 zVO<^fi%DZ|?Neh`0lFM#K~4&&%#oPpz^`SQ4~Q8lTk{-aL&wx?J|mH>XxC~YKl!A^aiWI$7js^Vo_TCO9ISu zna%NAZ~y-C09dsv4Y!B`@j^ z4e9WoWs=YB+N``p^}0TlGdBH!etuaemDEOoFO;V!RKa0aQ!I!2J3a+0!sck{eTDL0%xMy3HrjX2<8ED z_wK$BEviCw!bW)s*d20}$+bPO4orum5G>FXGhmRm^rkOA)A$z#VT{Xl&t2_9BGlsM zdeSE(AFL}7ok}HEE8{o$TS@>GF}tj40+B4Y3zQ}j3@J&VM8`D)^^uI;iV<$O44z^i z5ktgEFPUvA<3|Vo^P3@TsYoqSBh4+Dv~g7w18sw+xV+~<<(*NdK0=sl9eH3nb{ZdD zou^r+SKR>3IR>##Lmh8ux+NGvGLuk$zg*r=o!>Ln&qX#&|MMnG*a#f7ZVPH5Y=%5n z(@qorPFC047`;^L6gXoNzDlS0J!ww|X*oxdm9JwBi zYes}ei)I;?T!&tB(%ECD8aCd*>qc4`p~V=89l3x3EKqaC-NZMu%M`7&+gztlU zb-7>rJ{MR8wDUmkm!SN}>P4Wyjd@=@J^V<95svYw0u7;5EEH#hYaX?2qcS#IP0<~I z*)_yi=QnP7$SPphbjAr$6 zX4uS9jw5V{nOz%$^x6!DCM5A4Z1jKJ!^uJp={7mh zaPdiUEFD62`spgyCbCll;&!ly|MkcQLjT9f5eyN2&$;ypbLFW80r@D(Vf32|tYJ3o zoVJ{yD<4aGeqxGgDd^&O#NbZ#GLk$Ypl$iiP&gn*NcIc37X?Lg%cYU{dZ$MSIal8@ zygMb+x8@L0>jE<-$cSpB%OkuYcFt&7KDkb0p79_C8yPq8JH6 zK!I7wNMX<|WoNgtHD7E3Yp0QPHX=1whPFof)^Fp%UH{=NshAuTKNQJ8DJ?3+hM{6Y zB}EI;?8I*=m`+qL)W+V)_og^|2_)R9{3@UEqNd|T6UKRDGHsl2G^(*A z29V|!q{Vkq-SU$rk(7>pxq-^8fu@}mB|$t#2Wk6W%zjzf}^)rTh;l|}4sjXf!! z)G5xkRB!G%n1+J9y5(uecmL95ZCal^3f9DQmzq60jk#V6zaAjWZHU}zdc2%y4DIxBzzd4_uX(Jwu?0+aC|1Y)qmj^Ji2@) zusIhJsiQK+H68>R5|@nR&g7I?Or#>V9A?WngVTFKcza^&52Jr6CEc_DU$6eC!$a$3dL#_LZEm2?km+O`3w?)URo^y13%;5+ZvoDrJ zEngEB$vM=5r7A^H4&v?KbLpU)mlrOlW5imHF}e<0cN+?jC)Et2?^2B z2;&C^x@xs?uRLxD!qddwVmbxNcN5doAuVlLPhUV+=lRf7h2xLonxFGW6eIlkue?8- zd@#xJm;@LsxiJ|Pcy+{NnWU%W4;l7>_)2qs6g<2e$M5_>P*l)o3if$#X41 z-#`^HarZ|V8oWRhfX69`#krBhnZy?>KQXwmkiWyw-@8Zn4lH*rw~gyHKMcenIl0k4 z1_>pLeIlMP^}9mQV7v#Nt{lwM82VxmgM%V8r8z*^LXhg#AMW-#ruj%m^6;%kat zOEyxCG6liYKi}MO6{whTM(H&{DvBz|M);IFzR_{~(D}jjGeeprg^PE^Un=bI7x;r#bGbrjfR+QxaxsaZN`i&9R71K`B2zOS`>(n>k(*tJb z9b*^YhRMTDkS0{xFh>~dC4$^)&pc5=ZEQG1-l6z>jV~>;*T-7Z3jfCAj~A8+(l*bm z!Wk(J|3YdoWA46e+`{qISn$#8>R#oKZA6|;QrS`y$Co_#Nj9VoB;}B=B&dUOHR!}P zF8pazq6~5xS#GZ6OmHwhCOfXh-DS}70#vt10b`f@-`$+PJ+MwrqNKaLw}|0nP5ako z&^3^dCyh_VL`d?E25fGEoMk)7wgCVPl>fK@XTd%CxGd9hO*23L%n3ywSA_6soAGH{ zbp{pi+D=EyZXjwD()rv}KV5v=37_Z2oRJ&b5LB(m3sL?V%3o)*4&*B)gvw*=Et6d& zn`tGco{^U#o(>U0UG;auNBpE69kzaaRM4~_h*go=Ny!vHTm3wY*hIi>wc zS2EPuBk~3E7d;vd!F8|KKh9O`M=t$t7?N|g*pdB13wESfxh;_B1ydr21Ba=COw>_H zv%izBuF^9zoTP8d7H;MaO+j+=#ptYKO#gf^&0f-ra7HHQq!oz;ulc=!DIV`@6iL`r zBs~xEE|Ej%66;XXuW&1>$uCrC(HiC5-$&@Ca?jo+H!Wlb8HaMA-VCMM3CxFU40lGk zqtc5i@K$Yay~}uqbYyj8Y#@-Y{V3>$GEP1+jvF4u(3qj|m(u&_w*IJJkl&8)$Emx& z{^XEXt0837DS93iFtZzTig|@*ZVMuzCbW^R?@q$><+vmJv`MEaEW-4aC6;m6TBk65 zl7gf5J#_Tf1$-J>Wm`i*Ao;lg>Up^>%VE$$o5j9=GX zlnc#VBzW9)B)Lnw7{?dxxt{o6lYZe5pKe7D27-ORqBWrfx}*IezH(XOeWCy8eYt(W z9c^>4V@qu+$FbfJ(o4D`$vi)OThEe+vYNmAb=k$XnH%nyujP(xd5a#IM8_o~S9REK zLQBX>>u9z7@G#rbed!L#es{t1-!`cdd&IH&EsE=D77Zu^!8#Jxk`CHUx_^5KU-xe*`2^uYF5;vF&g z6D!yPY51$bBbfHea*S{I8grD4iZs1kP)Bg>APH*U{Jp2SdM8Md3jfK#H<27 zDk5c^;>XbSH-OR-ePI%Pv+g0dWkUe{5pq%T!)NiSO?Euil#pAE=@6WWui_D9Pcl3B z6Sh`*oQjbi@Xb^AaVRR(&cBvIBhydZ?BllskLws5!gXwBL<4{vVIL2Na9*UZ)CbgX z*-AS~nuQ}z23rj~Z#^K|UlMg}Z{dRP0QKM8OC*@l*oGJoN|%inap@3XZsgQtyK7Z< zmZcdp8KUOWI&ThdXKYLGxoFl|jiX)EJ%)Se8tyaC)n z{Z(7nEA*I|C9$&kbJ*iYonUw@A8xnh^d?W*Wd=%B&9-6>DUH6-v*G9&5%Hkl~l0TCNw(Lxu zoFztaP^@5J?hW3&-q1#B!8AU9qp>oried#3U}eh0MD`oWDaBfgnmFYyWptERr`XgO zUj}9clMmw_SAqQDaeOq!BE!+sM8?vi$05MBYkA z3zdnpP2wnKK7wD#4|K`P-r#Y?ts)9m_?dxMPr{s5MU72}!AKJa5|yN@>B;1r))G@Y z^kqp}&jLHrjEdlN3K1cLdbq&EbUaE1x+kDvqaWd}CgS_WfJeN^KXz+h7_AZ)!t5F z6N)FS@Jw8tV}DB0tqo7MjWaih;dX05@hUwR;XN0(I}sS=WDOE5zGGA>$K;YRpz}-0 z#wMWxBI8kj6CTl7fy1ES_IoZl2cUL;0aZBtV;zg#(2ro$*DA2s_(bUaGtF7h!*4N< zAHx%P5A-`049ehVkeE6ZyH)_g3q8}DXC{lJ%4EGf4Psz2Slf!L5;-Iem6eB8X-$@M zxQC6ub8!3tf>Ct({m^OTP68K+<% z$>&++KGSYD_W6|qXE+7}ASwFeZpo$CZysx>Beq&*icyzW>Juwdg~q_J*6t~G{}2u} zhk~t!7FOg}#F!hnlFH270P~v+ID4S8(ND=?d*8T`jbS<{&|KBs(5@M=Q7#+UF~uX0e#@T z9|36+k-F#bKA~Y2&BA^{dMQI{9Z_%{m0q@&W@;ddU#?QN52cc5-7)KCOW=9lvy;p} zIv#4jFN&U;;GGFdA+Ur;F3}S0$398;Alf8crF%Dw0nDO za~XX80`qeFSEai=Oj$f0WYyO6Ry~yJM8`KWrOFvTko#x|QPkeJt7Q|&d;tnh6lu0fltQ^y)Chs`S7$e%~w zZ>BcTMYgKOpbvRLA8tM14uk}H!9-zPFeW*rD7;oaxNWR*`FP}E+_FksbMOT#^w%*G!WU{P}aZ*Z3mv#RLx%7^L3|lou;gXR$jA27(enn%SwjbtM z{ztG+c2;Sylsin*ieWJ}h`g^urSY~8B1y}etX?4Tsp^V6QOpnY0 zAcSp{f~sGGfjxBrt6lmz-M;#}SlOMWj>vcpj+Ut8nDz@#SspH~?Bufllo~ON{3_eH z3u_Dr+f3_8x9(9z1RHXCC;K34DQeLYO)VO{VPIM0O9e?3s1Um9UU-uV>0D^0M;C0% zq#xaj?9g7W0r0WE7JJ0fP7SlFyH2*|e?0lPpHZ|jaD4oUeY8#R`e#k@Tzv-=Z|Dy> zQ@pFf4{7PT1r=4P3k&2$sd0!yo|IjQcQ_iS7Gb}(w}wIhleuQe@F)@G9F~RBjiBVQ z*L$KhfvQrgwDcIuxhrzvMjXFi>1K}F9*>FUCXA6ftNm&hkG;uXL?_n6XQ3Qt4|dN@ zdoUz$unO70*U9EN_Fw5ZmEpgN`EV5(y9bNS;qJ6V#Aq*^R_o6bHDmH{*GHKV%1Dtvrp~+ZS2oukw-xfPO#;-`a@JDWto$3+KzE99HL{voms5WuqNedI%B~FjPty!g5Pw zn({EkTu=V%GuB#Xu-5rfjN?c8^(f+#&}W!)qvEoB_*lJZ#9J=nK+uq6ZdJ>HUZJdWZ+yLg-aVQ1@ZM4?1qyNKUh95d{z{nZV#q5AGFO$zh<Ovn?za_KM|sakl$kddxo_EG>4|6|Pq N6lK+98l}v_{|ENe%#{ED literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-39.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-39.png new file mode 100644 index 0000000000000000000000000000000000000000..932ff3cf1a4cd9834723b9a050be846e78b8c784 GIT binary patch literal 12837 zcmb80RaYEL)2;^}d~kv@xLa^{cXtmKcyQOj-95qG-66QU6C45|NEqDV%li-ZUftET zRvq=~?t`kku8vkykwr%#LID5(=<;$>8vlIo{|t!uZygdbpZezzEfi&?03ZJw1-<2| z|02lFa{6un04mP^3HaPdptcpSyM9&u8v8sNulQ{rDgFb1yrH)S`mVh?yUNuv5w0GCu5Vo9P{M; zur&lP12S+*k`3Jm-L?1yC05C}(i*kkX1Ud*8xR(6nP8r|Y9Qb5FI$YsUlqP5e_|Mc z#jxmk$ZK8;iubE+-49ba`Tv{m;>nMZx9sNkLi?G17FV$!H}HTt(xqKV=flZ;uDch= zRKJIr07?q)mzZDQ`}Q!oMkW~sMj~Ujb);BvyW&ppQ8qNt z!ol$I*Ra@Xo&6JHxPrgtQ#{ae`I;7!((r0CnMK!8UUkN<2U`2J2Zexvg`o`Zhbl*w zwRa{ryO*mUOvB9xIo?j$AJV1t-@km5v0BQ~!R4S3_rzP2$�#r4hFSS3_mQP`o8+ z(4(-8l_%&Y7<|ka`+Bslep`wn!2;1kMb69uGgysLxyk}{Lc@ahdaGgU6rH{*vch0C z_ph<}id2|B)C5C~02IM{lO#7k4nAWRWhKYxGgugXD@r94wM+g3PYmvHG+)XZw~tGh zH^D+pY>g;DJ#baPR_<^ttI6h=)VWYxZ77p*FFT~vDYv8&@L&Df;>+!qG4i+PED4RP$ zN%3M`Lwh7G?ZCpumyp0Kk5YlGUsBi>O5|2;59H$h>6RluOhNl&nTFFE`@kK7#1DPpE$}1{fJ_IK zMMa@n;3-h0=kg4}mmopV=DaUd{=%M}HVJn^y^t~PhFeaebz z$ptIR=-y^^;c>Rhfpr+(P{8hD%zN%JpIOqTL50fD*pe#-6T=WLQoZRtLCl~~3g$r; zP-Pg%WH^TMqCrZ;__zOmiILK=p1)j7oOOU@oP%;9x3D&N(N6I6SHmu1cp=LMU!hxx z=)V~i`6EIz%6X@gzGq?`=Tof^K>yBFNReB+b(MhynY`a3C_s5-dLlT0FedtrqLVmH z9j!s*Poe7Ps#NZa;*+Q)>XDV5i5pvo?%h_Rn#1Wb84Qdq3`N!gSKxHPcp#HpXH@1V zb-85Lp(s2cDdeQ!B*hL&<~+YRKZW~p#BasSP%Xwd3g4)j?kTs;nF?xTMuSaEMcGX8 zuCDBXuS8BR!x2(}-8mf1QxK0Lb-c7AhzKDT=dmt@sJ8{P69D&b;CIDk$aLkaD$QIK z`ZM-I-!<39pR?CryjW46-?IGViCIhrn`7D#1MK5Sz5w5}tDw0hS6

`RrdL6uo2U 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 KQgsq$kpBY)=?<^} literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-4.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-4.png new file mode 100644 index 0000000000000000000000000000000000000000..e41c63b203a74ef557de042c19066441944f070d GIT binary patch literal 1225 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$lc1<7ALo-BcNrL1!aQ9ZLn>~)y>&iYCROJ6$M0v} zoq3aHKHGQq>|C>ze^b}$ibh9IjO${zy|P$nuZJMNEmu>$gH6S^2P^08;S_CYdf_U# zbZgg9`3SElU0=`1Gjhtze^;lKrOWYubf4-}EO_(l=O#;@&o%s?ZRS6(teC+lNDi3z zzs0b4oni6275kU}-7kHEyO^{1_tYtd#hl3-&e&`-jHu84{8_Sp>m{D;#g~tr=`WFw zRJMPRkXW}r(suf>{^KWaL<;TmPd0Kqc-z%>-opI637=Q_wB|~Aitqo;l6WDZ{B8B= zUkX7CZAFsy&o@|X6c(-)`D1psq))-h>ze)rv&SwnDw~dPIOD1F+~{#lv#johhbc3Z z7ChFU#5G&QXkqGJ;hrRURrji2*H2~cIi!bKQ*{IX2Pp6R2%EHT_eO?J~y*K2H|4vZ33uSMDQH~Z|5PQBLrbcyc`&4l#$XD1$4 zKdemPS#j{3{I`uCpV~z^&Q+-GOtDva8oA_H^^!W-o-Fa+GKOVcwQQ?}fBZbW#x=6( zU-y({{=qiPb9OCH6s!>As$Nj=QO7*|+oPTHFLtlWDJc(rTjE~ID)Bb>K;KU>zkh6X z62=|N3-73F+I{Xnxc|EHfyfi7e!*|wExE6KVa3^?*##v$GG3qgPG4oXyx&{N?%2ZS z%!*fxrm8neg@W#JCIu^*7xo6{Ul(mi+_EFXc;<~(Ng3APiZfXETPyJZbb$R&mx%=i8e_8WKwqReVS z2`~TS6;DM^-Bepv)IROMWlW{R+3}dqiK)WLqt>zQk>3x7+{Z3#~g@&QIn3vDcIBo{nwt zq!YHs8r$QWgdKPz*y{zSNv*!|QFPC<_AhHyAKl?fo-4Zg&$|=r7)}QAGqeY3S~dSw zxg)f8g?C16ckJIj)%wm4zeJAld=RqrFgda8`pd0OznbSCh+TZsqu{{j9z)yHn|hcG zdb&!RPj0!vap}oqGu`ceb{88D{+^L_;8_Icq|~C1qOX>!TrTS?+vcZrtAF;}jdDkP z_GUKt<}x1M!78Csk(~2--Q0yiZ;fX3a2~pG>-)U?Gpir3nW?lisnyHcxmL;l&YBMy zYD+|?yo@rgm>GTTNp$&yMBaljkNRKlJHLKj`LPQd`X#>f`P{Yfhu!KIb&vy2 c?0;(hWy8GvvlB!FfQ1f&r>mdKI;Vst05BXX*#H0l literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-40.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-40.png new file mode 100644 index 0000000000000000000000000000000000000000..b25365ea87f52fd30b3fae5168e7ea1c577a0364 GIT binary patch literal 13464 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-43.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-43.png new file mode 100644 index 0000000000000000000000000000000000000000..52c9327f28cba37496076de68715f860f928cbe7 GIT binary patch literal 15790 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-44.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-44.png new file mode 100644 index 0000000000000000000000000000000000000000..4251d580527d49c320dc7cf18df56bc5f51aefba GIT binary patch literal 16608 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-45.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-45.png new file mode 100644 index 0000000000000000000000000000000000000000..cc4093b79ce9d95e2054d40ab8d0b612a55b5553 GIT binary patch literal 17417 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≠1V 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-47.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-47.png new file mode 100644 index 0000000000000000000000000000000000000000..20747527a43b9369125e7d8543099cd1c295db59 GIT binary patch literal 19130 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 JPDHLkV1jy1Q|bT! literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-48.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-48.png new file mode 100644 index 0000000000000000000000000000000000000000..2518748016ed70690858d1fcb19013777ad5dd36 GIT binary patch literal 20011 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 Iy-r;GA5wr(sQ>@~ literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-50.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-50.png new file mode 100644 index 0000000000000000000000000000000000000000..c626514ee4749a8dc52383b4f8a08016b6ca0e7d GIT binary patch literal 21664 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-51.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-51.png new file mode 100644 index 0000000000000000000000000000000000000000..4bf3a5fe46e2994a949a7214626a77aa1deb0a62 GIT binary patch literal 22594 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-52.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-52.png new file mode 100644 index 0000000000000000000000000000000000000000..6bb9c7ccff560ad1e5b11b9194183227bfa385d9 GIT binary patch literal 23543 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¬((D+8{;#Rxpu2sHnj?R*l255#f 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�m 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 Xufj-j5u^eV00000NkvXXu0mjfur=Dv literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-58.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-58.png new file mode 100644 index 0000000000000000000000000000000000000000..41ecd2efb05ec4f69611a16899b91b474075e5fb GIT binary patch literal 29323 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 Q|j;wLOR1t$YS{1vFZz4 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 JPDHLkV1jB12yp-a literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-6.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-6.png new file mode 100644 index 0000000000000000000000000000000000000000..d39c24622d67858a7586647b6d29041fba62daa5 GIT binary patch literal 1418 zcmb7E`#;kQ0R5Ua%(FaJE^2H=Nw{1l5hky=Sy5b%d3-)B=AE(f7ZEuuGcgCa)>;UarR`H;**C>rd#M&pGGwIX|8s4&{=ElOj|T3IKqji!&M{$@FiM zg-E>DCWs>mNU)m|8W4YD<@0)~q>+np_K61odDU-{0?KHIC8bP)i@T%DDCnR%Qe|^x z@dW^YVJ>L9D@oinu3Na@xOV@Bpra`ncR@MA(C3cVS&Y^%anAF#I2aDs{l*=JWM>^X z6b>6WnPcA$A4y5{|IGNe4yy`Xt~Nuk-#EHCa|=Qj3XR(_lZD9S(1@j>LHeGR{}V+6 zJj>|U#J(=&!Rza&nBmSJ-`J+e4`5#9m(#GuW5Eq=;+>%V#SHHh z66c=NV^O=sdPvYZ6kC`x6?Cl4f2$+TRIgFqT>E!>Ccp;qtjr&fjK zGN3GHkDajXFy_V_+%%0;8_~Roj}&-9kg$FfYfa};tW516MiqX7_$`~>(IG8Lm?a~5 z^e#_HJ>65`{H7o4`Z+9*UaeZuw>?zAK!=wVW$I}uM5yiRQiqs-1yyt>EluTVn&6Xobx4Rk|MYcFt=ZBb==g{)pbaol)kbQz24S$haRiO<( zGuXnkR5YKl6v`TZ?#Q}4vnoorBdYeNRZwn~&0fjzu&Ae>0`%r5sKs>e(%L|zYcy3x zc?L0zrJpne{S0i1t7a{Na2iqj*Na8d8dH7UOgU=X-8{FD4i&8t{7h^~0Q+O_u2CYPC{eY32mlGS(HZOA2@hhppJ%0^HO%rP@}-{{=^>?9CT!dURCtW&8*(>)G38DC^}FDZ|!1 z2Z-mZGb8+D6H=(Hh#FTcKVK2N>(P15xZz96HCUxGvSth z8`TBYTWxA;-%KC5r{~h;Q6?^9FE?}1>e$dnEL6#33b-XQxK&6d@^Q zK-e>uUP7f&YKKpcgl3>HD{p5tvLoDmMKs^e+tH?DJhO*DjURaW?27PXyJ#=yAO8N- zS5J!mYadimcQI*1=@tkUT}yjf5Wn%vA?5X5ff*)Lp?4#(x3zs1hxq=NK`(GVS?B`O U#|IJiBFSq4E{-1PMtf|=|G9~n_y7O^ literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-60.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-60.png new file mode 100644 index 0000000000000000000000000000000000000000..7de79a46c41dbbdcf43602645c8e203287466efe GIT binary patch literal 31004 zcmV(}K+wO5P)M{TTAOJ~3 zK~#9!?7Ug8Wmj_N_lq^`z0Y*Vyg89fW^s~4vP6|xLc3)MNOkL>VW3|Ouz>yoe(+_I_s3*=EDEK-lXrmf%=ah;dfb|D#DKu z-hWGY?YMmU{UhbIca*o$-{vuXBf|NWC^!5C!oPl1xHeJVTN(fkqj2Dq)2e*x&P4h7 zLb-K2KSG43S)=^g3;z~a`j6!dk2mq{@$ch^8E;49I$lG+ZEdOue{#!m^uX}i)^KMi zn|{5@+&N5~y_!SajlQmyh6B);h(*#ur(~B@Eq`Wp{(V~72rN3Un2i| zP3GTM%4?T1JiQYzUU@*e>gkr@{=nu+< zcGe$ZI7aw4Zwhx?;bagFqp*yE4Tkxlz+mVm7Jz0htOmns1>Pu47CNJJM!7UeXp_kw zWs=YA?j&ws&fL14zpE3-Q$_xdFzml+xPD?;x0chF46`U40&Nt|fW37l*JaZ`JI!2e zGJpSUdQ4b;3wiXL#(&lD{)J^f3vSO~2g7u?99N%&YqJCo;cu<7f1VktOm&#}`Mb(( zvOpfc&$9gIp55$ucs{3@K9A8?P_`KRA=`Y9wA*s|!2lmbd3z*ZPiy?wZV5avj}3q4 zumn(CTW;(LowtP6GGw7nf<(g%Sb9sJ3=QByVr?^$1M^vY>;&^k;?8(%|10UcIH~#0 z2k_%D@?T#X);pH|rseX5<1kkAL(MYOEbz3`hU>E$rxh<$6=~`D!AG83uNt^zxP?_P zs)#D0Jh^{o4|p5lCpd22bgWN2i_UTVImbHJ%$;YOE0&?ATUC5=Z^F4$yl6ewr;gWJ z%j~}6=vBiljFvqR?z}1N4nnuJxT?YE3yAzNm>-gd18nD*hXT>>KXvL9{shbZn}(Aw zEz1kb`P9MGvDa8?=h(F#Vud-cxMCcWsb^c)7~Q0x%UkoY7i6PL+X zBbTp4+95%k;OCkD>ZQah9|=DM7AS8$A!+(&1(W_Ug!tOQ7~aS7FJBVsmBkK@%g-84 z2FHOo1emNWlPNHRX`k5`!%8yN8O|q$YMpo%SR?!dZB6jI6<>9M*d zx&hS^@h487I^W;Havgya1B2ngp5eubq1#&aFW|U!_~2-x!CJ@ZN)T_Dt5EM62AyO3 z%TQmU$`b~&W#aFk@gB}D8QRPONCyfR$}6kiUKQ{dZtuKlxqf2#{29;X3rF6WkXHv7 zbB$~(s@#!>3%YuZ9|pP_rUbSjV^)F5d_b$r@jCPRLBt(r>fQWpB<)ui^FD?%9IqW& zzUV71U$)ehW$7)ps}SSZN<}p>SW&_d5Dgd&*hyf2C-C!=#B_-K?hyF*A1RRdQw$&e zbBDGyqBCl_PLdl~mS8_-wO(>$df;1Az&9WtELUF=4tFgNT0@*z4km`sT9&=Vojc5) z;d(N3*5RzB&xY0usS~7`;Po;#y-buBF|r3dfczmg|CDw5ijX$!F9NGY;_|1FYln$H ze^2s_Z-5>#=oz;9gq%MoS3MK;Bo!Lp(>E*nev6gB z6-iti3$sD9FRjpHi^Uq&Yn`G3v3JPEZnq#PcOrV58$;|2X0>$Ub(H@treD$ z&Th%>E37@iN+8RY+2O!WPF(y|ek8j5lg57w!;fI(O9plg+qI>dSaz2l=?y6vZd%9r zfuqx!tu#ok*ct;Svj~Y`A%q!OE@SQUNcsa*55as+GUo*O63w2&Ss}fbM;l%H8gk2T zBLx6lZ-wPZ_EIot^!RF*l%B)Li>REVDN@B2aXmRd17=2V&#=ws^y>%s^#-#W`Lc2t zlNhFv?JP0%%K52s_at%a)l$y9{jTyp%3r)`c%c>kXb=v!mJeIc;oPx{r;QbUWeLGy z?1Y2GE;>BNU|&G=5Y>*#dvksGk^4@a=4qx z>&U@o!@Zp?02gh-%@d!riMLP`RDM+edrXucvHZWh?|3;F^4jo)^-RUm?mD)u=einB zV}&(SYP&-}IY8r_N|fX}I$dG59heDX8X_~08R!JEAVv`sSN*Dq@3z8sB--w&DflD_ zXIa>p34N~^pONf9W@IzN`yG0wc=ra8=cw}?((t!b&A_BmY8gluiCzNrS_p%ov&xIp z#8DLf+9@xdBt8X>Z^9of%YoD@$2J*O6VD~_eCZmF8qb4Nv!4ttGo(Kv$jcc105#8J zSfTp&B-4@2ipsT|4vMt!8OnZ!y#-8H@UJW7&Ti&l3Cknp;l|)bls~AUe>d@`DDMF8 zV0dd3mw=JG2!Aq`q&zUZw-lZ~Fl@G#`p9xwEasvjsi$citKg9744?Oi-3=sNL-mND zf(*xq+{I4slatb=o;shC&8KL*2l54)9%6LO)CGo(!nCY)*D2Q~%F&ZP!EeU_u1yrq zg)Rvp3w<9UFNu7H!x2!#Y%w`w)08BaQND-CQ?mIApT3}PJ31`8RbZlqW@Cv2`ZjSK z44u#X;WqILXEDE{{O~+ulHnmh7PeO%&+S*_cFJDcFu0l>ahS>=VMfpehD!)9A-o1G z5jiL8XISPKyJA{FtA;SZrwFrM;j0w5=7iTTNB-x_@Y0yy`;RQsW92_wf$KMgzrym` z^ohXqF7We(@)x&-{~CA`c<;+nS-B&_(W&8VVxhI9>}h*Xs4M6^wrQBkf)t;j=M}2- zJ7Ax|N+6{#z!{Qu2T|B$*z!FtK zMp%L7P)QG9(14Xws`Lw5U16O;!kU3VVvV<7QRSLoHjpCS%+u%;37!)**hW~>gKJso z7CRmIDkQ?Lr3ZHJXS@@-R+%h>aA=W9#r{Rb{WK@mGp4?R!4Qqb`i7jQSRiReBtp() zwRovet>~m-s*0@)4lvO{Ff68)jRt;kYB?AW{Qh0b;R^}75dO$0pIgK1SeUhmcdb5_ zh_APqgO`L~0Pk)svrc(&ML>Ib#&3uXhl`kEON!tR`_m0HylveBfPxmqZBxwX0}eb2N+Es#toGoTK?JM(>i+mWc{l?=Z>NAzVke zgfk6IGMHYOZVhK`#dOEeSB|MO_#H>HZ#h&)8)q!rIZk%*`Yc9XWXKatNT{h0nG?(* zjm}Uqa18Da)_g|h0-t(vrC=>3a}&)|uxio@qE2ZLuhb6E8pct<)k zd~(B4?^v$Qh0mkm;h7-~hP}&zG{U*Dd~YzEXG@9(=_;aa2zH8b3&hQ_ae`~6D0>WC z$H`65A8={v*sWm`FO%d8EO&`|PS7<|);L)s)j554f%hx=i-B1k*-R7HH<|vSvOmpi z{;$lx{ceKW({q6366OtTti^>1Lv;n4FX3EJe?iXw1<2ok z|33(Q!dD)X4bgN+K0~yH+@j)8>k(72Bg!gf^3-t{1B0npg^YIttF7gs$xNn-EMcue z8ep+Euv~&qnf<$&*(7kUPV8$YU5i{;@~dU$oT-n0a*?(ehhh)bDNWkeL!#MBw)HsNw68UuA^ z*DH7WOyv_f3HP1$CrimLyz4WuIxps^Tdf%H1i2Q9FffPnC4ls z9$;)jIVboYpDdCxS(L1T7?2F24GD*lj2j}kiFg9*9GO&+v#j{3&<%!5mlEy$%;B?% z_kXp|@!Lay*ko3~^cc3gLhB|>^CdDbVnhhiQ@J&%A28+;PHqtG4wwNQz5F)55QQ~7bnC?2f0RNkF3{F^ScE7K4LC|Zpr#3M(&Uth_+Zg zXUO{)1HFRk7Bzuv64_)t0VR@CL~|q$nYw9M&S!A8 z%qJV7If3dF)d@y3nx;72N1E43`mdPVh9N+({|{CADOnAXEjevS)ELtfsTrz$>S|z< z0#OrnE`X?$jDKw2Riu*qOdX6`bnGq`F(8U_?)>RN_A;mm+aq;Ug-T|zwPvRksY zhA0jne~+MZYW|v?E!?eZc63h16+ACvn{}9Xjs5p|IVSI;A6|jqtm|Dom zumU9ZNX+=ULWj%b_zG&@K->$cfaQ#k?_*^}l06&?<_;=X4zFu>8O#;DyTFogOb97p z02RSaU{DLeASSWS25)BQaFxoe5$TCGQl*~gL81~uhxK34@+BJYQqNa}ZbIuk-n3X1 zlC#v}=w*V@8CG`@bCshhbg|;3e--3DmJ4#YAjqdw3=F9vbC;0s;M|&&GIf{eS1`Fg z(5Jwn8kqc@a&j9c%PN>+&c5|?yM3Y^RQw?=O>n+s~ z82llYXOR3o4jT{)%XS|jk?>dy)>MxrPys3nq#3G5h&3eLP)T5GJrk51J){~%kd&yf zq&xw0g&1F;agNjj<^-EtFcD#e=8u`n-;p%q+Kf&H$RE=;fyPEQ(co;U1f0vnoN)$f z2epTgr(6tI(DW(F2Cttn*cC*FkyD~w5(Yu6XDyz^bOT>zE~SL~G?7XCcc-ZcB&1)r zweG(2sMTL$s0M=(!=2u-GqJdQ73BvQy#nR|O2Xz>*=b(pZ~|R|hg;|rvVm+5(Y%kf zEq&}Ub^xuY@-yVPPvru=X)#8~;W9=K$tGj+eWG1qG~;v^ae}oa%G(OIVFGdiGNUpu zao}9p7Mmg2Io9lA#i0txIHtxz@)(;*d4@HRaipNAR8$=B$|X3OK{vojcS!7^Pp}=} zJX|MAPqe3aw_ z!Hz8>3#Z*R`r$s2bCS-fq&#m0yns3n(IM7wbqdeTi^HuGs6ZDMfI&sUOmS+;6o8c1 zrxjFy8ZaJ=fgOSCb9iOlUD_pCnh%`hTGtmQ3sg{R1WX44+1R zLjG-x+_`@;>ThFsN_1y<_{wO}wL2fOp)9CILSA+`|g3<*%z1%?r@3WJv4sR8TCbD}V@Fs;k`78PtF zga88&a)~_=hs|>ab`jqZtfwYYbxJq2thP1L*Vvdz_MF7e*!B&};Rwmc7<(V5bF8~b z;$^1Ql$k)RAtZ*3b`z_ZF5L z*9_HCINwdghY6GJq5N-X_yqNW%{_^PFp!%HhJcD8>I+g0_$^>8R34@l*2y6$VJg_GVXuKR2kQ*Weh<}(A(qESb8r!M9E7GA z&DSuiq46d9!qZ~~=Lx!4{$AwrcasOai6l`%Q<^%JtZ8fI6ayHh ziv|-KM5a_OkkcJhGG1qh3=lKPK7*t;xUmDTjQ8^a{`w2}Mfem+pE0i@ZMIy`LVsj< z|Jd?2QQsb^>~G)*?pNpR9vT0{mO;e>!}SB9T^Z^VVKp_ZH^Qz>w3BnX?I-M2$EY4K zu!}WsV9c{fzC$NlL=(o{A%%}P*}jN1LgXBbr`9=M%VuMN9)=8UE_H_yNEwOQzuOeIwa1p?|hZx%thY54pBLO+i+4TvhO3Dp`t#RXUDRF|>nh*yX>2RV1 zw?OigNeu@M4jVX_Le4M!AS>0f+%41 zGRZxM;~pn_Q}$y`=X+dl_~FX%<=k=rCA0uNgTfS-httIsq z=Nw(*0FMuj7%J3es+3BJQ*W^;pzc0?cz|=y5UOX$;S0pQPfqtRJR}*1F>^@!kV{Ve zqKESc+YHMsta6bYH!wT9CHVvG{Lg0ddWh&p345U;>KeIwq zxYxsk5@~L%CY*=58n?uN4~41kP*7=Gfse)EEZ~L((i{+@V(SSa6QoJxsF>{8+BtQa zpl}>#t1;V7_D|?k^OlIX_=QNR<1A2ZB zPvoMy!{pTQ)?4t-J5QGazLxuiyAR4PTzLcRi6BYP%3|^q(aW@Y1!MN9oI%-Q^94~` zR+4cD(Fl!nAX^%9$TJIAczCyc9cMnog-mZEk_WPb9bYzj(?SodhvEc%C{aC3pcx7g zy8ws*@s?^NaoNG1gV_SaL$?7mg`0b@Y~f))Du@0_hunwa zz-|V!1|CK@?TYc;v^bs_b_ls5aEaOsBon||a-1T0#>9Gd8kpCGk4$WFJa3^53x>EL zX@{4A7LWGo5PzM-;vsJVejF9XjY7~mo5KSy~;l{a+GG9eJ8C8uMy;W?%XO;gC)X+KAk z$C!YT4rIZl3J%6xeX=bjprmtBUea5`!+t^P_NZ(kB_W%dX*K5T9k|xOrMFLqaJZV>LRN6y2iF4Ott+ zKu(3LP#2PEY|%2*mNK&TaD&2E&bz`@VrWQ1!?XdB3862D<-#>;ca2>OCqqKx2Uz{T zY4Zn|{tI#rxcn)R`%HYx`DuE59^|j(0I#gdX-a(-d?@Fn&8EUOdaUlCdW|Hn;rJa; zA?07Ki_}X( zh&VmP$O%Kd#Ki6L>`uv#Ug44}#PQKAob8~_#h7Y~sDqS<&k8=36fk6vQK9T(agwPo zk&PDTdBjcD9XwPBTAZe~5GG*yl3pfmgyF4?6-`gu2c@c^bqFb6~A02`tfCamp(xnih-<@GH>3MN`h2MzjibXc@&5068(cfGnTJ&2lG*< za8f>VF%;uwfk_3|8+hdqI4IvezX!uZuq_M@TwN-fqY1U+Z`py&FdpZZWzEDnr#Vw>ToIf=PmPipz-*TEySwEZo428>8+yFo~#!%AXMAA-(-82tQ+jBkD~|dY;2s zkzP;xLsageGGo7n%ac;7Syv3QO>pM|_ItRW;a*pa7{*CA(Z_tQ=nSLb(I>D^hTfEZ z!FGT%3$r|CfB>B-`C1H^q3981=CEwt%$4XqoWNpK7ndzO*c8W%S`546N2HpS-`sCt zVIfq-X`PnuxITlfEkt&R#R)aR>FCrG4_!FIoA)4nK(gn^#PG{?g-ydqVDhhr0DrL( zz8{4v6bbb>7$#FeLcrz=w%o_-&# z_-%sd%cei-2s-o4OGD&bwkYQES_}oUHwGpdrcx9{a!DgmOKvx=7|Qtq+m*o1v^eIZ zqWoxrT^)ra16@~~XHW|17#(BXmE&`!m~6+v^#xqpDUPyD@cFW&t1cFf)N4VTKKw44 z?h*_%HjGN7aH~`P_EpdiQ2FjC;2!t-c^Cf6S2O=-TWIjnzH-tjdlG5c;Ot#`O^_av zrDp0nLfBB-9#vtcfI2V>;2Jg_;Z4b}UdsNQ3|Gkd5YaOtYkbw>`$$ZdiL2T31x`Ck z-Zgp*X3N9jS^BevJGN{@a0PNtBg|Wfu547wP}O7f%afL{8D(>oa>P({hQXA_c_e{z zR~SF3R1QO1DhXqY6FOhG#9&LCdA}}cfk*m59xITsQDt30i*+ohuop^a@$M*eRkk$B zcB?{YSrj$&@Ek5?#TmQ4l&ZalU0-GxmYb_s8Vnf(*eC!1AOJ~3K~#b_nZ-Vw9XqbJ z1AkI5>S@csa*de}E?X`pN)H?YbrMblW~QgF&oOfRQtXc$Y6$*En`X4cmrK(EM}6Uy$SrF48_R z?qKPV)Ua}gT;yGLszRu8E=F{r2uDWB<45fLsj6PzdjKB%WbRFP#<#c(^U5>En|=$J`gx!;K^*6cpR9;LyX?!l&!9 zcOe!f61T?JTXIm+R9M}!JVbZ{xc8Q#?|f$zaN|jg<@D&`Q@D8uoWSvcu(PW)WLU%A zD$x2Ck$_#)n94E%IrsbTQ**(<8Zm2#56I?! z=Wh2rnrn<6Q`t`m_8d=3)G5YJacNPk<96}(kd&U|JY1(9$z3HS`tm6MS_&H2v1RfI z6&{~@ z_%Q-+0UyK7@!31Of?q&rg_#;QW5Tj~iFOdQOH{@%0S2*D5i&|8nYBAbhQHz@D(&h8 zs(E3viv})Fix6T~J3L&yjK+s}zb3d7B%ff-2WU!kLnh}7qJuOjwW}E16mRE+No9l5 zU^ynIhG-5jW4)cFAhMNWAZMOb0eLjKc~mWoeTGQk9p`Pa!=4*w1GGFA2hAv4nW{v! z@lSTK9o5VsmwG>?f(kQR{3Dsd3$iJ9qoaexQuA*kG~2S~)3$uaaS!V)oNr5av((g%)vlQTqXXS}^Dln9_x7e9`t-Jv=a1apECH zjO#F_B@GFews;e1HFAkaXBwjOsOia8v4bbugcU>98l@uV618UBT(N~CEUFRW$G(5a z#n@?d5HljAj;-O9fkO*s2X<0{^C6cO@~#Iv`3IGAeA2dlq%elDJe=C%FqJRHKkLhD zVJuCJl=pQJPEAomMa$ltbfrnP&Cre=Q6p<|T2i@lj9atmN{JCVxU`d~m+;{ryg3N( zA3a4G_}X!~WC<_Bod<^480L2kD+|*poT;HQmVKkFFNCyXsGTshj;z8QC5R>33L6Zn z5oA@)%Fzd`!x3FB8>!<&O_xD(3uYk6fDbK+foifMYywT{ktVZ_LRDwxTG4qyyHFBm z{2s~tAqI!73Yl_RhB>Sj<1T7As*3TFmMGc`rKLNJ?dGptWs#g9*-=-j3#@y}&mB}_ zX*Bzq1Ei7Jw>)maBz=-LCJwI73qkDH#hKbre)qB7lptFOL+NAWT*}Wjlr#`yL9BA7 z{DAcXeFPgkl^8-cq-Z(WR9qe`*B6Gr{K&xz!=p2pzr*zb9vDuZ7u>m_J{0Clp|31) zVaZ#=d?KV)ICq}dSTuXIHn`+4Q;&9rD3+?vm~o`bxrEaTjQ@&te2y>HJG7~I_%^~9 zE6DakY(B=@3!>SgsblB{s9HiF=zC$`E8A?zLjsLdd7v`};U>>d9cd)IGKxYniaOrF z%)qr798Ah4UIaMp;a&?DT}kz6jMhj|7gL6>TDW#nh+8*Ce<|k2-p=HSR7@^T;KuZ# z>B$9e+@mY-d<~h5J{dIeS_Gw-3x7zdAV@a`$S?v-NTpg4m&*5~GI89rmMS_rtvIlj zdsWTkLFV~`o{NtSKYncZZ*hQ=p%~vTO8d9-mN>Q4Y7uJ@9NAd16sWh^Fj#{ON2N`i zTjn{_OD0;yXhv+0i5n!}Bk(@=hZniu9U)}0+(-Ekl@A!IdxYE~ba=mJ$OE%=WIf5m zU^tHzRRnd435u#>#S+BOm;&(=SEAI{C3?b$0L~PJ%{0Z&cXKJXaxR_4IE+Rc1)(IR z4}Us9e^HD!F;GuOLr#Fb5dj`SfBmHK^yrpGIl5C=_E3ic>0KVDn{4S5*b)BwR8R>W z71NQZ=8?Cg(V>hADb(atAgec;C7z+Y;Gy@0r*(2UjJ4XnPN-RDbY69D?LS_k#QclpcTfBoDEk;_@oZuys z^%OA;IY&fJPB5Y+?2%qbPKd3qQ)HXb;wm^NAE>)6fu2h1jZ` zgyS1hZjd}>YXfsle08kMO-B;ppB)K5Ia1#G0R0L1pSt#v1t zn*y_Yq14-|aM2fK?U87M7M9Kk&9hNts!XW_`mr`=1DubwdNpp}_&2AKLyXB?bp(k# zM)g<@HoiFDWLgkqXFHC6rJ@;ZUD5tUivF*oOk7zQ*uzqhjVIHv>E|@sgJfhd1W_i> zD$@tTG{VQ7@Y*q4eJSwHN0GNtefw9Pz_E8`88#NXXQ{nG&Yu|Hd5@|iXUo)>B5pWv zHiL;olhNR@DPktVWDq)0yxpQMp$S44Nv_8lAxBUXaWW9C5=^8@iB1!B551NF)B{`5 zrx&pHUl24SY}tm4!&4ha=9um9bH2#0u+1gE?=elwM^QN_oSP!oij>i=^_VIi z6-q{nEf;lZHeH>TlyDwOME3*KCu2HoN6}$tObcV_DO!3MkBDGmjNq{ptW1e&!`BeR z6hyG5d_MLNJlIs;AIIF16m%pQhMF9AG076r4%y8x`hY%0+7|M{kXP{RA3**r^VL-O zcQ=KbpN{(WKXia;6zriTSVOyZ%o>LTNA{jBdn#if8L|q=3OP$zy9$+8)D&$r_OW!e z251o~jUb9lDo8bCi?b0CMF5R9!@3z%;^6hL|kM7Ucn66MYYrpV8$vFkHgu zSGejUqPE=YUZPDij&vNn;7Qvzk1)KlP!A;sODgk$`D-PhwIwy|d3a_H9DyC+a0zDv zT&&9Q>0TPEfqFy&EvcdH$Nqx(+7%Z}ajMFdR8ftOla8Mq#uPHDrHzIDv`EFC(fH$Z zQ^;VsK#j%a34tS&8-OQ$0UQs zM9PY-IwUKxRfvYAshPEgICY3OX!kiO{g14T$J>FNc9^)|N8}R7nrsI|Pciu}A-qIG zX`!YOf;Xu^c%bO_t%qt<^qfAKI?kgW;B1k1sh(Uv(~dd)qALpF*%o$M*monj9MLC^ zHNBT7V`?>J8mb=8IT(F~K7+R9Hxn>7DBKYBt89l;gokI7<_N20@ei^ZbB zk!-=Ctb(;t${SIlmj6R9_mSWy}%DV9yGw3K`?kCV1z zLr2GGwPP6=$5C*GasF&H(AfsgVi{4Z-6+dWVb+!2SGFaOOD+Z!R}5D>*r{M%jVWUk zj?Txi@)(P8R{@%J8Ha=7grY?R+B|AvWk^_ZU!yoQPna58PL44XR`C@~dWae!s~yXm z%rG6O)uUC$u9e@tl6mJN`*l9xsFKjG9n;2?Q?(jfPP59zsQ=LTSp}0Uz4fR_DNnYR zW|D}ZqEbscIGlP+ZK$l^d+1SmQ-<_}M3Mn(63!`UaCqzK%uBfZEV+Ncboz6KB%o7r zx=A!Y0KP}g25*&=PDysaJ|c5|Y))wz^%}ImeRdv>>GYf)YG~>K|gv0-L8~lUT%#2f1dEGWC_r@>pq4 zGk^S2=70FeJSt%vvTyJg!q7P+S|nT48EmwV6WXsB-&FX)qt?+Gp|VO|TVx7dvN&~E zXGmDO!6R5qR{Z}<*}MH(c3o$Fzj;|}?d!SJ#@F(nv$mIka;^ib!m5;_hyv5RjjdpFk5+cfoqPBuAo7^6q)OVwh8%l5w9YC-ppnR^k(2{LO^cE83QgZ)-p+9PJyz*E_&9^IV#^Ijy5n|C9J|2L)Z*6_5^RadAoy`1-{zA=NERFo~u>m zF_>WV;S#=e0x$boZ^Zh*+X@wr&{bO5{?HlgpVj{@bu!tCjmj6%$g_J=NmGl}s5ViI z3cJ#w?g-6LcnRf_;tC<$XBvz(bv$%D-TX6%-=OXVTCSNk1Dg;yPG(d4^uqH4d;JP7 zlKa3s2Fe(a=I#@8I~4 z6jrF*P-ISYCTy9cd-VCc6#X3aFK}*+jDc1h$M+z=bS!r6&;>N&7_z;3QHN89cz<~P zH4kKCi-gU_MfWbc`YKQ6$U#uHOy6=fEb-YJYTLZcMt2)d%gb6$-PZG2m-ZJWlakve0o)=MNy1ZN;q@FPJ1nXqvl zKTZhI5!H~tF51B8@f2<{JW*@IwpmGWjYrUNM(_<_dK2 z^G`aoeB)q6-(YsYbZu2CAKj@F21qrMjdivV)Gl4;t<#wl&-rj4C(nWBtjc4$(W2Qj z!ghQ}6HiEKhH67xI7W3$ien92jE=v+qm)Q)9YHPpiv)tY-$*O;MTw!Xa|ul^P$xu2 zJelG;+H#E3cNoik8`tIuPTwY!-=+%iE|=1B&~eb)n=P2e=tx**<}yEF&b`St6s%BFS2{`YCf z=^Y+td$2W`RWPX3|NG&rl7%WTH7XQ;iIgh{10oZycHcufD`;_Q-GUFyyx`Zu&?!6M zF|cX%S0jKpDB_p~M@s&6AH0A4#$q_kKqL=z@f%9ML}_pmiQGfLnU;deoX{Mx zm>MDTQS}0NS;Zbh2Gs_<;-!#%r11%l;-ebjgk#DGV`JfVlTDjwhtuO^O~|*1Z^)%1 z`o;z_9_DJYwY|(dILp(oXS`JyLagkfI_S|vmIP)GLgR_=wE?<0@~s-^nRq@zK6(2^k0zmifQawsnP+hSLQq6D45M(^%9Ou zfkB)RC&3Jk{&xCThn8S9j0pGwGQt#mQlxlXn&R{gln+^U7N!R^gzL10w-;8`u9Lx^ zPuCAQPru7hHfX!WJ5y|g=x`x|F7R>+@d(@rE>H1(f|I#T)EcYkXO;ES)tA_|up1_b zb`)nVrxsAnBpC@o$vH95(0d!dhAKtd^bqulFowDO#3gg$$x?OKgaP6nl6dW6-n1<842MEiO(TV@S1SV1&urBc5_SHCdQ_4 zKNr3d;kXh0x2f{&*D1g&gF}!zenvql-yWG&ZVvwvH0KFjDZcWs}#;njX=CsbnVe!ndvp_a?&s^<(%Dbw5HQ zJ3zdW^-zfZ9oMM1CX}C57L9(flL=7-4GyP@l8JG}s+@9>psg~rWo7ls4BlAQ zm%pimlR6IG72_VPlNFgmwnFW;@&k@*J1S~ne>K`T+m%B*7|N8ar}Z;B#it3WxuS5x zpc#o9+?ZKU3UQN(ejt{_X4cc~GN(tG%bk!~g;x1C!pE;ufLG(uc_k%iW1(oQc^`b^ zX++JgjervH;z$~ps53MVtykj`Z4xoPGAHrTqcTOpPx*RtM)alzUUpX5{$d3#?#R*O z(}XOAQKsN#NVt!4bDT!hHKK=LDF5iSM~(F(@P#_VN!F_G({{`YaLDC5M6 zM9s$g8!EvhmwGwGGz=Nb^-pe1g098VnN$0`yezpIzKdf=5s&Dcc6bW$IXNd>lSpKy zI+7=a-Fn1N6Za)^Gtc~TCp@Nb?@aj1e{Xx4ezd;;aa7a`nglly>$|fOyrUP}T&3bs zj27m_3PQ9Y`39vSYG81l;1XIkwr58=v}p*EiTMjgI)1tSU0%2aZy#Ib>*x^#FA*PG z9G<|O?3YMhP{NE>8j4Kup(<@Vcr-Jj<~qZx{m8ZQ?RItGvaT#2RlCGREKV01iY7z{ zZgR)4wl;D#0{+%eIPEOzh?>JluvR(8o-xn3sfwX)G<5Q2gck$M_Ykjx*#hn*tKd`R z18#du14#^)P8qK1pz5ZFmuuLKTSPNLU=inhu&}5$lnI`R(aUv02~!4{(6xnbOzfJ( zRtlX<98E`5GAqe!#zNc`-aQlk_b>NLxn6SxEdtD=P(%dulYW6hs-_F6p`lROXn~Dd_8qgk2f@uh%v#`I- zh9T^-rNGT#z5OmhmNhatmEw{;NJrol zukRw`x5zRF*CXK>QqBo^jfO%DBV#goOp_hX6;j#JgiF+aZDVI_m=tt^=0IeE>JiQ@ z5Iv%B#5{P8TKnM}Z_~Zo1b%BFRRSzM+@D!aj^6U^rq0)!O2zV3VcQpD`t<4<3uq}g ztj&|qpk+#{g`{Qx?U)jSXW*DlJWVB{p41Ud;aErF?dg zyCb^J^Pq*ZxpDP+wHNbpw9#$6qvgw$ejW69$z<(bhMYiG zG@LWaImuljVZ)4pK|Syes=tkk=cMvi_^=_%4eCE9mM=jsX!C|uNVJ-XT9E5P-xV%= zVZBk_-xh}BdiWnIe`}9SM3WG^LhFQ41ze^Hfl?Hw?zIRaiLE#ta|iAi=f1_%y~Sb* zH{)CE^cvMCP;ThLmgF1_g#e62XeHy^l%~u`{RuEd8VEj+(uCL?;rzV1ksQ$lZw%hX z?AxZ%c>S*`YUe6rrgc_@vxb|-KJZ<#4}H;D&G2wyE!(=azqb)9!o=ob6{HD-XyQ-F z?Q3AKRl^yk(enL+7T%h`<0HF(&l=DTT$KYQd~{aKtrJ}JmJ;yR`Yu}I!|Zn8v}a(8 zcWYd@W}dGY!kTT#kmp3#q7o_ooTxv+^PH@=P+pPbIm_7<>oTy>Opd}rGm9>BZ<+bi zmGJniaN7uvm&%p7fbz#y0~{DZj6$3j^g5%_lY5VwW_<88QrKxUbWl9KL|US0+_G3k zr~=SXrg%DB8&ND@W@4qp3L_I@en_w1L3m80C6`Pr*biD9;wJboF*0hf4_%F)LQ@?> zQ_Z2J%C?&TWoO+$<19z+YWP>IaGX@sE)U>4XtQDMzG4v+W8Ti9fmK&KYuB>W*-m4J zxa{DqB|M&)&e4k%qVwKDey**gB#TC4HvVB$xL*w=PLiRCy98UYRz}@G@FRoo>B^eo zdt5Ux4*w^?{|De}ivEltUolBL(rm?4Z|QYlaG5SBi)CVWT?o^{lc>CXT=?{*@Zp*A zy@v|*^}D~L4jzOQ6yFu3$+SaYGZZ>skWh$8NX`>*h$zVmE^i?`W0W(l`!iF?>M>I0 zL>kn!h))DBl+qE$DJ4E6m+#{F0rz5L(HJXdsPwF%*g@xF2if?8cJ6#@Y~-CBd;s=> zjLv6N)_{#F5Z}1^jKBZP7^GWJe7+QCP2L%;W$8#SM8#S`0zIgL;AHc?QBh{ z^o|fcP4W2b$c;^tN>L^_dhf`k;QTF4pWx+`EDOAwp)yDP5}287yblJ(_yx(IA-qL& z?{j|=d4CQM7RG{E*ED{$gUe)LbExVbSLX?<4ct`0#JJb;RqwyOs;6ts)@?R>P4|Zy z4Ro-dc1!{7I1&j0Ih1 zV+e`E$HFdUi*+h^gg`>7{3X-S#+jjVOep%0B4;?~aO0Md23OvM^53ArquRU{NW3+H z_fD;dYCK#m;Hx!!xw4B8oP~d1U*g`WORI2VUjPaQo!)EU-D7w(v50aznETjmvI9a6 zY$50DWvf~j;c^{#MvDfGfNSl0=o;%lX017mQ?-0}^YsbST41VC!E(j?OKqH_z%JU) zw8^IR+ZH1Tolf9Y2ivqD5luvr5~CaFb;muoV>b>=W&^ntcE_1631yb)fN3k-UI?e9 zunWq!mW7|Jgx@(6p4^!4(~sbF@#lVB1jq~F-Bh@`HW~Ohb@+`#TF7fp<0H-|*3!~M zh1}4Uz!*E4e9XPh%$wE;o^F2!aa)`yonApGI2lp>l0bv_B`^C^1A%H^{O%Df@4?cU zcff7Un@xtvv7Bia|}nv_LHsG#tYn~Y91|i(YjhUq+-zb z?v9b9bJYZ*QpX#cDwD)?`&7Bsu2hS-sZqVovJG`^)F|KOPLVlQ_mFX@9uUPM)7BgM zx9K6co+3({gwbugf+hW~NTORO@o7!1d-Nb!&^o`QQusX$yCm6Ia0 zsyw-JJfP4Y6~YVUItt5HIPQe$MESB&@=ExeC41`pBj@js6N7vXl|@H?0! z$khm8=%HD{m?ADYCQW2W4pm3vBFUYSd7HM%vV()dge1p!@kHlI1V}qn6UB{qHz59o z+u?*%TABb49Za*KY0lY)`&%dQ@IE|P!l|#-H3yT2eVgX%0flJn+9PihxJ?hw*VY}B zYA=5_wF~xOM&%&x88k-6j;_+hz3B&hjWDtL`2=SL;G;RT%c>Hp7p|+DM0Qn;v^R>B zDm_1L4HRmk)jwx5<1@qnyL_LNw?y}nVZ5fa1EVhtlF3PECWYV&-<=j>qr8RC2jz<^ z=#$dLg1;|(Ru3QGlX(sOAG2R~|Leq|;p6}5eb3Kk4!455R4wp@BC)x89HT+BaHCqjlzuxpT1OddwBVG5C4x*{$y_m|Lbai zXG`V1m%EJ5)Wn4eWHnG;EP!MdqB~pKzNWvQRTWq=0m_ zFe-0wJG?>AXL#*!;R)FfI6uJ9lRL)_tEx{Gx`i!npslm@J+U$z!uP9SZJw`f*q%AN zPVllaj^u8Yjaj^bJt zyN2usu5&|^2I6vLwJW@tlt0LhF@z%duc(^bP`?OAU(lu5v|Bgzi^6+>SbLSWeETVM0KTEF|Oe-p_&V2yX@c(wH% zN518a37q&^jaRMy>xs*FNMOFYb~aVIJwz%;-VS@j3Pq{5E|bP`@!oWytGa;e3I*>* z`%iE%SyqU)5;e6>^(L*QisNX@quO~5`$skO%N@6n-U`04x`QOCuBO%H<94uSYSUYk zxa=!9HQMFtLdS0S7O}k~OQiKLNjjrUR?O3uG~e;IyX9u=xoRV`t3VEp(Dm@W%ta7} zmyUCQkM$pO_?7~G_?hF=KeQZteFd{~$IA)aP90|gudY1ZN|~HG+Qze!NTZQHP3XE7 zr>BU2n`zrIslIs5S;5o#y1q@I*MU-A*)~kc;NIi$^daw_*kNfEY>Ka*Kf=L$r)u=~ z`+#(T!E#Q-l;^)jqfFCVSAykF73 z$!RrDyjOp(1Wwk#4UD&zb~dHfC>3E;EIn+!?HaloZ3;M62h!VA>E9lDc@w0?YlCYX zp$$O69 zzwx{rJl}ui(Bio6;Z_~Tjbqq3y6eDp*3n5rXr>fd;@z8we!yw$ST=^JNfkFzv2k&5 zGwcZQ3ksKzGTu!Q{~m4K`E%9RoqWYUkN`~gNx2-BIHY2mNOz+FEJZ6nf4@8;+TlN# z7(rC?LCHN-cy?3AvfGLht`cmAS_9lMn4GupU=H_>>%rfv5dce<`@?5r?w^~{YLrra zi33(YXk#s}WLWh^9vQ^=03}%Mblh4OBjt=im*5qR(6~8{$Ecn$(Z@)Hs4mITO>hBwqjc-yFeAd>p5vzr~*!S2-#T%v&2Q!^W!64#AW5Q4o z_%gsRH;-8lj?o=6=oY6Fgc+s0Wb}dM^k?)mO@PrDryE9Bmxksq*Z^@$GZrS_+#Xqtn7%A?X`Leuv}ErgBXk zeC#UY^>$|;z(o(v{e(7tMPY>>Gkue3{TA=OWUXiP{Tp15?{m?3PP0M7M^#U7QVb*T z-WE#jw}K67t)HvjKANpa9BZL#7F-}r-9zV;7 z-9h#;@@;kXN{95-RS+vpE!qTUngCZnn_0HnpsBvaU9gLPZ(p`B$)DGaS}wN>VW^5I7bKJoewY!i=s@{#BFpLljhfr}Ve zwVvPJI$jL{cVBR8<^D6}`3X#(LVKFsB^!^oD1m6jbGv#A+ij*xO-jMW~mAuc`-(yrOmaY=aw+6K2V8zs{;b5wCueHN^ zHdfN*Xa^mt^~yUlcz9G_Z!v?1Qfy);m69FmK*#Ap-|zOzqB4{Xgsb|IHFrD$bES&c zFh5C^?$z1@*cX6Q0qGzxomwPI$)ZlHRs)UR{vBTpv&SX${emu9`#STm8UlZI{Vz~m zdrXh2(&a_MA`4i>+-x5CjsPN$@?$>z(9WKB}FFjAUf$!W8u!?x!@YFZl zpFp!p{Bi@wL!s#u9|~bxkT$cCz@!t3SoJ-x>fNzQt*-{q=C8=Zf1-^~QGWqxWXZ_N zx45>TsU^o9ZCEj;7TQ;IZbFtR=i4d48}Dw`R*#(mYqdHdRb_6k2DEJQLF=z0Z0cU2 zZg256Ke&3GZsDr6*IlZJL)~GAfbI_i6N`Qs;0*_}{!S`bTbkM*aFZ+oOegmBOT`nk zb}MZ(Cv#uSZYI~-Bv-${+jM}Vo5uDQv~ydI`QFqh^{)oF*um5EyF|GrNn$e1lwlxD z2Cn9X(?M8%NBHY6gX6@pnBpFC&AWGimPO(kUBX*tu(_%PYnp zumWi_y3V-ij;TH)>Hmu>BbRcIi~bL}E^|`0Z*naE3FK2IJi!m=^zFcek!^OAMrlf* zX+}!%B!5b1<`mtsEi2~kD{`2V#Z!hOwqpyv8d9*u$$)z0W^CDBENZEf5N(WqS7`|9 zZ1QJV?}0tkOwE-eMmrEUTD?;0;qQ%^e6mP0)~L2@V77&LZrzBC2Ol4*qqwhLKz&vI zglu24tyspf2RAWp!ls%)=gK5172D|Q@+yb1pqJH0XjHhrglFd;ko*gL9LQrb7FJG# zlvy8T{8l(S6FwLU|Nhg!rxbo;1h~nLb`=yV5^08>hR16O(A5= z@hbe6lu&T`=Y-}PM%@zSnBwL*mnqT`oC6(g)Y^%i%>?ixCt80G!6hle}3+`UK68wfj6+0vw* zaWTLq;o8I)3r|YgF*>}9I6p^a#zfK?Q4@CTr&^tLD>V4K52vH3w)%;=$ASSx2PPcYk93Rul$;wu01Gx6@?{+x(c4ukqZV?uIyBvn^Xn9vIpwkBgGdBX8g8 zZ;Aqu8?VG!;bNDVkFQYuGdy2H+~D|z%o^DVr4_bknYTZ4{KaYJpS1%w%>*}Ynd^+? zmw5ksXn2QKSL71tq{sP3IQ@{J{5y~h(FNL8QQxuADY0pZ@&NQLTz04);r)BO*}->? z?B)FR4Xm#g6#oq|-k>sqQ+fyL1R>DL2K5WjW0QkcKHrpDv~`DePO89j+L)*RaeG)R zds{8sw!AjmdcAE#>mmt{U8VAp^H+Gi#mNdcnX>JBx-@`~Z2oEH$*+$Bk@qLU zSGz*+BOAG79(Rn|(zcmYdeUaZA7{?8aPdTWALaPliPf`)#*Kt_Mv0Ly9;4wMM)_Tw zzMzd?GK?NS`39F>u;3LN^++>8;)IkZ1UI2cj}iHZ`Q*g(`3SSlb8l*c8rkpt^~Y!s zG6{5xiqiQEWD+gTH#nyRF397SU7B%I3%GspN1YS6U<4G8<=4g14o4k)4P34dtL00L z7W>7MvA)Q~r0z8ys;j8NeYISE*HAiCT>$%K9y_WWs78PbTO@h0wZbvfw(wzNUn4qu z`FU4&9_)Xd`sbVe5l&xG^c>1{70|92nh8gfo~JJHc6W!z=T!co==t>BM^ZdbV27Jlz@;eY+Wv)Fk)oO+%O4HIvM(v#R!>Gc)juMpWH zL1^*{$ZQ%hjUPuu=6E^6xnm@}%_5%gU}}@N+riuX-5JlWQL}FS#cjluL<%D`g%~nL z3Plxd20{Xwo*~}i(ks^ex47!z#Vx$i-g$i!c)b501)52Hk#)J_aR>j;XnlG~hjnwh zcNMJ=@3fA-f4Zs#W8D+@ptgFi)mPOE=(T*juL$A*+gbqL*7?A&|5lvI=qJ;|BFjyv zBWiDi6csbL7=}|sA0hez$_1@1$o+!0+j5&)CZ%Vx3bglS|1I6!BM`azvA_@D@da=# ztiD?~1GbGrR)X`wuoa$vuKeG?e+^tNJt;SwELv{23+}rkwi?j#HR@mC!zHD^!1-i@ zj>gfn4Y^++@syAsk=lo-n?r6{i@?^`#m{SYX~ETKuYcJY8%OmV35n1ODgha*ZXpPh zkVvIRM+km}zJ&snfhj6UF_1dox$0m`Uk5X zwww$d+ztn;uc$)Yh*YHD&r-umeZxDX?W9$;_gtITK z5uO1TQMsQLJ{O*&EI)F@&pq#K1J6U`=yuA<@)3jn9zK7Fx+N-G#{3H31v*;NykoXe z#@rE`hm`U=h6U1%v^l!HLHON28|s zFDc?0N7R8dW&&$Q_ktUFgXgzZEu`@M#ho0T@6^E2hC69(#MFFuC{%?Z4x@)Zn3$W` zI2dXe?ra^&&K`HztCqr@NZ{^pv#LqNtS+4rHU45M1{?RzCX`OCzzhv^OOv3_ui&pL z*I_b&Nr9W)350uSK4##AMz0wrYo>Wk?i+4y8z=++^OL~&ulm14=M2T>;~y)Z;yC~4 zFhP3wiSiuy5rP8$Y85$-%29Fj^T0GM8OrYx-G9fd{R0-!!r8WbiRV9%XwdQ$i33GW ziSAwS-$(f`IBx8RU*|&M8J=rscBljb1qoXQ2{;CPvj)~U4HV`?%}_E!)6uX)P!u7l zqisiqu_u&k`t*?7HZaeYW1ru^8~bWJ+^LCf%pUf|)~ay7KST}-o;(Nbe!+^zdo#NL zyKJ3-^M|!HzS_|451d{7T3h2bwl%ek#io*}>Kz75`6N5L5X%f_u67SIt6kpT6J4{V zp{|A9ctYDO(X_zH1a%#ybP!t>yB*_oB;adyCth2(;Zr|nQ#-lRe+y>`2M1M?nZ{zas^R1-`E!G8I^nsi4 z5k4lPFa%Q+2R7zJt_kM^=Q@f8B8kulsbm6)Bmoyk+A@-Ym~U@05@dzShKWDoY;J(h zlUw^x-QVlVOQ&0!I>OFnIX++J;NdwuZ3f`qH(scB3RaE-BUCyjO?Qnpv!SEA~5m9%eqgMU+H4T~Oj42*JcKhe5n?X<52 zRm0^&I3#~ z)@!$Iwe|}(K0d9xfKNI*m~B3=iuQZ~t!>+1Uss?8h^-M?n>(VFqSiY0)gy2(4C#}> zzC#^qy}n3y9Ax51##O*X4KRV7A`_lk3#h$A?UBU(Srf)MWUaAE|_(-xd- zS?6QC+nM)IQ3z8TGpk2^&*kQXO&#xMH4fgcvV(FJet2&JlgD*(=$-8p+LnXG+rAat zyTOgs461F619?&bnkF1l|1jDm+Ew1bp3XMbysxhv)#_%`dfE0XZTI(IoY~a9TEmOA zv6%W=+@|U%y2%q%FM&%kH;Ast+OzaKav3;_iQ7%#-AnnC&t9v8|Iq_~os zO2mgm&XHaWj2Yyxf7!TrsU|o@)c(+R?J3218}d~3aI8ARSqIzgeM1P@p>9M+rD?V# z8R*I_f@fff+f8UER<%=$yO7Lfq{tzsQ^he4r*;6F@ldJnw~==RW>XvUwnulCNmZD) z)Pvqt9Yd;<#Uh6qLhk^TiNm4_Ux!uuZ^@}$s8}D2hQoIBSZQS*Sa07UaYjfp5N|sd zoF_ZS6}BGui`R}y`k!?H0Nlrj>L<#-05)$sK740Kv)*tiE2i-aVzZ?m8pQtq&l~K< zFKGOV;-eL5yyAR#hqS30zQKwi=L}3QQV;}(ypFf3o?(2dHIi4`#rs$Av|7GMx&z}^WbU}B zV9%@;YE=?8)ZtDl6gHl-m9_Mvvw=f8** zbo1CUYapkFm%HD>^H&UB>70_&1ez1xni~D;dZ>16-thaC!bJzq*6`N!PAcdRHA1Lu z8hfMX+N$LWS>JUEy&mmyr&2iqr5Z?-gOP;F9Zc?TS<{Jh)6DOn~H0}oF=SV(f2qqb`t1oz0(5eg>Yv@lJP#19C<5UqhvPvyu zu7=83B$&6Rw|iq^{dIofInPIUw`I&HH0}{+ExfrnP`UD6#s#>++Qb=_Qck6&fwi%I zcU6ZV)h{?>1da7*%Hc=12a(9-&M02%(Td1zwy%@-Le#pCpw#HK-&Fp$MVwN(1XAq( zpSQMTYLkrUvcZ1V%VL|$&R1|Xj0v4%xT>*+A2-TBpva3i-rt3 zr{M7};6iQq#7v_dhNy@%1Q*b~3RA>xd=0-L!h;4LFN{9kQA2qZs>bYb{?Y3}PtNvJ zKj>^n->Z%F+o^zVEyQ-0@J@!4iW^+jeZFbW{;h6cI>IYwFYhATMv;BTa9ei|Z0cJ1 zo`a*QR$fB6yJVu`5qI`k;ww^^tGGt8ea}+U*J@{uBd>O5mw&PADgMWV?sKO3oH6t? zF_Xx=#mMJV;YTZe)hP1sJN%DvuMhp-;(7W5`@^f9tYAP@D#^q#P+A;%`;ke%jmZZO(r*mmq9uEsqo2D_&2Eg z_&2nHy1$Ztgy(y}zx{#d@y^k`>sZxQBa;+3>pZiQK(}zLx|YRx!*J1Yd@u7=f_tG* zB;!Lua-mQN7c7JXr@^D0IQLfy^NDrC;3+;QX2pGDBJLY8y>JlHhn+dHuCdZz`Yv zbYffur|@iL^N+R)SeU^ZdtZWLm*lltsB#0Al|8-pB@lN9MwUYaa9GQ?t`+09*x%b$ z==%A_<`-FhMhrit@Jl-PC8>SMDsSk9fz7<<{x335?+d>-E1cOL;a{5q6da0;3_twH z@!3nyxb)n#j`y$O>Bci`18<4r>j#lpA9z_BW*Xs*DZ4x)U(b0kjjVSq(^hP8V-S>L zLzMtg6!i)r=L*glw_Em$AOKM{_b+EJ)YXk2*U4m8s{|RvGpF%3 zE$nKY(AKoE8R6@#;@oqhUo#TP(&4eqT$kI4;YrR8YgXmrZFLxlz{SQQ&E?kgeu3I5 zR*Ya?7fxOcb;nWV5=^2^5f{-Q-m(XN+@amudmp8$fGXA4I@Tg@D0bN|w;=qSsGp;J zP1AnEc5_A06>YobG;UduIhu{UTo(TH$I3^@-EmL++t2^?;q%h-#hK^(gX8JO^UG-< zYrsd(t2QuiBD*#cuN(3>BgbP-!z1$alrgNB7sb($N`&BXY8AbTqi}?lw{dw(=q?B( z6uaKu2hjccnn-3uvxP#@k?2aFk^^%h4VaLOC)|6km>^jLNr`TZA> zdCs|yx>eO({b0BF=;27TObWKg@@%v)+Dm({0sLu(`Vt2G3A_-z^1^@@MgxKk8!#<< zBuXPnBAd;A*Sqe$=arceUYy%aQj}(7kAXS0sRHVrLggbeBjW!EJns~hFD>PLC(yVp z5X&zq^^3`dO>}Cf`XQ7{Is)@l;my?axfXW9RXT<0b(-!DpI%NlLJvz2rUAN2Mu<<*vZhExE%9`?Mbrzt2xGa%RhceX zC!1;KV4p&HP9+s)ONwk!)+a}ZQ6lJ`!eAMpKRc`E4Y6GenQ0-wMf_9 zm7IeLCGXMZ12$nkMUh?g@0Ek;tKBbr$!U0%-uW)o%?Xl^6h8x=q4pFB zj}Uo|Rxhdjgv;@Ym^ajHScQ>0hduxCpzwqLp1Fs~gWtsjel_&}3xqps;aRI}=fc5C z>DB?;MvjNbn;y7W%{cU$B#|*G4GYZon8_iz?Bh10E~lhYF$+SL8WTm`F$F1tu%gjP zE!;yQn30MSD%*)ZIO3V29cnM>>F}KapQ$5Uk^O?p5_es{E!lf2$<*SEdJcR}mPC}1 zv+ml&xM9arEdK+M$BdklMOoDqy&t0aoKX)^8OUY9d4I^scA~219WDK=n`q{byAdfr zrO0z?J0+Dg73-T%i9RRV40oMU*iu8-C$di&udxjWAbV7*uc7HwyYRnD4_|o;nSqyq z;v>R29xfoApniZ%!0M@1&u z^bVDohdH80kZ$aZJf5TW5oV8&dV@9r8){0NF_$GJ9pdZ*_YnS^cdo%(JL$P~3y*tv z-u6WKFBE@-+c7~qAQ3b%j1@5`K_kQ&o*Q&FN12g)pITNV*{7C0itHoO;I<+XFqy7@ zMKVD~#0N4xB3n#aLb;^K8F4(p!#U=sgzA(yoKyM@DQt+oVZGdPIVRrdTb_+mBVlJB zFCTt=5yY>Y{cvYJ)fqQQcyt-aMTkuxk2MFwl0j}Eazw~0td3Kd%STAH2W22}PT(bI zBADVu2-Q^0@Ldr{XmNRj#L4=_twF@5Jm0VF?g1Ozhv_mzMlHYI9R|c|iYOTeFPI3G z7P5q?CvQ+pskEc2&q(zY#42zxsX zrR!K(V05Sy#0sV(NQYRa@(qbKt`~@1FvbfiIVZ*o=r(lSma%F%@(oH)+ZGPaGp7sT z-p1JM2YBD$7x)hm`SF*qu;?KC2;um?@a*NZtM;x7VJ(~#p>~DElH#}U>RpPxgU1^P z4cGz5n}{_Odx@5xQR0?pBQA~wa1R7A#0x>wBrP{-vm>F}Nq$DO++`NNvja!|66Jyt z3^7L}QM8~w$#7dy3W9|4x}a_jO&A$-g-9U=A>|Pb8;}i}3R1U-Y?=F(&Uz~E$>gc# zK13RA=*yN$x41y|Jx+!@AWN1y*~Mo68CpI8`2y2Za_sQV(B3BYZ&Q6Ze!(R( z=Gh1m$Z2niQgMry4H8dqkBA>pxJfLRn5+p^!V~0B2r^)~ot(k)n&9U&^*N<&pKQ({C4!-z@GAMCA9?0ZvCDW}!;LdQ=XxGOKI) zxJR)!3H~0YA0T!Iq{djHyfInHYe37VQ0dgbEjlTNk};12%1&reNjupO^{MYa@%g^Z zn+FsB|03<-qDa}|T%bB4ZeRryCu-W=S{xN{99LmTfjah#S$D9kkz$6Vg0mrYBaLKo z3CtSBV+CE$I1Z#er{s!79r1p}NFvsT7w2^N2b}vH_s`JqS9tXaRer|C2Ab1JQ*K)o z#xW8!Qncr)B=+kqb!&LDqRT60eglyOo?1xfcyk3IVfiKaBXTIX^~f;dI?aWPlPnQA zr4ExloNm_?Z7I2D8Mnw{gsqWg#{SwEtA<#VRBBQ)FrEq=jSRs3m(E{IHOH@a1K(Ru zyMKFICgcflv=rJlLbXKvI>qmy`dyqi!F&9*Mb;Mg7Zkamk`|XjaK&RrOQ!f#_$jVa zG}y6KO#;CR!4o2h()Z)~xEDu9;)$I${e%77YFtAJ%XGN;ucDWaE9ox zb2^{C5FzHspbOM*Pmnr!fpChYOH{5HRxNswkT7yyjKgGvLFlR(Hr`~;0m(;Z@)A8b zz2c*a(v(L2Oz&20gh_t@`bbbmaqm!buKHN5Uf$q3?c#ZM3hrRUSPffjtTNP zeR+cB%|w0;5U3~&;DHd7VsSd4{goWp#GQ5qtokjN!W+^6@IFgb+@Mk-5!A0WDijWwAq*&k!W7BBCU{0!8IZglcF+fB`EmJnYs zk8^yi7&Q~}8Kt@)$!7#pV%#95rJ8LxCsC7_^*u3Uw(G`^2=2j>Z+t=ak&HCI%pJ*zbEq;r-# z3A$ryR(VA&?_&O4LOmeqW4!z|dz$Fhg)tZ2TTjRS*CN2()lS<5Xrt2vXALYYQFH(~ z2YpJBUm`N2_ywUnfp~)038lKA@eL^yDp3@p5GD|aj<_qj%dvI$PYM$`U!whj6;;!b@u)4DsB3+_E4JyLvka7|7jQZC4L#>_SlGpfc|oZ5xnE2`8}$#3br&~QN`XNX?W zY&SeT7@3LTb7xtE$LosgOM|XL;% z))~PQ?pK&RL#U8^j>Hq zOwevR+q09j;xf%SA8w-h7zxKnNdz1*#kql&ySO~W!xO}&3XjVKAR|;*KE%sC-d+gb zT25|V|Lfu%+@2EsKjZ!zlK-4lD71sK7b}Y2M(tf0h!~TCg77g z&EG^1zxlv<`hDka>kO51*ccZ;9TNSpp$gBiFc9TADK}V?IJ7la+7o0XsX|Z!5!cLS zYzQg@5sZe~BjSPV5sFf2PqG;%hIvNHKu~AFKrZKas1OoKGC?{5112?=DvGTT5i|&H z1y@I0C)<}2K$kRC%`8qpjnP5vk{BK`mQQeb%t9{dn~FR}T;~M4NeSN}%Da=#FahyX zkY{Liax7G#XY>RcV-^eDfs?KjJq=VhPO@yKLVZtER5zig-7oQZ)1G1Hr|?dw8>$dY}G;t zJIs8c%$%y8^w+NH$TB6$VPszoE5<+|Xe7JtyoDoHCQH{C2U4CPYuSq-x}l5-)u~}}+`?7s1oG2DKGMZlO9LHUk&bjG_bUF0l*=55|0$?k~45orhOKy_YB#g<(IVdcndgTr+de zWSoB9v)W#e!-~okp<@VFNWaGVk!MY2FBZhaK1;z-jK-kuphdDr;2A2}bsiU2a< zzBzx_;8W#$qjC0G;nAN2_G{zC=;*v7wu#DH)*hJwWiHIOQ&Fapig}Z0f^vD)aJg{m z3|_V1N{o?0HJ$nD_&BLB*Rdnz8SaImKIQrzrhAc{ z+Ef^ebM~#m>0b#yxRJTmIYTYX_6rL)wlNcm((B~MEH2dRfi|x3`h<|2)+W~vn#@Hi zyE=g}J~yg6g_Bj`#uo+`P6zyxqryiS9&DVO4;>ylKi+{lKEybB6HXt)Q8nq*e$g4Z znOc#p$KG4t~S4U|a; zYNyxrI>l2rTpYo1gv#>kf~JTgmdFahJH|W^-4F|O6oeM(FW9S&d6~~R7(3e8fLbAy zf{zu^j;Nb^Sa}zh+lUv$zrd>BFdH6o-d#|yGQ~2XD#TPMIpei)*chk3hV{O3cn{`n zAjLpk1g?}MPUXVM0uDN73oN2>8l2J@%gVUDD6|)jT^OY@e)`yXkHR^|2fK6o!>^y; zU+w7m4+&o@zaTOP9P)lM;@jDzjiHi(!z?wMb2;utG6ozi5O$y#G_jY4^34NHdD}W|A^XM=)HfK&bGxE&%uLs7v9~nRXQqALU zQ~P|~%Q?O;{Oh&w^GoGuH&552^OM@SHh1oRRQOB$RTc0XJ`%5CU>_rVa9?=37QT0> zoMquM3kN1_zPC#i9}9~(z3Aqk{B}>dyAqzRBa21FVF>ih(0WEFb3Cljyfc=P1z8rv zP*cYFBmq|{DitIMrur4ml1vaWoFcxHh&2LbM-I)14v2RY>nX7%lr63;WiwF6j?*qN zmyv^}<79MhNFw!)m&{2~4y%CcLC3TRRMWVDE$uDT~4F1M@-1(F)05 z9zXpK?myH@6#`9FvrhYjBvj3s)Lk*;mbA>=C2{?-@IQYe)D-T%FPx6TIt%x9?|V8b z+=1l_pC)~G>Ao{}{@u#C|G-|!y#L=WfNwzh{Ohy)hu$ZD>uUOV*C@IVJYD~O=b0}q zm469*c2hZ7Dc{>F-Co574a-zx(lFm^pj$BNoKhBu?m?NMH001AL@ENsE5rgSyCYyn zmYaG$6SNF6A_-;ex|NrMBf7D9)(I5UjK1TQ<@Ne!5_jfR|QU~sy zM&_%Ei>7+L2%>xgMs%9|EQwG?Bz7bQ zLg^`afYc*#z{AK{N*vn2ej1Ry%<(hlV3m0}H~1J9>b$rO|L6_aUQP#2mxZfQ*(T+t z335YGi7fiaxgQeBKSbo8<6Hy#n9P48HlNV-8*Z1x>6rN0ZweFe!e1Y!0LRFem9|~w z?Ix3%^WSmT|6QK=H<3ZVdENX2%jW~&=1q8jasMT73zkQ4VsI-vFDp1KPM?jcF_LDA zOzMsG*pp}wt;saRFaaZ?2iRc>T#XnLSY{MM8ObqI<$)+Y*oeqLs0Okoyo@YTLgUD% zhlQ(?!c7X7PYUg0=bwJt`8DvTSHiDPl>Hlp+iy&!zn*OBh*p6VVY4;zg;UKZ2-heL z!RCn12p*_xvb|}q2}e&}jmQM(`tWrgvoq~^AYap4ke$WLhkrkl|2IZ}|ECMcU;I!x zKAs}M{-PaDk>(S>YO97M2bwV4ThuU6K2rM z{JC_h9+es|~i zE9+I@M_+pVL*S1wEZ-FVq{;7}_QEm=$`0N44_7T)BNG@k11Oc3a5Tj*K7u zJ%9T(yzqCjiEoe3cM*=qe;r+MeGBRq}PFQ>@s%ilbwhjZo5o$L^QN&34s zM?tua<@PPdYRh81qi*aNVG-9vzTFS}$A1!d=biL*&+X|x{(!uH$G3$){nDDdh2bm+ z*Y^$or7^ToSPq8Q50s0}u(8SwrCc;k*(4 zc`tn2nx_YCJ7p1sKirDE1MI%9oRgk7!|%F8JYCZr46nW^lncW$2)p4o&*|JLf4Coc zb*}tqbcA>K6(j1~7_Pr*`NdFRy~A!MtfyN{RA|GJGHs}e4w?Y(hp&?b6oj`%!@qu8 zxV{wLTjbaKL0AOA4u*pr!`WbvsiBI(@k|(^z!JR4Yfe5h*7xiv}Lc|ZNS6X;u5 zuD#-@uNI_bjkVWNzDE+rAn!BX+-G}lMf2IfoqK^h#IJHLzheA9yDj|t$A;5haIIl| zRXA@9*LuSw2{JVdg+(q5LoF0Z@G3NgA*_XZ0{sxFt3caDiaMfI;^O1TjUsWhA31+F z@t36EhFQ!rE&NAgeMq?J3g*Fdd)NJdDhznN1@=uS;=5M z!FVn!&t&3QTw1>Sisd*P9|r zA0zztZyNsfJ;%|7<6`32-m;X=;jL%Ca2)Jgn5pK2;dAO{lN3N!Lj1 za}nk^3i`$(t--yT*LS1ICGkhUeQ({ftezjdCA@xDINMmdTbBK$<3dX)YpfPno9IKJ z2$73wK=%`Fp0FX(#K0#j%S(>}w{Iy&_ae8^Uk7OV!<>))uBiHzlXwdOEdR?*%jHHm z>K&681#2DUU|`a zQU$l?SzK;o+XG6s1L8?`K`jrt)Ke;Z$z`uxZIllOWqYH%x_qYWrAwyXw2+c>6!!+Xo6ag+wuCgJ)>n+CK^*!_VQ zBHRbKgg<>#;a#hDhyeVgR1Qs~*$m9hr}Xg-gCq)fAJg{4N#gu7<>1~wSjv87-FGn5 zSo+%nOGB7DiXbeeme^WO)G!mnVeuAfm%t`quiBisZ$xQFOa z;(U*h4b?Ev1mWt{d~R<75C4%4@GFl+5MBtvQDJdX5zrLH(AHmp)leHsaEgtc(gC)i{l_1%T?#+!+UbL9tj3`$bL@b>uIcQ9}p>IatZ zZ!An4iycQ*S~kgJg99uVrbg_H%1me}Ksth7VTL8sVZ*9X*3R%k-E-F}Jc8Q{+(GyO z%3F^UlRDDtz|cL$O;)&&sJab}@0qlbTayGR?>qy_zjIso?gPv32jQm=Jx7CKZ)ySRVH$()J#jK8#T%%8ho}Q$1)CaNUlIHk&hKJ|o?&uC z6Fx(m6;ccwK0k0A47+`Vd1O^6-Kp}kM~1LSy#AW<$L|Y&iSp;c%k%j?bmQ3=UrvOt-e_`cZo*}$|-A@g>)-AGucKVAmBl5TwT3bYo0;H4%KShKLW!mcq7%eVaQ0PHUxuQ?r@zI7 zj^bLRj)q64ju-<~9C*|Ru1+GRQV#YKKf$oPjQrVa@V~t;9K5Ey{uusxW4P5DPFu&; zHOq2c5^TY#^>}B&I3|9=MRSwFejDLCB)vkEV?6H@;(#eTQjD}FQ>n*G<@ZVa5<6y^ z07S0ef%jffZX6^&TxaKa;UICZRQ~WzWQu(#dCb@v1W$qE>UmcG?Bt% zV*L?uwIZrem>#=jFlRyxj^jm-uOcVjaJ@>bg7D5UJpX2bhj0YMDBSHGy9b_c9e7U6 z1f`@b9m!aV(y{KgFtUva&!OfGtlUKTltC6qe1O_1^Lj%ii3@e?8s$AzUj84HyB{e3 z(=Efl2mS)()n(%2W4O}7$pgdB5V)nh_ln_mp--{PyI<1d4^Vb7@Fx80dzRfGbX%4e z3d?a}QL!}Zf{Ae$3PR)YRYh<2u-EY&*6@+(z8%ba;^d~|}fxcYOhWkv-8VxmGR`jO9 z1;-%g*y16o24fq7mh`rwCPH5lRtfJS+uE~sEvwM8SS7Bl6I(t}Jg4j|614E+Wcb#e za=z`kQB^!TsTpid;YyM%km%S9LS<@1O9oqGbqcx#GR10%YK061?ZiV&R0VV!p;;P^ zqAOI~dmBR!+&Tq% z!|I9nKFw~NYEoO^}Ho1ixkImb{C%>^NyVZ$2lPDsTH ziJu}8KrfJZ%%B?%L*QbPsGZXJEDhh8E4TlCtn%bxf18KAeFu2+p&`9t(8gk-V^dq` zEfNIp0z(&YZjJPTSSrQ_G+iR`F~o=TdP!}2Oe_(%!(gsq%mKzt@VzC9q7hb&<+Clv zHH6qZnyKa5p+zdovM6xt3M&&-cY&LjxQ9g0=rB@(?jm-d#O^3L9V6yGMn1#Zb6gX^ zDZLSHX<||_Tnc-= zVJ8aD?HYb;Er*p*Of45{hwU8O>UbQdluQYJhBXs{ouPKdFdSg)bHI17@@=k`P?a@Z zEJ?#L-acfIOA1-x{F2yT;`NLaFVJF%EIaBla#kdYCgM(%-AQ8opA&!n+l9BURsyp` z&Ilxo5!8ADj@lKZXn8!hm|;L;!Xn<=(d=)t@ zB3C7`eKYX0C>%bBG%LgFTf(C#umRsWOz(JLE2i@~ve~0fbF9=@3))-C!VtxwsbnHB zt8(5w)f*VM1zO{+5Ys?v2Xx-kt$QSN%)5@Ik579QaXS$c;m)3uJx%5rr#@SssjDr6CXqr%-lXS-YIYQ{yg;A-4(JSh9VqUrbX)r-XVU55AyP?9*o@+rtUv51&{MHiH15(ITXDJ|?|JAr-1Wr;k6U7}f+U7+un&9iT;%FoYR)GR5kW zPL(EYp?yh`NHWS&lof6HG z6rk9;q&Jbu2T~6yf$g7cx&<+qO0cb`FO(#TBeL!y6FcBhumQ?7esjsZUgHUDDu-LW zjMy6_?h?~O%InHeKcnzhknkcZZ(!xSm{cQtiby1efapMy6HL6%<>o~aAbbe%m@aH^ zzN3*y;d_w4jt_J`(rzr#T8d7%AB7iwo_Gi4oo8=S{Z2m?p#YS7`kX^rW>}q zBVu|F6LtvYIn^*=iY@x|Ju3Ydys`_0fsa=IjAdIA-A@r&;PnHNo@31=>d%Qzh-Sum zFnE)wQBr~!14WsrB8Z((>rJA*O0sWY(jkyY%rNE%QAlPN%QlsT%7P}xnnTn)#1(r~ zF(QS>w*hORb&7F@qPDbyN3Bo-^cCU`Fi~-|bUsmM z0*Qttpo3@IB`#8hi4&sV#+Yktxh)C{i{WKLIKgs8&tnRX80>^j7eo}BJ|yxGn=Y}T zhbGciiT&*!=($?=oLm}K&A<)U@*jTQ@xPLUuhypitq$;1;P{(fcs^OymBH4E9|qK( zf9;x`3qc|Mahs(x*6kM3nm^cM5$^8dj(WN!y4_5EMxn z@QHJ1*RWj=^s%B%*Qm{P27Q4oUl9^?Dx@@EWsO4^oF@cm1%d&GAXHfPNM7-6O%$Ou zf`~w}^sUE?|8)q$7Anu-IV8w7k{U$LAw`Ufh$`AYLW-Xe`hwovr`ujp508j)%4}F- zz0g>TRZEQEG-86GtYFK5L^#nGQ2QZP9+7l`b01-b6GWAij+#e0u(Xu`R9Qb zhsfDSiQ+f_Yw~Qu*BVlB&or`h2jQSKyj;LNZ@D6tA?+ag4U)ZqYKxb12EB&ik2#p^ zvgKhAFd=uHMQRE&XAmK!B|fbP>JVq~`aEIqc+(?RQ9r?^1B3~oTB7k7Cj)AC=yi^z z!U-6GE>1+~@jfyYxXVyYY!k{&{IaUlUdk7YrEMf(99v>}e!H^tI4dSNAaFwZl ziE9(+6D%8OLk4I;p|dBXSb|wYJV#?gFiX~en*_?0rSOK8DA*2kiLxOnR1VApPQpG$ zD-Z`M5MqP3J;^4d-(Xx~!<1P&CC*nYHii!PMIHEQiu45DCH!M%EZjdh`t`?S6Xy0~ z!}U71GOrnBGdOBJfZ`8G;dR8`L;YP$*hP4OiNIwK%hPOxMGxM<5TD1!1!^9lLn5X* z-rb~4-vhG`^tf<>I#9WaH;x#4#C(97&ybk#ng}SJ5kw#if=xZf_5?NDnAB`l5E3jS zT!ej;Gt_jz4la2N4)p>`J!sFEy7V!nF z{t~IS5Y|*_iDzKb7ZjzkN*+ps?^*^q$At$hyVuz+vl9tDh#|=q&Kc@7r85?nHuMx| zyw1cZ(ft*vS)z8$YsEmf9Qf!#;IF^hP|9z0fTxo-KLYODHeYJO82$@}ZO#0a1Z_Pq zNf9v>MyB+=Cz>_JyvL{Q8^qKgx9t$;5TOMZa)?tZgMl^!^YC?TecHyYWTc~%!gw_{WlOVKm*pFV#5*{ z{u7=11wOU}I;4L||NRO;%=AbSiH6X(dgLzCR!e&g-S0?#y*8^@~-g2L_uXze#x>WF6tW&)LPA1`UZ|Cs>`ZDh=v-Qg3mEq4yp;R1}j6O@eSjBkxh` zX>LEsDNx|T3wZb6@X`cc+<}RMPcJ5XdI1l;X z$OEETVq9Ws9l`IBLPteQv1Kp~Bsal@3B8$Mv zmK%q)jxHJ|y|S%=OE;jlq12Wr8%(q)uh83@s5`>y$7p&)A1{~&gV-6#T!&cUEqvYq zXW2lD9zNed8=>@IEVxk?wWc7&3KdT)(8O%y?Fx1Rw6SIpufhlrqrj#g6H5Y>oJkU} z9P*i~$xh~6c8;lsS&@&~L})Dd0F47XDk9N??UezGm?@DRYGY740UPOvNN;iV42d3N zcd_9*eRz{fD|#Mb(?i6rNJK0i6Baz)T%l7qS>@jNum`_2yTMzvCRODQH3oMS%uKZ=i5F zHA<2D111K%yQJeBFI(*SeHQU~V)9s7P*e|dqb5c|+C`Ejk&S)Q&kOTx+@D_j9=(2m(<4F*sPvc+&@y36=GGzPh(7IMNGmibCt=PI zAX(USVC)8$l;prB=mlbes(`wJ?EyLiL(K0FA^Ud%1~RaNT=Q2wY)#=tox$chLbN&M zdh6_jg1qc>>zrT!x>z0V133T9R+=V zod7scMl)uD^t2XVZIdlC>ZA`{0tecf_VwmLyRdw7C3o`lgISBAvu^67>b6ZONJh5 zfx`(r+*p>~6cY^u5VxW8Q0oDEMNY$u9?m)l;S8q_h>{3QdDLG)F+fWUmlW25&agHs zj580{3)nAngkPSILa1c)E(to#fKthspa#Td$GI|v*h9C5a%2P6KEoF1iQfb%iF}SzPnQzj9@Cga92}S)O~-6F=OXOl$Fv(Y5k=5iv71O) zED6a|+FWbTT1XsW>g*2wXP4bJ^%aff-+88Wk%GX#-DoAcl;yOmY0Zb9&3F#D-$8@29B2uAr zp+(9Ss;4abU1EZZ4vZ>ROG0c>X(66q%>T*Vi$4N|DDPwR43!Gi8e@B6TGE;Z(S)Rz zsLVIHwFOt|T!(k-TvJuxVt~^YVi*mdKy9w=@}#AeAlO{@t!Be+B9s!p5h7;WIS4g^#Qi8e+mgFTQRitzY=_7C}RQD<6o4mLU-=0BLWx+@Wxa?pvWa@O* zz@F{d|DqK1VD?&I(VkfHA)s3o+#lAIw;u0<0yc>e4=GAZ0CJ zF!@*!P@i|p*&O9=H2gsg2Oh4^^WQc-9Iqj@a7q4qC)tURamxk#SaP0}lsyMG=P(6K zpB?O|6-VWukK^zpJuzL-o2!%peY#1~ zNYoyUYYMl@NkhW^DRi3e}1&SVA$Vw!dvBHBEo&&7EdvPf7RtlMa5o4qx_kqI z1+W5I-(d8VE(8iW!Ndw@2PAex28Lvq1qG|9Ryci`q;F7jl`WTrmh}Kti$$R*$y;osKEpKO%XBiQUH?ST@Tgc$-`-5T`?+pY=G zQB7ee45m<=_beKR+rXrbY~ns@USL*cWv#GTY|&CU>E6K7P!vm&EQz7V>XK;havrxi zJNXuHf-yhEnV%8$0VY@+59s2Ih)@)X5GJJJA&x7=bcJXw#u^+mLY!p)D0#E(XyIhW z=-2$2Jf#L-ID({{8SI#%i}(eWC~bD8Vx)uKK{*+-iH@SpkOAN-jN=)jrVvvuGpm#b zLBf-nKY?=WKg|8OmNsh+(PT$UHaDR<&F^3KaNaK{>?de>iD{H+4dGOXd%}BO~(YxA0Vqr|4C*b2nK(a!|!JpJIQfg(lhB+%-B=W}9w zz4)Kz@8`R6$8>Dl1@n$U0X_CuUJCfF%4c4#^ynM+)^!54~?M?_x( zj!l}g=PQD1F{vfGfME`CLbM5SCQHZTRS(86UgG^lB%?WE)93_AbHrb?`E_BSQP7dQ zBe_Lt-|Oe=>LXBu+z~HMrOt1)$(&vbMk0|%CVNDXH>fvN&iQ6!JQMqv}{NODE@1$o@0+k;j93lM8c=>yE zuI$Vc#|vevR)&K_+eT(V*^UNhg$)n}r8fy@BVq@_u)w8vQ5jgpKSbL%m^;{==4@~< z%aL>M@(rAR%pi}D`6V(0Hk{!40Xy_W>A(&I3o$tyOG;DWO^J2Ts>OsrBVgiyEju(! za7G!_<>ZnMEB9?Cj@e<7n| zbzdC2A=i960>z2RnP3_6Z=oX{)l6sm0F8(9E~}z#$m#yF%iwkuG7uaTteheKBT{-m z8PCBbHbtT_%63e|1)TN5|5(D^FD1C&t^@)f+*axbFfA0n5}IRS{+&d>7FfYIhoI_c8VwU3wLz$Xwe)6?45avP&`!uN@jXirCWDEgA+~ z*W&ArMX*f05{#qM0`DTjP!I~s#BR~2L!7Nqtq4Pfk&-S|c*)#*?lS)_eKu|zq1DXy zsxf0O|*S36=}o~m^CgnB;PPNMFu4pC^}&=GhA5;-+o#7 zH-Bs4;F;zHG6uN&mcTK5zfg`o5pL`#&GWzlie6beg<5b%+3q7NU^WkQVrf;G3<=6a zkbyolI4%%#gz86}x8LTp8UbE_$7@J@grqa9tm$Jzv@P@0fN5!ow9<2Cgvr`5?0_P~ z-cY$ftsd=eWB8|#j))_ewA4hVxdEiGSHRV2?(rvJ(d5Xw7+@W8CQ!|F{fT0jMg_3# zAxL(V(!f>)FHJ#qGfKx~qe%~?=4W&SnB%OX6PQ+6AnJO!_%a<$xiqCwYF>vta6-rq z(8v7V5VP}ilFN}uAUZH1YyMFUlV}+R$4)e?#IZSYe0~u4=%Z(10*mYBF9mJNO1(@9TJ4h%#N3*l0QSrWEep_^HT-jRlFr1&N`YhkU= z(T_E{82LFP(zj&Jd^pLe`m%so2WFF}h?+2hG4n-ZypM3+!u#hLAEcCgUO%81j#6< zk_?FT6rCf8r|^y#JfM*oSFCvRd38fNNo}JPV)`myUQ*ZKgN2~;wj_BCsN|jUX#AnpJ8pW4nG93#; zPVw~3DUS@3EJSFW7~_)`kM1-w4AT90oH8z7&ioWn2=}u=1I1 z%m!g)gfM_gPjr30@WX=YlEgi%M$~Tz_6$EP2xbkYqoc=^Eq#*^lUO9fO&n?tA?>4+ zj%~MMJs74Yu+m6r&IuuR)QTdHP$iR{;Bu1{!3zVQwGbTa4|&t$m>ueT0nk%bP)30$ zjz*MG!xxi{*GEP!_Vhjy`E~drrAr*0Dvl*(R482>%gZ>CG`Db2=0TQ0;dBGieldsO zV=g~NzW}PD8OwB`M#X_KL^Hvd8W}1=F~toDaf#(pnQ!1sh1-*kzj;OZgI@}76ZP%i zbOQGq#_y~pEG=#-Y}JM#3WW&4XR4zvv2iWisiSQjedS;Zt`nlQhz>;C;M+*>0V9_f zEio~WLd0l~x|Y%e+7PH@po@v!F0icN1)qrV5L^8Lntl%xKc{zpi<%3fbI`Y_e9H0g zfJ?o}e#{$L6)^Ofix1?!fJ#=}PRiWdcLq+oF&f9r_{7+04DjtD>-)xyR8ezt=5Uqg z1&HH;=?fkwqvUJGSp+0Ihe%$FjDk>+Z*RnY34RLo*lO;E+-J}y05N3;B4o!hBQ@>g z42;84GK30cib(@0L}I5<^=$1#sv$9n%Eylq*EhoVZw(yXgSSZfYZr~We22=>_-1XG z)Oq-`GM3O-ic*ll=X}I*@4b``0Ns%i(vaP_0LB~ zaAW&-1c2d5x*qwxFD^CQgA!UYvIVV{q#VJm= z&{z<44?9c=V(FT|CME)4qhOymY=6?iL^;1H@F0>!!lzE);5OJJ!>kvY+R$4|Wh~Mg z#2aMzf=LcZ2!&9SYh9BPI|MGitsVwE=Zh{;y1Z$UZ$)vxC#P7KzsLe zNVIUdmW#`4_oFhXCjYy#*p*|hLkfQ`aVf?a{K9~%vuOxd2)>2Zje zG|nVU?5Ih|6X78XN4oif4eai~ZpiE04A8smXfiqu227tDZ5k|&imrbiiBkyBn){gH zJwykr3ph=j4vLFPy%TwKsl2`gcW=V(gVE!kIKW~pSfFwFZj)6h2w8{pUow8<4E2}P zD>r6?qa@5y;w)uvcD*u~MDPQ<8fb=sxffQ!;YvtDWI6;o5@kr-3!bV{%H#;PM0|la z8;1Tafd@!mP|6hiHDdZFU_Qmg6FLb^Um zKIV4udK@w>EF6w_B&EzK{CHhsieJdn|1V{4_G4Reo%#J%MC{=Vd2+aO)vbZWNg`=Y zG$l7|7zC_-?FR#Dz<-U3kNq$B9}plucR#dkbO9|`mSswo#ZhFbZcTU2;pCb2-Z3mc ztjM~TO-fA_aFMsND$hB&BVxr`-}=69p+e3bPI^iaD7Vr49$kQ(zKn|E-JYokioV zK;$mP-Gy=n?We>zA^sN5?T|*vIEt=lgQ1NQVLd>02OI_OghEHshLV;f=kPVOw#80s zZ0w|O>jL*!6+o@guMhThCKd(ulYvY-wY);={om9_)&#q=7XfZ}h6T{t##)aCId7un zE^e~VOSX-(3bjKiR>`dE%^TH0qm)S~>dExX#Xzd5+@<8-CglOAbA%RhVT#I?OFTTz zoDYGMZQ?C>X`P%WI5nj&K%oa zL*s?G@Z9oneF!))$4dzr2AH*leNi@@M>n2s>2c+Rz`IPNqmgT1%cAMo%Pl7PDz5w< zKHdg*L6L&vGg3}?Q6wD5`IymLtGMW%Qg&!acx^4sPCX(6k%p}6oHPaM6I zdG<5Uxc1!tO5yK+A$A2UC*cra(>Z4TR~J9ELQ@xi90DfZp(lE*;!C$h{ zJwqPxgXj2OX129x{(qVX*jie$ar8lGe@*M)CiLgY(>Tv|?D4FabV*1s$c}I_8MSHj zlqS&Rz<%l>2Yl~|;v`%;X%M6LJiAaYoqm z;M7xGK+6(sBTZCPEcy&Qh(^Q zfE3wA$00hV$-%b^-}`|C4zX(f)DeSF-BB&%*V8{FM^l8Lj^sPW^kw|?Wza2U_6uaX zWYmn40HtF$v^Z(#yAH`qB%5Aa-5%d<%}*dlQgO67lUyc@h126LyWxhM?~tsBA5gty zD36))9aJxA!hu4ME4NVBQnbN`ks=3z?wQo8lA<7Tph!z84PIKb%u#J2_slwY(8I%} zDUu%T4NJg1VLN~ilNn8gmP0(I(bo6^m2&RX@Pbk-jEAvi$~otFy%`hMs0P91H?>H*M?$o&}9tAbO8oxr;Ai#bI0j#Cnj5le}GP2yLh61fPX4$-!Pq{yKy=vrW&@x|f9Glhb<4Vpf~xgMuaD3WZI z!ZAhfQrsz^XnsoePsuvcmOa{-e5)yy#Ht=CElC7lGAcsn;Z6&8I}7~?lrkb*5N3Ot ztmKS2qM=ObE}!oVD*r-0UZLk*hIy=u-oMswj`h@68u&g!8tr-sVwJ*CSAS+<)rVYJ zf|#;J0=?lHUR9k${P8h3Dr$0UD@j~yj=vMs%zksjVh8OUO%HSB8`yzo;xT#1bwIP&h7m(M$AzHZAz|U$|@u+Gb4+XZP z5k;mlQv5lZUZ9$wtT-Qkha+yd4~kczc)>YEFJM~ynqI(=#6%b?Xtwez$={G1yIQr#q2a)HfyT<2eMAVWA zHiLj94mhB)A%qufr+chh17J3zm4QK@Q~VY;PPkr?tYqJibHl8I6EV2BuVRn3Y7B2W zc}=bjqwcj0kg%(@aurHt1|5>o&NczgHs_dGd(! z8q;O-Jov{lsW2qyf`8ajW~Rx_>{>i zIGrfYk#tANBcnG44$im=N%yF~09}(L;$t8ON0a8XVwi94?fsUmaru3{vt4}c)Q>fp zyCE86`&OwP%3NjVsQC>Du&(A8MJpb$uMo1BX!coz7yAJp{(_u8BkN1DJf?HkB)P)5 zJ-NI@^a#&^SRQc{K4mA@bmM`s$;7rWyHGv_e#`tHU)uorS2utqe=GLGm+|c-i}ooS zryMk+>d+~3kOo&99;yyia3W|KP?y=nd+eeCBDcIjqnhD-dWh&PyqnYJh662amvFg( z5*R{9t36rfgwT_8j_Q&^z`KbQ3){(6ki$V4kU zT&e2d8y#S3=-h!6Cfo$xHIN)m5}Oz}c81Aku@bP!1`LJD;B9KHk2A@;NvtfH+f-sl z$(F*jwfk6V8(VCS215pau%A7uo&nDW*v5~c{G1_u!n}P(8L#O46`J=1J>Z*5Vt#_= z7AFJFos-9x9Lk1yPK0?TOqs`5g_EPgpB*XReLVs+UhCy_)0Y-bowAORnZF>%Y^tEW zV+@|&3yp(3Kyf3&GteKCv%`50`U^CVAaFf?jcH*(hp$#E799&oJiYg*6GrW5wGiv% zk5Z2CuFA#ejf8?T;)UC=F2@|k%Fjp%bys*9aZym$QHn4*@KVr5=v-nu39S?+b@T$E zHD108;D{VjW7cxsF_szLbqu1+!X;xlBPZ+MuSb}oZTzLcV*VOVzN?!cTZGw67GVZ8 z3K*CsVOBK<3jt{%?u~}F0gj4of}mAq#+Fn@yf_Z~7Lmf}BfV^CrX8D#KQ}5wod|x% zIP5u=fy2?nV#@S6^W|CQ!Exd5KY%}dJpwf0mlK4(MgSHgEVo*hCEj}O)%oPtmq zrQ?96$MzK49jYzrUXUfx6vxxU*El;^J-r)@9qZ*l))A+Led%ajgi;u3X;X)^bHpzw zWd>@b2bvjaxJe|vAEvQ$6{3|eX zDB#6hKh-s;w0I{3RkR2+1LO_sbj0jnSI@$mu=Fmloxw6f8ce2kkXIeTsd@^~$f6Xi8CAu+=b zJ<>D;2bzUgIs&%|@^$9Tf<^TfSjUd62b>E8J*FV0@Kr^V5=99al6agGBzq(%IbCy@ zHay)Q(Rpk1WOqdgii8>H91+Lp8d|Z>P-MgPaD;QVh_lwfsZBEEZ*hIoCAH8#!$6{@ z*72!w|E5%FU;~Vmdk`}`*}>zrMGRLfh0dGqFz(-FDjh)-S4Jj(iPO(vcxum(i6W7O zkEkTBat0zN8Ywx|#m{`}xbVM!p!_*1@1uc3P__!kHyyq#G)342N0VH&+jIo+q~s{s zlQaEC zF7dhq-=opd^@`s`_T9umGct?ZCo)W#=TjnV@)wK$XFsq(67o7LxDATBLJ~nnEB|`n zIysu?DUBy2kEDRQ4xP@}?^m>`C!jdLXDTBu6uc&egJbTE*JO&OUr^iyA^Zf@8BcaA zT)UykPthh5N??nybb{oT=uZfAkUMg_AcQ4FmxvrO53gj@Q7mgduCgwta4~tFZ@-53 zg6amRKX{6m_?)P1+^Z)kgXHA%eJ7gO5vsqrR$$;8-AG%^ufrj*20PP9|zc$c_rm2ZEs_`fv4HL!1##YUkk zG`KHlZa3&(=*&BGUmTsbq;w0BcX8=$COsy|o-9uZ%`+rkL4v+X4ADaqX;sM*K}N*A zM5M5RaVwh1N> zslEfb<`6gBK=qdE%)KRxv0f9qO8(rA1|1(J$ngp<&nfZ*X`kWBIc^vb5~3|#iA;Wj zq$NpDm{Lp7rxZS=%`edXj^GEHCQ>vKBy;tma5T%zmzi()%)k4wvU^ncPro`iJ8iGi;KhX~9S3un@xN@YyrS5k5aa`8vYy5#%04FDU6Jw2}xiFleOBup}~N zhtp($Og66;b%oM&3`tQ9=->(B2&uvQ1-Z;AfS{2@6dNGK@3OOCwQ{AyD{ae z+;w&eU9h{=J81j@$AZP8*6Y>qVLLt`d28)yb4i{u-gOofy`prebGXvr9So%2-{;KZUnoa5 zC;8Vgg9F=E@db{?LJY!`GxVNRr*O9uq~w{kp6$LvC7Rv?q)$saw&|BYFn;A;)dY-QKe4 z7kjvj%BXvSS0aHx{{Q90Bn>4#QxUGFL%}Ug>;6WBFpRv{zwLVTujGIlNa=DxjHM zz?DLBJ*{g{>BzdrYhlqUL-M#HXdCdvsD2&*03ZNKL_t(?io`d`%%Q(tVcg35N_h?GXxsqYHC-XIcN9Ih-uvcxI6Bp;$S1Rk?e<`VOJS zP4rV`4S6_i?Q1(&`*{-sNfjxX)*UG6KrRPj*pcIe=NBAeL+gJ);Um2N8F9SCO?&q9 zEel;UXW}v??#&CFB(8knkTaJv<-Py<#P&cwE^OD16JHoM!po4EYa(>QI0iI3dKKf; zH-(Z8IDLl5PnhH(c#qc^nH4IYi5a+&5Hcb{mji>G;qpT=-z50oCglf+fEQ&dmw3O$ zr#198NTq!B)d}S8+!(y`#(iZIOOY$OGaguCq-W zIck-5k=b4-Z(J81+`2*f{;Ol-0>=yG@j+Q`3)%~doiLjht|w*g3p*8-K{%fr^Aw5h z+NN~n1yUTsUA(ra&WQO4uMyWnQwq_y?4~n1?lQUeaOL+n>(975H@eiW2&!l7${EiG z*y#ZJ1d$1eEsl{=u6Q~2xI>Tl3vkzDEx6z)1%gIALUbpryr=7{$fNcMcFFAF3YK~A zqal~-1Sj5L-~#Fb!obs^hf>L*)voq-2k#!kd-dMmOcvUk>KCwR?BCnT7(a+uaP_j@M)AzmU`N5(KQ8@9A*WS0`hOkBDM8tFG9rA_D|(f65? zuCNbE*%X%7`HPu>cRo=5)N1{IegmBUg|hg4WjiTuR~Wp*<;*@5+Pzf=0Q1H|e^Vw> z8BuivPEp<<`3=Z3M4!^QNFD|zr-<~xA2P|83GSMr3zoqQ8ozXE4Cwg5?OGi0Z9 z2!)=U&0^lEKo~gW-ZTUiww|@7KAJaHep28(+j|^0aJsa-U{ZMO?A~u{TURUTa~I$$ znQxH8bp8};`K}yX?Y}}O{}-tUU5+%nf#OC2d%AXFU(9=9r4#Nb(@mM(ai$H*Vo`W} zZYTddDBn6RJpDkaQ`mnqlc?jrR@UFKPkppYxCFzP@olEbg^d~?O2y;G9$3 zy#?&21=o{+KM;$jaDm2wMjWne(eMoN9xabKpT5LwZCUbz>Wi~#;lZ-9v9)2J&de>v zL7u@Bm&7t4ZJ}tP(E&#yi^r9o-miGGhu^(zn`_AM^R;cTT{T-M)#a;gK=P8DXLvu5 z-GDHWw83kOtIeGonR%#&QI`k!$0|DARV(|W7VftYS8y@aff7|8=)L_tR{wyjV$mnZ zYG>!ocuF!99Vi4+Zb3b}B$o4NV$w+2Cst+R@htMqbz<+8TW#iXf>@MpU0|;K&v(ns z)Uba_3;3%WU_36IuN}8uz~iOzRSKW1Gq+0OeCIhijmSDNb_QUV&f&Eo<|CGkow%hy z%=Z}cxA0CmNJBHbz^6otA2Rcwu%Au{z-CN*l)h?ksTdur>&-#r-Wo0<+|89J+1VYt z8R7ZRvrBIv{uxmP$AFK4iBnefgdR1On3>?k0AX8cc-4+&)fh)#GsNuK%YuDbpgNkL zznGUnTbnfQ#u=Ni3Eo59VtJ0b@G2xpFscq z(bpaSlfcI>gnPdQACJO4g{!ULI)@eq*)yL7G}X{Pt~lYhitZrl~F-*&>9>fg+h? z-3&ZE-dUd^I3sJm*cs1nSIHOi*6iSK^>C}T#i5EeH3yvYbb&9b4r%P3?o5k`tC{?~ zHy7_Wk6<~g;Q$URl+6U)kZ#VC>V@SUydFqz!|%NO^%YFHkukVLQDZ z`{>x?>61qXvx-lpWAqJe=|PSu@iuL>UGD^9zC~7pa-9%e^T8S`>)L$j zYeVJU4DQZqgQkixOZETlY8iK9E7R8gzBgsONyh@5&EVk*j#pR%Wo0WouXL}=y`g=n z`m;E(9>LwtqUEB4er6K1w-@%h0l3_skkSice#tiN7%}tBCKetaJXc%zSYVhbu~F8e zauSs9{0ttU{0ETlQNH&twu=4c_mv<03H%xGzfkz$UpQ_Lh4Kx!oJHPv>M2vhbQGCs zrjwB|?#bZ-NS#K4#}WL-L+33^;Z)vL~j(HacGH zA$3+;pEYp%#xkw5w(03)wf3xX@b<+)@?3Zctf%p%{Ckx#BBW~&3POoU;FhI0~^ zOld(3_DeSbR`tFu`IyV;7$gvwaLp%7nBM?$my?<44MQ*xr>$m)Db@6}GHMGJVcKfu z%;-^!%A>hZP{genv*RlEtg5A3XsqLgn!8tvIc_Cqnt`J7>-d_vLtCmhM^lZYYA+&{Y90~c`DpuRT@y#w%#m=1oY(kH zNOb71r#YVEHzP-~Lz@G$yeDraUNFMR$RkGn_}iIp{y>59>wEzI=_}xUgzo}B{xR&n z1Amp^u2=4i!e<-DZ53|MlUXhTR1NRJOQ#N8qD2EpH=ui@@y*h1IX-JTWprQqC4 zyuU!FV(!}Rk9c?0ac@zZD6XP)7^dG(R)&!+ly52DW&dp8 zd;_0vO+}RTl@KIX{eTwx>{qpQysM(mO|^i_33l-mO`aS(BsxS*%i!oK{)E9FaqJz9 zIJo0jwUD2BPMgAyqHuOg;hXT?N4)=mO#%ANoI(NK2VQ(%*nC^~0q|*1Zl5csCyD$# z@S@4+s^F3`#YEIXE73#?HPi)fztpJ4Vv$-(flwHsBz)R1vc$O!({RLfV-w-l!90ME zqG9>_4p!MFd6i@s`l_{!A zyIyKna=M2er`mMiv~_dTlB7}1D{$$ z-P{JW6!Ycr#yDu)K=vb=7RK+dPT#?s^r}=hkbQt*G+EYo{s&Ry1*T}-x zkbhL~{2RNN9SnPTGT6y375vc}&9YWaVI5N^6#xp=ka}BR_N22ivI909JlfvpD*m@P zzrdAqa)Buv!<3o)5yY0)Wu6!bRtJ34FE7yp+O;Cbo?*jRDOk;NQe?msvGDZoB~<+vZua) z@y&qKbN1Tv@n+60+QRpZv61`QPQJ)+UYWQzwy`&c!Hu&`eB;jHv|6{_@cZLyYM+B` zf@gb^cgLEm_|}?MIazfPtLk{F$>&Y=k!zJP3x-YHUcjlsWn~Xd>pSeS!#9`s)S&4O zg@o#oMtdUvz&v=?&e=6|H?*;VqkQ5AZxicAJ+Z{g}XCvT>i&amjv{ z2;H8hUE{_BS+DTjilnD#evS)|xt`wUdbrJX=eZgzocGQk-Io)Hp5y$1INim|TexPV z$WL*yA?l~>(p_|aiaJZ)-d>oq_cmKgxdoo9_1 zHo#Sdnx~rJN!>uX*v}uTptNK&pa{w45tL*bK@`HwBAloZN3^1q#|!Y&En>dK(cJnG z0eH0iS8RutP$Hu^y5d+1w1Xqgl$V-$>r6SnR{rWU_@jS*69m{hns)-a^Tf%~tv$;l zxIPrlo$}ULI9n-4Q)cHBIVes%rM-icJ0?a{J8h@EC2U)u@H5DNiIYd{c*a~V(X?k& zgDTq8k>}UUR2ZTn&4D1+o6n`8giqO~6Sny-&krk`{*__kbDaBx9IkPCM({AD4)1n2 zHxhF~#c|M6P^;bFK7v^VY!=R-;zMoMN;QWTwYfbvQ$s2C-?zyIOnQO)qeUWCkVi9| z8gDFMn_4*(Gl1SCnAK>d)sxr-Lrt}@1XsOnkf2p>kZs^a)4(FV@;SaehqvaIdWgW^ z#ox!vQ_xKDj_eg7aoZoc&jSl-2<;rl+>)Vw zk4^)RTO*0B?1(iTmh;^eP+x_^_dd4t<^rtT+OxY})S?q~S!7f>E^me#y* z2f{ugCDR>yN_31-(c%#VH!7vw;nGXQCxi_07?F>e=tQs>s>t@~=+2itHK+eg|noXP0 zk~ytWq0h!(&&j}_sjbG)xjKwj*t`!G0mf*XXROuERHfwJ+55CriF~}U9IMIZw|swc zJm3EoeYcNU0E~%nm!%uXlTg9HC{@ZY4kA28~cMn0yD8#Ck&9ljiJPH|euMWLC9 z9LNgI?3#A^m_&;crAPyEOf2OKzTS=P>QSsB&6^2eYARZr;alCp(O7+fn`#~3x7BmF zwLuZCGlQzTd$=6FOiWjZ8zD~g^MUOcxzkM?x=6fC+&anpa43{><%91k`a%9LX9xtY zMn@|R<9H9}{{ZB-!0kZ)h8WhkY0n*(_+-i~yOEO%VSG#Q*ADG=#B@f;pOfULbSx>7 zNbVB!DV@I}q{zA%nW_1ycPC~xIYwu`{=2;0l5-4+w#h`U7gvoYHb~Rcav;ZGl%Lb zzE1{uhhSr1dn#{>-y)8&)H@zTlm?FUR7@lF_h5hXK`w z;i$o>XLB@?ui?euS>g(NLu7I8_~5$^{UE>269^1m znWo5!HG}(*%mK#+$|oe*GMh4=IOVIe!oweD{^N=8yX`=q8rtj`b4!{X6Z|dEcPI!x z3BKC{!VrI-#{U$JTNZu7JE6^iK|5S?%>U|od72D>H$?@kui7Ah?&Pz(ga*1UR>)`=OFVS#Cp4QBpYh>CGmIn@F$Lu=7Wv2aB;cHKX z?|pIERb9aKB6B=VM7_ZIA5zjkl0rn{C2h0i&}WXP!lR?YAE5lGi_Cq)zMVK^8-1bU ziWI(#Z@xoAsw3IYxn@l$9}&wl+9q?f7p`?dIO-UrrEiz`@oiMTP0KNqEfc3W-s8== zJ=`Y;_;~XsZQGE5Wr&0@pgA*yLTWNPBvvIcrk+#=L?_G2o2uhq+54t?mVur%-BI@mm)u9lCkP8<;|>ASIzWxDa; zse_p&vy>mICCtoOv^cGeD8#e`>u6fRR8_^x77o)fiMu$xz&Dq`1%n=uhXYL-naRNU zJDzU?KU_OL_`ik9bi`3Z%IDSZwu;@g4Ql+okNb)IvUI+p%~GM=L4h~A%)-24mE zW=bTq2gX!q370xJ3CK)n6eDMJLgT?@hh`-sI49(o@co`NUgF{<=etuLUE3*qb25#< zy%n5A!vRDsd241CAx;9k72(5RQZAEh)oY**Z|rN6Cy7lxAM4=h#@DW2gju$d&(|EJ zbH)ljsRmN}yN||35UMvbCh4bso{Zin^ zg+D|1%55RGE%&4)q!q5c&FJ5O^frz;G+SJHij!x!vL??GO@`dGgjtV|_bBc?g8vdl z9wKgK)NDO)Nau9^Q)1bnVPZcmxt=`Fw-e%ifcQrox+{Vxtrv81IB}?YW==S$;7R~5 zgxry5GluED9kd$p9v*?5Saj(+%L~GdHQNN2*YNX=m1Se4b>$kugBT6$!P4sYL0^M^ zZ#Hnn5L{EO0;)gpELdG17M0_0FzQ&S)-vaH@ncQ&nrdL_>QKpC=M^0on5iX~ekmmUL8}#Wrq~;GP`60wT>OUkPs7tiPl(kbV zoN&S@U&Fa?k<*uPZbr&mynl|kPw?}B6eEpqK(?qnCl`n?i-lW8lrc9e2v8Mg&PJO)&^o-9%^LZ)ewoBNgrCv zz$%)eE0#>=8;6u)$)wagp{?Ifb@~YP&sZ0lI-(}3p_8c!Go3e=kfasEXyJ5jt>_N; z?Hj^rF>c{3K^W!~xkaN#s9)jZoWad#x{jr5xY{(l7bgDZVTND4Rt3C|!uOT;QJ(OH zeHdWh1NigTp4ADk>4f6vHr`zRJ8rlC4R0)=q+5KtdyDmSMri(mQ44K%PA7qs9#XRc%Y>)9$Cuz}ue2VA+A0UNiL~)A4BhsPLA(|K?1eb}aF!Lko4@4JPu%&nyCy$0q%8AxZ%qsI3 zg{RjBSKr$k<2b9G#6v~xQZZtw_b@hAGG15HW~t%2h0#hH z{vKzI?OxFfR3~zi$x}n@0^$Qwf>E_9u+ar@X@SZTVS+HBk`Ya&*V974Ts~aMbrh>7 zG6N07yhrqkF27(5j*t?rb+}O&TcL|1Q?ipnFsb%=G+Nlg+r#c`6cO23J%3WELL znsB95f51=~K1GdF@O-puU@EWp1O7GFvV@)Zv64|@6{$>>uUN{f0hOg%&f{KPJ7dlG z8wVEyoa}355-kDEb(#ob5H!(f%2H-#a?y1}W}GF@GmeF@8C*h}T^6F)k~@BX;`NY|DEDb>wnE(|kyq4~%`mc}F25UMrwR#AT>)A$x6$bhye!CNLfl8>@(;NDl(B4SlOocZqiDNk zpFZM;mtUf<8F-rwa_#D%=r&Z)CKx8L>Wq{c>zLL}G%a7zSHl~m7^m;i+HeL}g`=If zY`v@0a`G!4;8=|y#%!F1sanTT$IMDiIB#e=x!T01Iz{Zt!SidlGntdfXIsk~VpT;q z0=@SP>6BbnC^K9ROgXUC1`Uof3h$j79#E5@@Efkb>Nimy&y@KxGL0kq&NFP*w2RL{ z6WQ$u~J0XcN(rXqpx&BU97Rh!A5YG><58V9i6sAJIhX%SR9CW=KRu;^-}G z&uZCq(%V80H{qIBC%q)NuKk9UudLz5HiB>JsFw;mr%DAI>V(o8W6K)>$<0J_t<^-S zHgsCY#f;fD;%7UTMvNJyUxxlFGi#)bGt9Pi3oT>& z>f&3#XCMuxMJ{%nlt;Dl{n6nY@NXZ9m%b?c#!=u;fFFL8;QMeK2i|N0ZC)aKLi8H5 z5x16Ay&&aV*kYo3kVU%y034J_L_t*XiB^|DO(4;yvg)umw{9J9!ftFi;(nWMucN;%9EUe9A5Qi)z#m9ca)$>wZ#lgVzNX#uW`ldzuqPp80}Meq7IJ_5Kh zxh}(g|082bBK*O`wRS`3A44!kY9cG9@t>38@8aVpQ2&xZ8GW!8i=Xpw`%S9qQWO6a z^bE}d64LyK8%dljf=YqVXn<@ZTX)VTdHH|_yR>OPBFGX;OC~wPc*s__G}6(BSVS0X zf$2Wcz_3#9&(Qa<4W%mA4Kvy|&O%9xvOAkl8cgGi7?MzSU6_F&*OoJAG|z%iHanQj z+JNa&8qTj4z@?eAQ=-|WNz|pOHS^DEZDz| z9dg_*Y4Ux>7^w0JNq1=K+uT{sM9)DBNpvpYYU=43_3rvBS2VYX(F4ZW_xiBh8gNo1=}*3&CH_wqNPk`&FH4PV#2H!;B`9`8Lwe z+6Ti_{*Ebu=>{7UlRC9z2u9U9n=IUk{tsFJekm7o^-?wnKaS2fY~pw79ooPbsw|ez zvHmZ?eoj{(vv8x53Y&x+%H2xrA^5WFB&S^c&@%CtPemOUEy9ixaVpdtm20=jsS z;dmyQ+ARMfm%BEX?%#_6K01NdyOP_y80SXRoHvX%9}6=30AJ<wx!`?0{i`}2GY&h_*_1Yv&1Vi#q9ZPE%&@D zCQ@~El~as!-yqLs)pqFwK8N|7XU+gu6EA+{-Qkxe(h0h{bPau07VQ#jx>AogY0Eg< z;V}~ahFCoyr!zcu?D@dsCULkdedr$ne};*?suld|#D9QrAK?e{gg<_-{O8?HXhz|F zuPj!|(WAh68HjBp#eg0-u}f%Z8KhyE8?zQQ{53YiN@GCP}2R*=GdD7OFsnp~30lWoyK_-b3CRFyv_=*JL0WgMQ< zgbf$N$o1ufZH%VLY)+l~AN~3q;A@lrF2d=1!re}IuwP=%c`cmnl-F(q)@@*MOQ5M) zJc^v^f?FOq4@wU#wPfJ68}5RKj9NyLBB~@DB_o;$80K1byUgy@j;(51^ z>N#dLd$H``{h3;I(iPV2vkuOZ<93GF2vKk%s~K0fu4a`^gVRj`Vwyf-vWbd`5PRBu zo0DzBG?nkHW*?sAoCM+p{(dl5Yc_oWnVk4M9xr%+<$T^xLxG~@nHwN8UHu>yjzgZK zip_0ro$&{kd_unr_cKVPn{%G2FBQ(`ExhOxE+1q1Q!)>UJVL`Mo3Z0aS{{+Oc`|T% zH}Qkhk>^+PG4X4Y{{xi!z_s@jI^nPOmEWs{w>QGGPTBQ=cTCt+5%s{cR8xnF{ckKu z(;jDO2~*8VBOYUcdsmPUDvX3;3hEVV6;-8lr#AVTYcH-P6I2}$AeN2!oH35rzSUSQuWiuTXw=v+l zmMWpjl~6=OS!|Cl;B*I_Zy~g_o7+rta@ICQvGmz+1wXH6nYv4FU}m&&@K-QrTpb6O z1*bfB6n8UMfT`pk=M$Xtj>u0De#xXysNxgG{({Q4tiqOM>^R#E>@|rWSI+7q<9$r- zy^;fX5rc(42LAQ?!hd+AoZnL3-Ut_+@?u}{5U6e{V;fo2k-mu>oK=kDK0|$-g?tMO z*HAfU3R@%zp{mJVfkMs^QGwJT_71Qlr_YJu91n(=BU0j{xE3&ukB9~847;poXn~1- zyutHWb1{`2@uCOx5ka=aZ`j}AFv961h+Wn1$GPcpK7#nqFrJk)7AhJ~m@Xl;5S(#Z z5*9_U;%NQ#Y<<%gW9iSfuuCUse2Ar<$V1NBH`xt$*l!A;v>(C37MDn)3l>dr3~Q$= z%Xq&unx30Y{xa2`(a6)4@ubg@WtU*I3sk;9?Ndyjkn?lmbcR=FjDErXu;Xd!ske#y zhZAcO_h5#Fy%GU@ZVr^m55!x_;V86=z?cJj=LM0_Z6Z6Vs5ce93aBn=aLEFWWb4i=Cw&hT9=B9LOZkC?vTY+Mnl z2e`MOj>yk>-oF7)UQy`!sRxUtMvO4K7h|rU}h|LlOy2_^Ap^jBK{PU$0T`zhUYjZ z^usxeaRb^TGO>s~`XEz3&D{Gt_VEtF4-uZfFZ{(biCtrF+MrE1;O;eHfYnrYh z)fH({V!gzDO-03&HdMNzq9fyEX%G`sD#T@8>4Lg3%!Lw<8v=&on1yl`L=drJq9r{h z576onCO+Q~zItUk#PBA~B(x+s3 zj&qD~Or1^`+bwI^BG&U&9C@uBdC_HVR>r@1Sz5ZP>$oHQG0MMuPx;BYG8_hu=E)zs zfOQp%>kT@taMpCJ2^vrhxE$bi0J_GtE|P+afhicZ3RH&(dt@5KSGX;4yFv7un2w;^ z8E)${w5mJ-3yyfgrFaM;g1OF!8@bAwq+~=UPQ=S+<_+(2)HAwF5GD3H$*!>(_bhu)wg-NBD9FFZwfb_^(v{DK@=8tVMNX zs#1wuQ$?%-OIgs%3YP|N7DzfG$O?)3xa}hxpt>frMtrYC0&z^{E|K)OXOJBxZ2`Q> zDb5L!PMGwRkWU!vQ<~|F&~NG4FfMj9W5;e9xosUU;>hqY!Q+Wjj2~S^f%tOwvw<5) zSl(kYp9CcU826R-=aeuK0v8(I$PmcwqK9}`udc+>}Oh|t^=hL!T} zn-2HX=S6TS5K(%>aSs1ygR<-cqbhsLJ;d)&hi?(&EpoU{^aWEoK=>xgKJF*@^tTXp zq}F7u-WP#?0w@Zk^ zs4c+Hrm#Z}bZAf&lYDVRF$j#{DUYRFd?>X@)>h-VTB8wNB((wb%xw3_hI z$U}$GV$|5OqZ&H8_EJG2Gv+4@`5HlRt{(_LcWS9mPVPeWFQWZ#pVRBF$J3X`S z31XtLeMZ)Z-$uEP=Y*zni063T;4xu#TwL0vIDc4wNpt-2}%-AKZADr;iQ!diqO zL^Q6EbPeH6)PEb3+lcpwZ^&VX`zgv7AkR?Qv5=8CRoJpeJwlFTjf8Bt817!80hHY@ zhS3bITUx+!;M@T7Ar$8?gu{uX(#QYTD6WklJ^aP%w?J*Wwjuty?6k2Vl zeUDr#sslm1FG~INe+uzhd)HtCrqb1?%sBI zVZ8r7{HJ?=w-@jfc>9$UF)NlGkx-H=k&=k%8Ny@mbJS1K@Pw4VM5}Xr%A}>^1S}<@ z%pgzkc>yGZh~s1&)fVw*O#Wj=Tj6}0H)a9FU!30|+oyQAC<0IfqJW9asvgBOP>Y%X z<|P@N>;U`*Dl5DTsu6v~PAyae8FmBm}9gC@BubcRM1&2FlTnZ<{io?Y| zOy5EDyNGQ|RaHLXA`TpOiSs1vHo^~I1%zCWr6jeCP8}StjMX$T$bkD9F+3#Mn!p!i zPLTX15}uOu6s=DQ(};&m6`U$G^ixD^LMlbkLYmjPtu;$%xg|tKphe{vi)$pk#xxz` z22-BUFclz(hXP=+B`yKv0`+Mwrj*-FkVIxl$k)KXMX=Y|Tb6tKAb)|f1$he#J=y*S zpDt+P0vngautdWfjQK`sQpt`i$GAMhWk=KZWX-fX;=OUJ8Ob?wmW7>-M0eD0;#lcp z1S3m9aC+`&!Z|seGU*M}HW;U9K10$87GAKL623C3m}X#Tz{jT8?XUnJnRrIcDW)w| z-*SF5@=c75gNX8Mh#Xc48v=ww0&kHSQT>vh2WUE_OY*BKVR!ePlg>HsooAKP1gGCQ z&3dHj&PmHBILFue6>R1-YjgVXssW2VUq*zS2RftKk zbM=ubZfD(A1NkLiwr}H7A>mV8cI9jrN>uT0LB5H^{|45R84;{N&O9Ktz~u%Nuk+Sn zv4?+p0l(PZAo&->{O>^@qv;DYIOaWlRS|iOrM`{iZ$cKbKBcxy3g=Xuk#dKGi69fZ z$~hl1XulQ zDS6)|T-WD2cfR&+x)z$3i=7@tld?64lXI*^+^)_z2uzKMk2CR3rQ!a2dI za5JQy&}pD0vA4;r>cnFa4qK;pVL2MU{2cQMm3;yORX(Aw21q?BQ}HUS_mR|NJfpHl z^qjF+x5Q*jJEyhGe$GrgnU6ha4~2B@tXC5c)4+|BiKEvie)iOPt9I;lWqlHOu@A$k zQmv2a{bMRS#U!Hf302x~zDjh_`GbY=lUEnOt$WVn_nhAyjgwD=XWxZpP-MvD*rOQQ z_ULNCXgV{SGdg87IaXJspsdEk6e26l1<{w4P*qrtNC>1Hh%WQ)?jSF5aa5;SV{bx2 zzzGD`Im;hWFJVy#p#Kxg5tA*-fHEN>xC@zBD7Tg{fhU^+;W{0jqx_VHhmem!&ha#2 z)yV!>(}oqM3bDcMuq@uHDt&v;^gdz3$kG#Q&5TnfY%|r7@rw!GK6KhKu?$u!kzUgy zG-RqFA%|PKZA-|{sY8w02%%*sTMn#a>@vG(#F#lhb~a6ByUg6)I>TO(PwldEEhG+7 z=5Mp{hh(}p;oiLh(YyaP+yqwp1^;O2F+ImDvw{zJ)w7oqw;pBw^2p)0j6eO*!w2`~ zCeVl96OMb~w!!)t*zIB^oVwR&ig?74s6cg?Fyus zkEnWLujv{4iEWj*&ct=gZ1$XY{@l2CiE?+~hX{|~3*7C5^NYaY9pTx&a=TN`24yoU z3llUcwK}_na(yWr*UGI**^U9}BTFqJ`+ZoUx}wQztT{mJ0N1^Ovb1JC3SxnRTZMRC zTERhHHo?n+n6G+s1H;9y$ojLvu3M&(47sPDGK*lOK}njByu~;{?K#_g#)0fe^@NTS zVVBu7H8GWh$>UoHZx*T8@D-9DKzdm0@b)^!l<{c9DN~J^UY&ZGdGwj{9pIC_z@0aQ zu#2zinV;Df;$yfQW$$kC`n$+_yTm_DV-_@p*&Jup6{IDY}Wi}NQ}manfe zxn8#NUoGb!+z{Gv{`51reP&!=WqxvK-2E_Lx{1lxfgnE+u6?T9?WFjij>@y|Dz|~< zBrh|_vq2g5gtq`cR-W8a_D_{`7`VQSJnI)!>xyVgs<1~l?n5|4e1(J+?n_8DXhpC< zjsfv7H-xHRgG8MtpM*;}>wTuuNEiuYMq?>c7E_~=A%LczWiPCt7xEC7QyvV_^hA(11E*wFCT6n39IOw z49fR_lRf2VsT{|^Fx7mcQchW*^#U39sOlBNcz}gHM9Lx%sjz8*OO1Fa)w7^87^F0R z<}F`FDTd5VBh7|uMoC!C#L#2bquw&<4)qq34((cE?AdiAQAcVW*|wSWa$@S8IAwM_ zXzG9+Hu$te^8$d;5{(YDjI2{G70v|=SxKWa#*FDe7&DqC&Q_Vz%DMXl*57o(PT5Ps zv**xX7v6f^X(xGUzy+{9aW0OXyS2f}c)WBz`Bi`4-}LphXnqfUnc3gE<-Gf&mn2~M zRUGn5ldIAizK`(k`!geWUI-_z+#k>9fA8)Hzg;_dr+mDxytNC|Hv$jFnp?TXv|-v? zP)%zpT`^7jt_UH*oCiq8Eh9M-q$AfYRqE-j zqnal_q@Jek=!StH6I~j4W0CmciQ&Pxvr2q<0kt}s6j>-+snA>&US&cP4M_#!R>h*E z*83i{M2H=!y&%|@&Hlu}lz6L6oczMMKR>5G`nK@bNw}7T!|0^|W5QaU!+B?3I(QN?l$xGxc@Q7^FXOh7H-qL}E6h!I2!OGxu9l@$_V z6G3-a9thgfF|g8>+!v^C6?=wu#Frx{CyATOiIcNTs4{O>#?Lm+(NPJ-Ll%ZCEONqc&`FP#s8PxhVn@7d)U|9><2{|KJP{~?s{ifF|1SKi;62YC&J_np*xB(N)d5s@c{RacHonA=r{mmn^0QE^8()Do9EN9+6o1>^3ie%VVH){G5<8$cV%V z8wZFziJoX3%0RmtSyvsQ8aSCIsx)$a7?GoqUp{eue?RflrNR9of&cUl{N8Kue5b5Z z$#I4(Y)0j_3Dfn!c2}|1$dHyqe+SWjhVv%wj|uWuOm?4oJSW^5m_AP&etY6iW-Y$U zXL$dW#qjFu*1Y2{xtIL^o&3L-7a*mm@->BsUn@2&2p^ES|69Vl&mEpA`B3=18;Orv zW!HeElCb&K$*bZ^oOL3|Nbm)k8&Yft9!ZxA!3Fm?3-4Us28s*0=v1y$aUw_$HX+uL zeBhuN7{bW$kce@l4g<$GGmnllx5#|s-#ooCP9-j!u*WnJZcU|yFST#m7 zC>IHuELaDtg)^CgG+Qt=0000aqB8g^d+LIZ9!d7hl9W!msgVAiwN!0ptJ2uYYJ=-(+nD!s`exzb5?Id;0i^ z)8`5|-!NXs{;}@!OY1e@55DmCTL?E1{uJSNU#^cI55hdv-=6_K0G^o?0Pc>BpU;e2 zw+p|IAz$yFf_04PE`s}r@0dK%f?3=vtKf2MsxPfnd;l6He*7AD&`K#7uAl$m; zIDDwwTq$=4&T;ck(}m6Bx+jHNS;$^x2wk!F(=UzN4(45&n%g-tUy1 zBD|Z0t_Y)R1`q1LUkZgCZybB0-zneJ3FMnE_BCPeJ>_&Q-2B2nedd9Ow~aR_|6e%4 zV~2dafw$mC^Dp1iy_s&p+$9e;OEy5Js6{NVFH3 z<(0(sJ6T?@*ZH*__VK!J3BM2ge6#L1&lTS(Pd*8Gsr;;0`dwi-5}w=Jpb^mey8b*a zOnzqMjUzBA+`e46b-R2WN0o21$$PIVube9Z+YX*cM7KzZem|2 z@_r-Z-$prnS-A;(uu_&Ah`a%O0!%j>^~`2t4sRQOO!@oKVTSNOzUsL{V2{9YKVnv9 z5L$Ft(9IUC!@xg%Fz_cgGPiH%Z+cIUjsF_T5yJ1^s)m2_T$v|fF9|zEAS&!A4+aN2 zusc>RfS84_G)6_})F`2_-4s^d$m2r#dEt6fxOo=77-N4q?K593?cCpF3w5xXr zKJ$L3yf`o1{xu{2HI$pTgllu*Pd-r&lHiljToK+~IG)bJbnH0k9qXW65m>DRiH=<$ zj)e6>X(?DLoHh}+%4{cL{vzD{Ike}-i(e0+y@R&BC}?XRggNTjN||@~4GACreFk*dOEg@r{P`L_n8gke3MhuPOQ@uKZh8 z{Cj5Qh$I8w3Io4)Cw=zXueo;R7RrmS3hgH1n?X6OUt-FyBizN&qC9({{B`H?Pb;sCl}BrbTqsQunj!=fyemvX0S`}Ih5u(qIQ&Rx zQ|852jo-fG3_geQ(-(}{8kmBv4J1KclB^?;IImBAUH0^)e18|mb%gT=j%5)pT@tic zCXHhp65f92x$-c$Am;o+__zwks2Omzp`6++r0IbqBReK^CnOYFR`P$RU7^L65? zCj2$wqebDVafW9KSH1DdPDPDBni;om!)tsgP5e@J|HpW4;<)*$@M8kw`<^RBxqqhg zgJ&l>QloUq5!DFAP!g-5u!_pfS!Deb{Om*F`3LYL5{D>nkO7#DjpaS#iX`UKBP9Kw zI31JH`-Jg|wiJe@aIdwmU77q49teuHoH4luuCkJ5&c!zXq3BCxI()a3S2CSC01Uq<}BM z|MY?9{ArIrYT5G>;`9de{{-V%6vfKBWcMD9hr|ft6wMheE3$UvgSgT}ZvHvZ_2aY#)QhJ9Wl-4b4$3;*T0^1q!2E;`6`02c zBKW4@ETJ@Hca@~yM$7jod>df^`D@Jng0a2Hf(J-iu{BNPnAp0=Tsz48*`4yMsx*#h?9JQUk{wC(I#VeX7nrDq$2|gzeC}Fx}5p;nGt$py4BNX zVHyh`6=P>VbM(`~5C3D)=}V~f8O#6CtHPf>@KA)^nd5jFxF$jxJV(W|>jH7<=-UQu zw-CQe=eC#>M+uouI>-x3@kkk?Y=Q1$V*tyxS>TbLe)!rvka)q>vFjBSc25xrCM*sJujI#t1)w7J?SqEnz;%M3kNRz{l&t zle0t*?7UF8I~VTWgI9*kFM!1h%B_dS@gTg_DNjemwj9?Mp8MLsIIwgL(kf$X5I-Zu zr*OQ8+A|aylm|F_n`niJADA_X`_4078_P*8nWlFguWy3)rx^dk|DO4i7l6aWauC)< z*xfO98e`|jng0XhH30On$n-gn5ne;Mc}w7-^5(fPipuV;qK#+wnzEh;;<(|4b6i9Z zla~3#HqNesT*VKUh#JVLqxDB*d4z^FDFW8v>p z@E8faaXf>vN@TY{%g2bDkZl{6k3a`naY)%GmS-ulOR)tpeTufnbX~&b#Qwy%yYQGx zoYUc&!a519SDw0*dHY^q{ypQ{Cxv(C%GepR!SQIzaeX^b!U$Wn_@-gh1SpD+fo0mI zDOXW_k!-((=oVJq#_|%8WBPbbVc=khoNpV83~ggP@jc_M3*(<3IPT4iKLB2w7dV3J zNx1ugau*n$G2VVb_}vDsjVrw00e(KKPH_7+{N4rujz6i-_dAYjPMM4ybLTicZy0w0 zb)HrBm^HX=3uz9B@fmV?9+PKKX~3P5?R~5WCJ%7Fr|<~NZ=>!WId^1vA8!w7ZGkq4 zGbyy*SjQ?8U;7Ol;4!4#n;ARzgngg~`k`R^=UD#{&|@-1T#vU4x-`P&IU0^JQ=|-p z5e#WWQwG-NnU}z1Y78OL_l}A084rm^z^9GUJOR%y3ahDd?HJylDwhrvlfbI9gvA*A zh*8t9CJxuN%gc2t;}F#*=|iZGW~i8}|%K;gTe z823A66qPf8@4@$gWl$y`DTKnEvrSMmh3o6eAC6xT-T}VdDRi*BBBX_57(4RHlN!ff z4wNB~+J;5n;6g*MGlCxC}6Ql7)AB@%;e>5|0VZ8AVJAnI@Rp4!4{(jcqam6uFGZHQ<13hVlTFPY^yu{RKV_SP-HZ=8S2E zh~S=uQBtO=T-|c)Ed$Yc4xe+h-g8=7+{$x2@hq--f_Lni@{>k6Id-%e!rJlNWnr`> zJj63zJ8WBF?TLM0QUXE8bTXmnlrS2T%Y+Ftq+CMWQ^fLpw!?L$Jj4K!%p&_Grr?w0rat@#z6OY6 zjo^$SDOo0{J&ktXL1ji~_n8bIuyiY&6oy=ACo5t$oVAqV@jAlUQ{?h8BG2G-0R08) zQA=t;yIqQREb=4DMPht8v$Dv1rR<9kr9p=o>aGy=2Y7o8&2Q1^ieSemTckWCho)v? zEff(%0wIqfPsyX6oCl^MGHN`o%Ph(m3&vK+tb?#?Lfb$#L7Xz|!7#vBjB&|yeZg5| zwan-^^S4XK_nXA=zK|M+WaYyiy1fi@825qZa?7whK+<(YuYuo%Vt84T=n2HDcoXBTNnvqh zxD4i$FdZS`kdj{}mM8H3ZMqz3^MNx851`~V(AwsK$H3MA0XjWLo z$d>k~i32|xxg4ixvUe;CW+(1E zXKegJ4cjsL1(dbmy`iRLH^P+(&@yye_}PfuKM(c_F6@!>Dd>BI?i2}QO7b`-Py}U+ z<(6EwV6?=Bj-`xY9b%XoPLOwIYq7zb&BRKJcnd`8n2fT zg)9XvC*bxec|j?LlNIZofoUl)6oyXmpBl*OdPK% z%Z?NlG&bOZK)j3_eT#m4&RPB$yKT>-u4Sv;#_TFtzlF2kB9|LD)|kDEP;lu1rVGqI zWk}a~B>M~zOx}fZjO8W0MkW@CO#+{AP2}ZC_?>aGpPJ$Z2RxC6W~0;DqW|9|9hieJ%sXi zbWZVdN+Hq)M=V>U@xVwXNRx?!5mI6_>M1_Zm#d&pfqe^jiDG+X7ElzmQ&2~82T=AH zH=qXR<&fa_D1MjRoH4dFrFDduSVpDwMw(P2Y~t|hP^XmG;PRE41#=H&Kte=)A?JV< z!O0329uedrjhwNHV7?`%F-}iui;~SDp=G2aV%h<&kmY%{n+Y-P(WeYNB;R^oh=sQIFkZd2| z{l}P{q0S@m9CSrr#*8o|70evcI7AxEWtKM3YC_WiMXuuXIz^si>R_4na2APL@EWmF zmz^^t1xO@;5iP~G=u4(46U-TnDhY5-$vIH6M?~q8XQX2WeF3o@f*3CA`njEb!|!!TpSRSyOsJywbGFG6!0<+Uc+fGY{tB!Ri{qKB^um3*ZP5 zL*-M@NU=}B&WLV6y`ecVxJX_OOk<+I9|=bT=VWe^xWhM|QSe{c%=m4TXWkJGo>5M> zlqNZ%OljRdIqfktf=dfLW0w9URQ?5*wqSb%GlfM1lK`jvAznVD*ahA#$fgLH%ov|X zbO>28>RK9^U~Y#nDrjC}dV%>7s#9Xwrq#OgrodXK2#z5oLI78KG7SY#H(&_4IC3+i zZH;U*Bzdec8WjpHIEPOSq7GLAURrWK#O$9jYk>f#Jro633Wnk35wZMDC7bzz>1rU_ zlF}^LcA0e)QsdcGrPqSlf?@-KMDU(QVG%v+I3d{xpB1%%LC+{ zQOsUsx7k4z?l0ghz@mo)h&!OftC;mfT@!jC$v)m)M)e5_fgmeX3MKF0Y>!mH^Z`D8 zg4YXTY!KHm6mSBA17~ZzEr}uGY?qyOMsP3y^L~c8Dbln!wvjwVO~HE_gq&N7f{%fs zEkzr|MhrFqd4i{>@YD<_aNI$kphL+Ky8a3$`CFKM0`>{HIYna6epvDG(qmJ{{vagZ zkaH$#PZJ;EIHhoicn}XcH>fqN{ft%=r(;9}E5@Kx$j{^T5hgwJyy7s;IcpQw`^bBr zBz{c!b&dZe2l&$5-|fxd!jCpHYHf5JMaRxU$R?CVX_%sRgCb+Rd`f0O^T6Dy!9U5M z1;l|DkbHxp5v8E<0eu+}!c7`}z||Re2VI7Bf}y~~RTgrzzD^dQl#eklwF$zC%mfc) z%On?(xTZ8l<6w6T8E_s><277)1a3segPY*+7y%K%QIN(XX^UdpAY&Y3W@8wQp;eeR z&;~f^z^6K~H53S`A?k>gpRpIlBpGa+M&86y&jL@$7pSyIc^-8yFl{``;ajLX zAr`=2VR!rk{@G=CYEpgp(ExXs@MsNAAzO{QlekB)dla2hVnKDx)YUwCzP^muCzxMi z^vr>Mg@YDQnCESJd74np@Z!mAlWYs6Uf)S1=WQAd%vu;Jc!LliXhoT3vs($U0?PrG z5wa}s)-x4Hu?di9TaOOL+6DYr>0=9dOp*o-3!=S?(z5DyDe{n@$CR>z*>`B%i(DJS z-UzxLKJCF}I2i`EM}ft1#JDJ96aE6>_OBoL|8WZV%=ot+DnDK+dr8Rq%K1#W(FwXQ zSQeryNPmpz-=I9i)>GU#)5I;jKBU(kmlF*GnGsnEz3o%-KC1OG@-FJ0;kj-2?Q7sC zkk{bnFz?_@>P80vQE<{=nvs~nT1H+t7=Z>zI%BndlERu1J$;1U)hJbkMxeMY97@tH zM!L=6w8Hwyx<+y{g1rW&9=3daPpFkdm!UK0Bg_XlA7C*+U(Qi?O3I0eW>$WSV2W?n zltyZbTW=AZrwwDUDcM?rom0v?h;sz%F*9=W1fjghGu!a}J$QB-x&;6B6L{+woc<-g zbf`2m`;Kn#a0suy0j@_)Qinn7`wgx#@&1TrYcjj*#ebXw^8 zfi4{rbcM>4fnA*6r|64#8d7;kF^7}^mG`ma7@A86g0nL;w4}1jP~hGQ_6-(YHOOhK z@J*>X(h1};!WB;vMV({nV1EKz0i?hO<+&>T`US> zp~Xr~IpYTQ8`y2((zrf;*1@vCYJiyGBEmA&=r830arbckgmyI0bz68BDb`YCN}PK% z2)>!Hb|b8eK=$x9A?pMw1+k2lOwJ=5QvxtnFa;G5gGsyLPgYomajp0JmN*r*%7|+( z6=GX>{*m$DG=__Kqq*?oV@ES6{zauMS+?c`+r96$gmiZdqJgyZ(pWwk7 z9xY)I*lEEP@Cu>)JB!m zs29M83i%_2NduQ!*lTM#Dh7R5QKXOcIzxiudK^n|OOgquBSw=MtG>mzYqAyGD5Ggg zGYWM5C4x+e_9RlCMqNbQBajP9Oav!HQPwGQuXE@b++9`PloC9(1@{&&VfG=1%?G53 z=U_dijdk`hb&mUoAj^Th|FGn>*LvP~BY(3LaO)P_dsy>*|Dxi)V0`C2odkLUl9jUU zkRDPp$~Yl0GLeDhaE|aU&fmb<4{$kwz76s>$nY`fBTOb_HB_F$7e@q6A{_THPjI$| zivijV95)*x*q~$`VY$V-LT8)&U7+<9zSpaLa#^BoU~N4goVKhsP+m+h5sK9J`D9TY zD{l5lH%(EK&HS!b0@--jRT#U9NUH&$#e6`^E~;JCE_8%z*Qg9+GsJnEHRL#maBuM>=I&y)#AFRAfIj57yUIEXzQDMJ*`}Jw(qewh@oJk%H{(?82>T;-g_PB$K7!l^AxX(GT zatUTU&h-d^WYx)bTR0fOy41Eo z*f>E^$fY{iD8NK(G!7XS8Ek+k+n6MrUP16g8XE1$r4USrxdA_dvO|=8e0iE{6Sz79 z*TJ%Q=J6>8Er?vuGz(JB1otV6GDTHbtamszjk!!wxd z6S_64#MW1}BVM zLL{NtanQh}5v1&Ru->cl?N;zjPoX2ZG5c*b+N!`=g5}U5@*#y4E)%ri;z|j!PWr9t};&HY|u?W6UibKc%;2gxH z3~`qfcQGOZN~1=WOks&wLeiMxzKzKQm-g9_F}>Yox;kYABr=7E;Ep)lEu_<5Qwcmz zLccFGXEpls5Gd^ys+TG01(0WPHlc8ib06V&AGJ(BF6>5_hlunGR8Prvjj_N)z$Jyo zi0e{sE-t~<$l6l4-@#eeQRGvC+(q*RgA_u!i%3gSP+Nl;*LxTY-j-&-hsPq&8O2*}$>^z+bU9Re0pEiZC!N^1F>hG!4Qtu+x{aK`%B7y^- z!39O~HqKgl2Wl-+AQbQon1e>E&ra)HD9IprxGWX*Ru0w<`T!FPUy$THF}G-e?Fj_C z#7TOdM{!ND{|lS^gjIYW${FSsF#eSN;heh*WA=e(HL^&cVq{9~ zn3af-Ks~~Mc_A@Eis#{~rXQt7q-m`_%pd}Nsa3?PtA7ur>I!0Dp$^6*g`h1nsYJ4E zYf35(VyY$x0;2|Yo0@WFu2vWKmr(kOf^Du&B^w9aa?lO+8dpZp0v9W|*Npl2>|YY& z7RDjjtw7&l6z_7eQm*^L@e9B^7+*N{_G`C;iwSCqi9;BHY}ZqF*5XuI7exof=YnOW z_zo>g7Ws2xry>;FVbF~B7a()2{53iCocC9dJjbjMY@f`NG`3I74={Vg;0oR*4EdjM zeQS^Bw_xmHtsB_SwI=^?1;=YJos)e+P@D}Et3wnZ)zT`c^;q$Ax#s!CgR{yh&ib1F zd#l&&`sx&ZlU7rzslc?Rh^eoru^nK4RE-z3a)ouOydjsWB;J_9D+l1mke2W_8?JGY z>T6u6=&&1LTj2!gwJMM!*@*P6rs#WT-(eU6;^yS^2-gM%E%bxq{gvYuncL*AO9J7$ zfA7&ojgm4l8Ne2l@(AI53Ui!$K*?vsVND2`AceIQMx#ht7o?f9h=~S|WDvPZ;}=LS z6rX5I$Fe_$_OH-5!Lv*BFVg3K%B-DX38H-f`X-(P`UKm}9tRT`wUv-{Lyc6M!v%0} z2@eM_e@@VZso!X1Mp1_+Bb!6YLQl39G5^_d0M;3nJ)9^ER&)Pig8;G-gbLuA>MRDd z0-=T75nO5E(iC=Gjj7``ob`6HObyA!vQP!xu&qe$es!-$x zB^3(wtX(5(%=fgMV-o3XAM$s&KAUl^txapS8> zca|X7$3%Aygo*$Zl6o8&P>MPViWI6MS$rjRsa|8Pu$3UWN-!-!%GDToLpt3?q;XQq z#GMfwY*nLO8CPcztHv72rp(M0e4kw)CSD&!!Snu030JaM=T<4g4&2|4ktz~ zEvi;OFQYg_{ASK2k}N!q5hpMWwLCO~A;M}S1Dn;RkTx~POMtP!tgVneX)1(6g>}=4 z6mA3EgVmJi&R}Z|r)xM)HPr-HQ_Ow?PfX#`tX^k-s2pmNDq()uRYXyRsjKffPg{sO z(x9A(Cyaz)Tlmix@b6v&d*drnz;lT4;tbwAH^z^QgWbXhjWSguqyax%;G2PUx*b?hRc+49q;Zllw(F^Nlc2+Q^GOc-s02c zzu>fk<8F!YA4tQ`5m_MNE-H7CG6lDyu}n`uZ6EbJm<7BJsAiA}mLZCwPB0o2SEEwE zM6jX=e&Za5sZgv+%Fb0XSENFG<7*^)tFSFnXB$kbP%{qIDbPw9OQ{m`a;OoT*;KAt z1)%l3_B(p3qLNxgl8J*^1CvpW_6=w;2^D2VR3!Lxqe|wDge@|MHZn?(1NaliT zMo9rSxorz59`*#z`|psF(l$m;JwYCjQpV{6vi&)W^da5Q;Orjw_sDXDj~&uCl=gil z;y6tWZ5uEfq0KfT2Y5Fo53lFEw#R{cP3eu68Xpt)m+wdPJi8C@3GGOi!V*GU7O*D+qhxPvhBM*qlY zFJ&f;a0ZO_jM-q6n2DWZN1-d8Mm>!ameH6@dRDqbhIdi^Jwxg^$uB`$HT^3s9E{Lo6Qf^orM=Y+`#O}8THIobamIb~R`$+iF=Sw+W|hc31xRmKFIPRUGZl7UlORt+SZXl$g;2zbA#0NRZ~ zsa1n*qJEKTDoX+rYI#>Sv!&UpQ5rcHd%R_Jd-ZADKu>0+_zU?!{NuH^do z%)#EIqR9CG=Lt%x&wo~#W~v(MV}0CdZ988KFz>5luF9qvWuQ98IE6GPgov3?Vm(=K zI5GMQ;lFB(Kl#MLVfuPH!0W(k7~Bzfx$yim@a~CYHZI(VMmrb}2Bq|cxf4b)GxNf| z=xBXr5)x_AA)^Zh?&00Xl>7-X->7W~-IP0}PVkf*39e^7^o&_DFfhb{90v~R7{b3PIA~zVj+8UncH|@^T14;T z+buo&u19Cu*ymjro_MLuEVE^yM($-wq_MZBN+R14Z?Cd*pOZ$-g}!n#-7 zNb%(mE&mED-=gR{2p6@Kl7N*4WsK97S%7QP>I6{7(@*+3rF_1Tdef$F=1R?!L#lfH zCyQG1cS9v<+X1f3;KmNHR|y&k7;2TUh*cGQJeuh$aWvSRmE1gTH3&ZYBmt3X)WJ5@ z&t~E%ZlbGafv{%JX7Te$g2(Zd(2P!=jM?!VswO z)@yKd1h>|PKPsGeO1e^b3Sef8qwvwG<9^>VSrvB3Tu3793a8PtuMup4lLuIN4`a-E ze1WrJ8}bs9U*P0#N$x#bJECL3njXi%@X5eaF>)?Ox2xodu#G}-ltBol1Xavt^jzoK z1lH+=$4py*zCMoyb%07`=ZTQV>Ld@03pGn8bszcs2gU39iRZF2o@)+NA9PW7j>}bU4c|H8{;;Wfkcf?-*<29 zcWC_C-1v(@xZ;hy2DX8Vd11X)4tvK*v&YuXl4V&j44K7R*c%NTWnr2+%pC(ihqA!( zyLhK0w?_0HCEr8j7$*xxqYl6B$m4;lqsTjR7#+f{IkL29({NN2B;ZUaLqK)F`}gS6 zciC?%!J24oz8ozBr+G?m#;OyJ`fB{0w$|Dsg^5*YUMA=>h-_qR`P>;+u{uQKt4QO@ z<{Y(bqW`my9yTO#!$bItv|>|?Vz#Rj$Xtn@+|Xa9^nh7l8s}k zK`EXjZd1uP)LMLSh#R4J&blqO&Jx?DaDNAW&}VKp!X4ms@-K4&|Je9%y(PQ`{Pd_g z#FIOP_Of!ihUI)ChK~!L73=l^bKuH$qMU&?!kHy}@0c_leLiK7jOjVbgs4iejy%jU zx5inIgvc;Nu1G?0VOEx5pSC>5;P&u5r06+g70lP8=tDVXF;t_D1^i|J z)I69KJm);@53sWe>pPpNUN-e~+HABam?=nzj){xHL4fy?vG*YIU%ycJpLgK3JH`Iqfl>GRt=HvC#=pDy$kOZ2 z3F|?)o`hLzkH3>Qu9Qd)#@Z>fv5Um!Eilm3|IA0a*HO;0it-eo4U zky)E08ycm7r~v^GARFjzba$<}#&#EXKSvLK6V)Wa0i-m`3d^jh%E)l{4D>DYQ1>G%?u(J~5QcdP>;Q2+N7) z^9~{^a)VORDjqJ@pP`jzz^5(tuuK0xT0+)73Gt;v&RHYs`ogH`t{|Z z_9JwvNgZ@Oh1sLWlL+8riHVHgrIHZEp3!LsLlCjhv zdPLC^a*1RuXvrLU#gE3-C=4B(c;j9)rYm^zK=|jEcDo7uM<0IZkl$hP0rq$6<1Kw^ z7mU?TD2<_`kY<$ZWHJUb#+gBroFTm-p}>%dQ(@3dcac~Yq zaE?W+{rY!~;Db}R6KC*cF2fF`mS%?xJF8c~Dpelic|V7JgJI74qgC8v>1y)1inWy; z=aMi}|GzQUXmhr#`NB5M*?*~}bJ6E1Ay9C`X?6ucHzJN@m^!>fTPpQ^NWZsl*K`j z1NbB1*c{uWY>RNx8r}=*J`+O0#R-=Rzq$@|YsdZA;g-kj-GZh~gnWahACa3+NV290 zuOadlrtd-gs_F%01np^Eq1XdD_cjX;H`5x|{upyTUEZQ$LAC?VwU})X=_o8~bzu>q z3PaV;i5wM)+t`fOjWe<*u$2nZ9A~&{;7MQei1BNVJImU0Lad(n7H4rD67D?Uld!zQM=NfbjQ1Kk!=@|9GljznCA#-qCuaTsqR3@Mv=MJI7{ntk#Bh$^oD= zo+SYSZd4wH#9Oby{?H=b8M%B9m3wsQZRMy#vt>6Ucc*zlWFe2|a6}ok5wau~rOG zU~20XlIO+qGksl{IfY-V7Mhvhai@i&t}gB&RSMg7tfgZDcDvdn%GB#((Zb5X)l|EZ zX=WB3N<;91iGhadelpYB$Ke||u5s#UWlbI$G%91CNiMO#*xyyUE93jo_z8|b!(K6h zetr7Cw%A`^{C*N%-#hLs9MAWjlT!J&j~ZoTj`o3Yu?w6}fwJ;Exa+t`fps#jyu-Y5 zhT^oaYJ_J*)+=MNbM#F_(=n@ZMsf>EV|2wc%8D2tGURU}d^@9LkDIz&3TU*Y_$b_>f?; zuce(h*awhQ8$}`4`+Fga)1^lc^vN9)kp;jQr4V-y6 z0PzNfSt*qbycNPUF`8lYkiTFnkCEw!tb*wKsGJbwH3%!hG?D2UrDvHF-HGSsWnt_c zAHL)G_%jXv#naEx*A~BXoE-vBt>K8kRp;n>cu|xTjho5SSi~I%8t1v#Hxv`H38z^o zV)VX{ePM8!QwRM}X)u!;Y5mU_^H*59=D1`I8i`HAzzIQKr`QL0JdF(`cS`UtV3?Tv z9>*s%GLcG0j4z2iBeA2&fl&g{dkkNVnCK`eQN&d{Hd|3R0x4`p&t`<1Ije6RJl#Sn zdvF~G@kFh_P^2P-D-Y7ZS%hz#)~V}xP$OE$K4w5)?5$Yz*|QBbKn^ZYZ%KwlN@g8 zc)JMCvhdAH&i}`!{~w0__a@6-Juzbs2jFrB0+0u+5(FjuIy&q*_ggj3ANh62XLI3*urz zrpy>G$hIX&0oj9Qf)zX-T0wJ5(2kJ_3kAs$)qvMC+VFr?s8H;7gd&&R=$@;~fT+X# z1_>UKVbg+KhCLryI{j zQvS^!eT@|Q_0#{GK2AqRS_N)y-X_`~VH_C4k68QX3|AcrHuut4=8kJj+ks%G+^Wa#rma!+u1i#87D z8nQG*&G^z%@|s*<_~8n@><{-~`R!`-5XbANv~RuocGO%^*UDtOYu*=mjw z8Ttt}bLm;6UNup`Ys<1}$$D5H{z#R(e9L`C-ze8>QAmChI-NhC+I5Wg~;^7Q! z7dSuia#+)D=6ZfvL%bLqtR`(|zM_S(y`@&yl5wxFA8MO-V>QokGfuFW?|zyYTR7Bw z;Fe$#XSlhlpI~L6T{XbSqFCABK&%s^b>^Wc*0M=@1U;5 zyTqUalO*mrWitxrt+H-Cz15)!K4;VoIJ-ey!ut+!E3`aj5l&eLIOH`q=^Z3IL0BN# z<6Tc0p?Jdw!<>;dV$vhc7N5?+UUH-N84s0>obnYKuW7XQEX)EfCPrxq;}VlK-Kw^S z*IlK7J6BOcrH1tqYfqmzhyFRF#{@Fg=en;^%~KCU3pWA6)htbuiVcX?&u+#Q76wl; zTufI;{v6@wn0|_cOUNTy8V>aI`2;D?5&442u37ql@lf!wu#U>bIUGAan(W0ticm;bGO9#T1o{`#40DCiH7Ee z&=!gY$_R^SBvl&89Be?W$FXIY?qi|4fvTNj?vla==L-%)?F6T7b?tVw{`Ym14~tMw za+X((LQS_cpE;ZlGfjMkc8wbT&FVdG4pJ5Q@qAwJRaWV4GW@J073`BSL`(QZ!E zs-}Am=LP!l6^z`^qEkxk4~+BMcu4hX8D{9$YsD0fLajDl^e~p6BmSpYc}k8~Y23Hx-^-E3d7Uzh2J~;9_BaZxi&Bum%pV zA84<>K%LR=ps44p6UMzD3vh!mx=hq-%zcKXpMqcE^WWAQRCa8p?=a*_&6ZpGbOG^W z_1`HDHwf{Lak3Mx5f@WjicSM(-Hw}NqyU}Im}XiIjQt*Aq+cfTRFG1*7nN_HD1ZI&Z_ozrCt*DaH@)Nc zLgBf;VH`Z|v9R)vY#xaY364GrOFvQc1(W@R7&Dn;#D9e^8z!HL{Fuw(_c`k39X@y1 zvJJRY!E}p}(FO)}3=%l;LTDOtu2_N)$OI&;(EI?i*AZDFx+S8#(ykI$)48N@~q6tC)HDuuO(e@BS8`|c#?}W&LJA{$>G`pY&qonTqIxvt3{0j zCkmSY%SG+yzdY2eKg>!ZwMy|CW_eesd{mOw4Ya0~jn@Yl$I3mB0$pDd)0C~MfX7lG6;Fp}H#$~iMt8uK3j$vu@e*vT@+=9A z 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-63.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-63.png new file mode 100644 index 0000000000000000000000000000000000000000..21311d1a88c55282396cc0dcc13ca88956f6b7b2 GIT binary patch literal 33011 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 LNkvXXu0mjfH_eV< literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-64.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-64.png new file mode 100644 index 0000000000000000000000000000000000000000..e5ad72ebbaeaa6b1e9fd7ea34a3e6d8448f9e122 GIT binary patch literal 31551 zcmV({K+?a7P) z`VvZhg;{7bA3%T#(1wdf1L~O^^g=Vx)J%(FruZyo6|3?Qk&*H6aKEo}%w};ttFl@w zl2t`QqYF6v71!gQWB+6J|C`yl!Y?=+gnI}N?h1QvE61&Hbr8M+yhy?$;O5M@);NE* za4y|<-oyl)e}sqML%H@w;QP-ar>{r0R{eQ|I5^$#7r&A0Y@PW86`m zJPM@G6~wM2^m7K8qcIcG8A)6IdI@(9oNr@%hB1C%{FlG*?N?3wbB=q!pWqwo%dcyG z6ko=jCm)ACn&e;I9IHpFnH7-kn47BQygwrIS+W7Yn zzPTCo;T_@9CI7(i4-WKWPu^QP$9HW4>YL8D5gd2;*^jv@bWKyXn0=#9X23Z4xWO}&MUui^PR=ox{Z()UMP(w?JX0EvH$MyspJCqOFZ}j2 z3EiIHXUZ%UB-vpszD)4nCglZ@ck%E&EDj8-%r=R$E@CrChr-|X##eWY|Ni%#vnS5& zH9SbdaO8X=I{UYrYmM_{;e7MHau@yq38ZuVE$6}?W)9vN>19oo-o?vjsE-V+*_tQ7 z*vHw&dGiwxy>GuXJi=chu!K9U@Mx|43*dF&uLk9N!*p_+g(f%*Kr$Wyi^2K&j`3%Q z!u>nKo%{A1QvqCWg;U@nFlIqQ#C%SXuVC_Z0#|WnlzvD~&q&hJ1u#>}kU6=L`Ijdn zcAj_&oX?!@K;W{IqjLiE&mGpr(W&zXZy0~}mUEYX5EUWd4#t1}56X?-&lE2PWK5ii zQU!-|BhNCA&WxLnjC;8MS041$YyJq)`zHFqpFBo5z9n2e6&`fT4FD4!WT9FFW;?>q z2BpcuUXxiaGLM(AS31W};CrXaw=n)};XFY2_QVH1Z7BG709{uXNP&38*cHU0q8wqzT2$5?u6o#p@`57>Uu-hRKoy3JB2&9 z93C3{!+?N$IQK|A{wwF}e`x&lL^)q6IXGXtaw%jI=(W_ zD>z;%ojRc~hT!Zr!v4~DyaPw4nf+S|5A!Bw`fniC|8l*37vsf$aNfhYim^oaDbDJa z^S5s}e*}Q?7Qicf<{lf8hV#wM^Mktrhj48v&705zXT9?t z)i^>};GQr!z^r501?FWzpSS1&XzXBKP*ZR=W<(2MB7H{&r6q!o?^Vbu$H6jtlN+=QdKvVR&eYLq##nPc6IRDh(O zpi3&tNN2o|%vO=v>!;u9m%?3q6JqSsB#7i=C+rS^J2xXoS4ys(7Mys+(3FH+lWc)` z%~ol2sV8fPL}kT{McT!(BYFnK38Sys1=doKPiwp?D8%Svi=Vdy=_u7%SDAL{XqAau znd&t2pMLDz-Z1Uk_)9SSs)PKmNZ2bzzdK3qhaaQ6A1{S!!_4<@2#Uu~7f3pzt~!=&rrOCISI*4?gNMcg{L`u^`2~74aP)_P=IxRbuh^ZJ zj4~q(GgfJjSXBrk!?>aeEm@p0Dx+2CnX{Vr#N1L^Vu%fOxkJtu!M4djup@#Wp!tN3 zp6w!2R+*EW$md42%)GWpR67&XeOYVx6$biq4S)CUD+WJMj$WT$FWV32VATulAT+JQ zWw;HjpG@DkyVG;%H>7Zr1#O~pUO0ybaQnn~3|udb|LdPPU;Yv7m(G7Y3;d5J{HTlg zt-#k;k@Ha*8=>nXK_jEj33&(X62wb51<_A&4oEzs&=G?S% z@gsWsF7g5Sde!Lrt#H~4JA=SA;9Oac8zU!Szn@lqwQ7x(+M`f|Ljs7{f&( zmoaHD)>QHs)2Bo^!0IJCrvr~0V_rJ%-N@{{>HGo4H}OxCdjI%T@NJw2GvnY8@|TTq zEu>t7UMKL|B>NnM0}7lZXSjBhU1BSPS4K{OUX_6gAGZj871gg{d;^sPJRr)7CY>U~ zKpZ;8d8Un#`Q?PJl%|Y4w1Lm>Bu<|>e=!KRZ#nlL+N*NWKTNU+w-Ejkg*V`KEAU7; zy(X+0;d+?J+m0#ip78uAunn*cLlVX;JPpcXRN9qt@v^aVsxX7oUT70EK(~aQm>JY5 z&tY9;@?b=u`Jzy@#!nBGOQq3u!hBaKwdA;)VfCEtx~7dKmJJpIWimVmvI&I?qbXGp zF{{YAA;!Sk1NAAav(S#h^@Z^saQ(A!q+hH8_8MoY&c#zGDraSZD%Pl9Aj{_vRn)dg zLm&)7YMfLmqgNE6pcslLK}r=CxO+V>{Lpn z!j+l8pvak0n2?7+;Q}=b7C7yNs)qGS2jnr(WvNvUM8Oyw<-JFLoR?}RX-(&Nl<6-*q)$y9?)xfz%M z`SQ5?Yg7RrQ33#83eM>cyf{>LeIUy*DLg{l@w`O*98FG6#!@31BRMrht7&tfR>Lij z>XtAbg1>`nB*YhFOL!4zLP6Kg(b>SPEf_;$1Zi>#9}m{M&+HbJ6N7Q*U0 z(o_xN1<1%ujjnV?1o4u}YfJ*2j7WWsua}&Kmc3qBFZS`EwBr-vY@lhOC?fM*bD}f) z_5u@`a216nDi2CAVzdL^bnr~}?asuHTK1PQFOQmWDu8LNUaUq{0ho}SZ@Q6KPJ zGK3vM*u|`&h%0hBK`2x)E?KzgakvI zsp5b(iFRC4#g5JsvO1^rkuqkEOxP7@3g@VC_BOSFZ~rC$Aiy8J1@V@UPL%O=L6%BX zBiV{l1}rU6KSqj?6Bkq>sV|XYMwDGrQrymva?Lm#Ll}|b1>zO%J(Me|1naa#r44B) zh;>8u0;v;lLeC58aLj49rU1$-&e5S$4vD|KAWOl27t|DtM z=ru6kE?^aT(G?VxLJvZuH>GjGb3j$8rNP)H|kZqTsJGf_@12nvin6e!* zN4=w~j5N-%373|c%VzvPi@?sRLBp3Zd5zuhJ=XJ)ymazRDd!RGN)k0vMbHutk(3HB zLp6{ARUxDTvzp2aOctnLXUwM{j_3}AFOd7Mfm{SR#BhSYAg3eH6>&9^RJbf~uoKvh zfm{`^RFYR9yC|>Y_Ip@Zpm_)947X!K&ZNQ^#HovnHi^_`NJ^MTZlu85ZQw8)zcWkR z!gx5b|KCh1_=k6#J3n-`zM45bc9NGQyMfB@fQ$^*Qt^zchc-LieB?svIAcY$fP@ke zK_$@U3erd+JtK~eGmxu9J`Zt^M2V$2l6P_0nHWg;0iJ|aXen7yX=ap6w{~vSnPU^y zRi+OGXO!&e1rlFF!VBtEPc8;xX{27+_7d`p!DlcOpb=$a-4YxOM1>rSNs^_CG&+HV zM#p>(vWMkMNO1+y6~qBqF!-DpDi%4CW|488IUk(uQW(ZaMI=PQ3^FCKL)1&m1DtRL zWP$q}t1@vcD55f0Pw3AGgE6a|vtYcPGJAa{c;?X$6h2#9+AjydrAyA~kDb-hiDhQK z8fc3Z;!7+S)aqoMt}&J;nYkv0Y|QJ-S~CT6vMxx&98src#flLqka7poSCQ~_%w9*O z0TxIoC>#>tuD}5z?~=5k)Rx&evI+&42DrR%4vq`Hyd~gDiq9#kAJOH@XbC}keCUau z8Kt7PEtD-p3PdM;KZ>Dlh&bv2A>z44R4J+@7CJN=K`JszmV~gz8 z?FsYkN2IfXuu^^p=P#xbg#5-l!0k63Ze`wUGnZ{-S+fEZhpl9Bg8mXvMca!jl- z3dt-xLmMZK%2;m^wMH{&&SVtTnlbGXxQuX%MX`$mqTmJuC=A-Phsy%jiozq&0!vD^ zvhlbturjbyXQBqiQdn%aoS&Z);tgb6pv4);3U{N^Nbm*1HL~9zi~~WRfUF=JAp|TJ zWUoL1nLvo(>bQWokW<3-`~xK;JSWOCEVndUnb87Llw_Gg)NC#ceMOr~3Tx1zp(uLr zcYug%1NH<9OT>1__CB!U>)9~)E`o$0dIcF*gdCfN1CmkzqnMeJhac+6%>C- zeO#up@Uu+u`anKB=QKRxG6yggjPz7Z&si|eHL$;gGj%kN_^4RbQ4RyGgM>&YktSwV zsYY`RMZuVr4CD+cfd(k@RN8O??g7a{N{~XJuVFP*=+%MORT+;1PcH<@90|SRrBLJw zV+VJ|lTua*lak~Y(BT_k{{!v^c>GUD@h+}{djV7k4Mv3Qm?VM^xb%2%3I;4cC+8(0 zCe%(C;{jqz`cWA|Lo-us1P@9u!NUyk3XwS@b3B)fxH`y}n^@t4-e@4jVR{j#y@ zGS%L|m8H?PEsIKNU04Sg%8EUoBM6n8L4+JLX}LyAq6H>?@brKzkDTXE&VhTu@$r2G4+R?vH-&VUl~lnktCDv`gkqj5|Nh+_~jE*l{jl zblEry!j&u}3lIwGp=R_76T{|$^$DFPPKR?EO$3?YV>2;vtuS@WPAK>hE>AFo$N~p~ zT_ptYToN>(5}+^WT(EUu*$7vg%xN-IBD*ssw-s?q7~28U7Ch1Dl!GXP;N}=365nG? ze~pGUqDP2s`fF7XCZZ@(1-J;Z8hP*v*f`yDqBE`tqR}@8o z6eZ4r5uP;e@^%NjbB1ZdCQiT9wESiJRy~>u1jK4N;4Xs8l2`I7>5B9%1^N z;A>osSQ2)bRI8->#Z@KM|O&VwIzZXmW1d~o3Rd) zZePp{lZfd}B>yXrk|5v3^(lp&kaPrFkz@sOOeA3Pg6xl|@)2ttkf0O#%SfN+)a{%h z&PYLsVNIExBqgbuq-2*@1d(aNJ)_ytGUEi21(XbV>iL_xu@#X(_CSH-!N}iEQJX^R(Z>00|WuE)i%aW3$Fm zPpgTFQ-ZkQ>6RH#NX`3$jRTskBf z9-m?UKBj`Prr-smodP3u2(-B%^xG88KDpmV@&!Wd21Tm6V6arb57z{TjnWGX3ULaH? ztqHb8W((78$O~KqNT@M!qFj)*!6kupAU&nFpfjp;hQ)@+G*5$##5{5yN9vt~l1N?8 zycs#|4wdA0lXXb>(I#?g@2-9M-5jm|1! z%;Y#Qn;Vx_fuoQRJ0sZN5yF3D^ck)XDeQd;T3kn5M=T22510Y#G?K$et`eaSBr05M z#(0q;Uq$mZ#;}drGrT;;y#y`DMBP9tn~`jBFJlI+)_pU>O3+s0FnM$>)g85UEhD5o-{ggU?Z|slqgGDKlMzJ029( zfLjeTm|ezvMC~!Ipq7bYr1Q+&M@BVp7*J^8de!lGCvov$00ths<6OGy_?y411@=>V z0D!|cg+F)${wfLO6=88|G^>H-N(hS)(gc_FN#N}mX(IH}5r-c#56^LF$bOEoWSUTvF$T9F%el^s@%{8D?{&C{R1Y&_E9AJ$w*bK2u4rvNWQX{@V)Nsp0?a0}oFeC_`GljuA2wSR1${enZ zs3Y%~a48G(Ub%TVmB}6ZMTw$M4}d$sU$(-HYeIjjER!-W19ri&!PqaAY|6MTTvCDP zEQds>PI%#KwoD*7y+-OdxlGcGS~}L6fkfp(h+AZ7NFIoqa8W|aBu0ow#G*y@42q6u zPL7HLr3>c5;4-;w2?$1zX-ZsVN<9+6B3MP1Ihsq72iyljnA+1_%PE&(fiV{p)L5uc z79?39wuO6%5C~ErA>w(Ciy%ZwfkI&sVW-@%DTmP@nM_$n6U0igIza>@AZ#((C8Pi( z6IHO_=vY$Pj5gHF3#aIv-UgbOxv-_2Y$=Z(MYuciOSUh4VgP)kS>);X$pE7T+!PUktVk3jEA9pEyGZ&x<~xYw zDc5gDD2eO|b0ttBQjoPmSdev(AUn7(2vSTT2n7|2O?t3x(4NUCDeFnT~3&sq$>$v?hO4%hFWZuTrN%0IY3L+8%B_+vs2)aOQncY%5cEZ32G?=oTB zqE9OVlZ%gyGWMAur0r5St9 z78#S0SQKce$f+QpdW#?KjSv&sQfrq5PDm#1}@ZF<0DeD|rR z7uodo>I4>%iXd}hfN`ARVz@0yArSH!Vuhr7lEy?98fnVFrPBaxyZ|pt$Da)VAMUWZ z15Xa7*Ktd!5z;ac>XJMz$bOY7B$Ah?ZZmWh6z3H7jBR~}#Zz|0Y4(Q4XMGuDaPD;ka9kr0hml+qPUFjq2RT3Vt6bu0?W zl;E3cgE`rhfRTN(@-{0bXkf4gWdtn{sZrm;bwSA61fMahCs&S6k34RSzcJ?IO*UIk z^W+s|^ByM0Y_E9c1hi>7Ckv1xv4G$(YK`Oy4QH5lxSnGUnj=y~Vi%BIVR@iz?Fk2k zu)o;|<8Siw$l#|VfnQxt+nQH>;B#46nKH{tuFGjP<^>%$Q2ji}Ys6S%_LLz1FN6Ip zDRzu$WAdLdr&2XVSAlLXa{QjFwAU_i7b zxltr1jRjT|lt%>?N0v#rS-{bIQyBQQkU$6iHOd3o+ZzA?AOJ~3K~%Rkov8e-8801 zB8L}PejAtPV7p{-OqId|5(|`?lrA8C31LA~KwWO)wX(?vOt00z!-w8PCp&)Fyrr)g z{S}aizwC*aIGd0_4Dpfdi69-BscA)mF^q~-!dfb-7-$KI37se*C~QsrgTEjQe0mx9 z>amrSQ;levk?a!cH$na>yR&T;VH#AIBOMJY1u+T30%CINg)yv*FU7=Dn~?f{JQwyZ z8rNEQ=Ymn2^Oe$gx?Qp!E@JI2Rn;;iBX}Uh0_zJx42T#m0reT~GsaXB!hqzS%m`wr z8RAOb7{c5U8<2PcIpA^`%R7iV#8ceo3|t^^g(}o+HItsN%4r5ihe0N{EiZ|kL3ruj zU#@!De9uS2zz6SNes6#nZh|wZnn2!^i323aM1lw+CGL@s1LhMNOBIfi@=vzl=quCK z{$Fb%=*eb3UAHGx#}lj02%aXiJ32|04CfAAg4W&vd50mtV6Gk7CR8$38Ru1|ed_$5 z75r{(Tuj2vGdO)D>>+Gl5&mW?a&w3b!&fM)o4CKtAkT@?V8e_+LuUnLF==tji>bOO zGu-mj86;=mD@-#XWYQRMbkgg=a7K_G7zxoyu3#0;7S3hnvF1Vr^9E)SwAc{2JP}8k zJoN`8!u{oZYzQ77ZQ*-G1bk4tQwM^OvZ0c3H{5;t?M>K11XL-?K<@=k!8jJw1WxNf za~>E)_{nkLsX6^%9Nq!H|Mz&nCkMcC(UVbHqKFffwRQ5LsST!$y$)JP6m?};VHtB z7!x^f6LgD48+I$$uVJ@_CV~~PGRW=Z0c_*W)i?3qKGa|OicqjuUB6F;eHo5kI_W7j zoHzIXa9jixN8J$#kRxW(y#%CCG!?W`aB+xqR&s&FFl1^o<}V^&CB1Sl!cPf+ZzH^M zz2M2hcyu(OwkZux;ljLUy*k6TpOM4g5%M|C7Q#U00P)ADyw8|lpxSXpW*9TOlGt7) zwlI!wIk$l$U=f`Mo$~ge{C78uD^~{IJ?W{_cPZjeSzC?R=kfg8sQlJuQocvhpO9jv z@-=9STMt%)E~cD)f-;nheu#*n21X`iM>Ugu1UbWHWXv^zi2IB>!fpi@D!4d@D#DPb z*xw2C8{_7eE`RDVftM;^lM~o1aCGzVP0ql5I`@NKU;jDVcb!dPE8-T(QlJtUsVGB1 zEDF|LO_0QH2s|B2zP^~6RQ|Wi%Ju2K1^(uTUf`1f-~qxH7L&eQM5ll5RG)W>Xn0O| zTru#3f&s!Ic!@Dm*cs-hkXJO?F;pY59hmP7>{N;E|6=?vH{tg-#if&3WOp67TEmS? zBm4}yHWOAI#qKfQ4>a|He#mGj!S={OHWk3BsD$~HnUjpl0%MLkl)8mmMF`J96jMQ6 z2_$kZahXBh0<8#IO>R0Ds7zAqCGo3tGHRVRI)1aFC&Kwr_x{qTvax6oD8nQbg~@vi zJ^_JOJVNrwGmh<*Q z=N|6&rXcmn0PrTp-5;zuye52WM|hHipR}1~E}X95l6D-nj?8;V$5@WUm@v;2d0;3< zhBC1{PrSC3cs$QMKXCpHPTbrcEnZUQt2w#crVPe#e9Al4vKO6YJ@VfyoiRJ38iO4% z3qQiFoEUrf8Q3YFMhG1uhUq!v9n@=F1EM1?1EL8rA-FK&bY3C8h3CsCySP`lfqI4O z#PE89HcvWz1Y(3bLg+qRsk({P_6h)8KFARfn6iD9LKQZ^$>8}zZ=pJQ0}qPjjG!a} z(VgsIDg*>iamo#NiBVJdn$Ak*4A}OFwgt71JdH|vVXT(IzrB^Xe_6SA-~8TmIiDZ` zz`cjS?>!Ql--4raVQUFZlrl&|A z$su83K(*iO!Rv@Nl0!G`zRiNGZcI`jEP&79d2{X5fy6PfJY`{%PaZXY#TY~kbUyFj-lQIJyBYq1Me_x zQ5gv12s%zmXP9yYSqvMUZJ@YnTzcv}9))jY=l*T@pC5fP0Br7|Bs{?R(?`O;`~p19 zu$~F+8uk~?YJgBelYJ_0nvoh~EHh?_m=otQ5r3GO|2Tg@doIre)=FO~swJ)!q{KL^ zsq0J{N_K0dbVD21>R~Jfa#|7V7YNVM;slj7Rv57!>D`bKkP(ptVWcp_qTwzm1-RhM z!LN}0%gp3+TxnptdMWWr6r;zhmRVaf^YRy|`Muws|h(a2R!cu^Yc48&8& z6`YMN3kq~y(QgGbk94VGDI2mD?p;0&)rWl_6)#ka$(8b2^y2%i}q+e-cXtzzJFiy{H`mi<- zHeO@!iKpO#3K%0k3hI%R=a>{IkF5Bwg&Up^83#jf()g&Q+rwle{t9ibb9xfv(fInPefW#*-E_^vU-_zQ%) zd+;pGXf}fh-JUou!-0tP>l^D#%KJ7z9}a$VP!^I{_nGlp@O2F{NhDUDI3d^i03$-gC0} zJ;iQ{YLTW~K%wvg4^UOloz6Mm3DttQ)9uMt&e-eY2Y7jfnNFETkOV%!MF-APTwY*o zG1)QX3B4zp4%P-k{%p$kvekQ8?Z-VRRE6=+`0|?fae!3pvm2$$`*AYk#)&$9KKnSV zGB$`ccxcI`C3=Uuqdq}OK)g^&8bvo{LB|9Y$NIvu%Cw=-*KmF2d==*}gNI*r__wbI zgx?|%Zousu%K0vk8lkHMF+qcK5Df{=adf(4BRn-uZyJAo175r1KPGjdZ&oz4Gc{O-HP%_~DznSXv} z{A-+ldPm&Sf4qsFM7J(*~IaSkCoBpagk!knf_r1-y>voFW}*xI*)q zs_JNcw7hK|gGP^ktHpoG3wV-+N2kJ_rSO;Qz{CW-P-+(j6ILc9bvE-*bKzFY(Vo($0U4@jLGX*54fXqh9&7RlyGm|K}$0 zl|{!iJ0gWPk8Fz+oHja>4h9mH1Ni{rO)MYnsbLKg{sPm-{P^+#S(haF6VmXQTpK1c zD8~f*I!TqxnuZ-!o>5ifX`hC1C{$z*{rYDGo$ZG{R`yrFeGU)UZ-7!hn-WHaxPK;u z0rQM_3wa>u_!N|UP0#_Agq6{M0KS58h+2)7PtZ6c?-HhgAqw+t;QGX%`&)oPj}ZRx zH-&$Dt#qf#>l2~hDiaf8j95;z^U)pj*fN`vx!b|A2+b63UKbwa!kvk6Iy3&|)Y<;f z_``SpMsed$0n~9D6u$dI;n8=DfBByB-!_GJD&vEuVtzUx7s}zZBUQ!=b0!uLRbqC! zFej8dc>XGGuTgA3^~2HnR^MeB{+uBil{Iv=;yR%M%uo2zR1txXx|(1c2Az?6C~-XX z6UKQ#vd@M@FBd=Ccmw$U^oxIn6L=mwf-P{?j)ms7gUbe#^U*uVJJ5zK9mzKc4JmJN zO?3SsO2(`}@DYd-VNfNdeer2RU&g=iI!pXj?|*)0-?X0Q(eSu0fv}6D7-^Xk(jkK{ zP=q$_nCc2U+VJ%GfCOh*jC@--ZAOFWAL9J*i z121kkI}{Jji=A@Rw+vGlEK#CCu0f8G@+R|mmu>*_H9;PexyCqWCOtb9=xgeFhj&Jn zkNJ4_4N?G+Cx{#Bfn7PI9>(HL^)viG?1wsKPXT*b{pbCO&-)W^`&Q8%Rs-xt;F2~& z;SASvifqxmLx(j!U(t30G3?k49c~#77l=Q_{Q&WE0-rMI6|^0h0qdQkxwEZobb-JB z?>`6FpFZJ(Zwqo3xH=9@=Yd@ts8XaIW}tT=zCn~PgWpG)GcxpgrgKTz7Nyw;Cj_?arF3#Ti> zZXHn%#BNF9CX@%5f0?P)6otVraDPVNDUDnZ*do%Ca!($FGBIM9CkMjiJMveVt3Q*k^WFWkbB6Gh z&pCpgza@MN`0dJh2l!wIF94*4;jxo;^~u)93z@{gki^+TJV_F@Bon&!JlJX z&~t^#mdbX7XzUg>zBU3zP{DFW^%$*=$z?CBDR*Y@qzM%1h_=FPgRsJ7MXJZ2ho&V+KYA+31yYQnJ&74v*SI|! zS=ME2g{$D4UpjH&y!ZuR&=<;z9wFRa3+vCNhfVsx&LUPOXgNgX9_C-ir2;Xse}dZt z$&nsG`;os+KZZ4Zjh~^g|IFgQ3|2aRPq}lgth4Z6Jb(|^%Hx+f#Yf6(g0@u}u=xoIZd3?iD zGI9nFHCkFs47IdZB0<}a3!nBpzv5tfvS*+7ZD0YU$F(JwOpt5TRurxY+99FE$_CMM z$mifIyj_D{Bfg_;Mk!d_^&rOJj!b*%VME_Xh#j@9*oKDMGS@ltMlL+BoK@}I|3B<+ z@CyD~;JjV%+i$J>d++{yddGKxZ|tLA00t9|QejngBs+)r0l{ZD$EaT+Qa}=UGSZjA zP?$!6J8=G<@aKQU?CA50|LD0g-zg7H6|R-5UBs8dX(c>Hxdc*h%3UX1D>s94y@1sm zwin8+LqqCJ+eNlH?SB0aVXE{g z5Os@{38Fj7Fz0Xr2XWu$XV|<1fc&!>;N^VZ${rKYid|o!c7@a8GN9UFa*f(Gffbgo zv2Y3fjykRBa>n}62DcF*C*v^h7{urr!J?pbLHdCqwA8YJUB_L^Jf9eE9TtA@-1rWr zU+4$$_B#Woe|pJ(^KSq7g%R+dh8F^(FA0#;@y>|d7MCYDKgR9PfFI-j0;k7ZDBB7h zB8ytN?iHQ_@BTDB>}Rre_|E9v{}8Bp<@`GGp4Ds?HH%5j)wJfYi5xbO*(Pzkjm+x6 zdQkes*zPQsuwFtJoHi8(b<8sAJ*F*5c8IhzwxN?XL+KeRBP=p;IxrO{E;_25>EnQ; z0yJpp2yq9pL(EX0bDUsV!3^je*6pYP+;p(Z^c?kTVpy{+LO;wH@(C^{gyERFso9a(_L+mUBbGI>tm(oE^DXtZXV(@y8TDb| z{WIg?E#rH?z$A*d$v>k6{ydlMJKuM{{!QZ#TH|bE)HjWGTVU5w`U^r5N+^WVpn8CM zgG;2E9pj;+UH4osmE%VEI>vwhSC~hS5FVZhj~ZdV3cR@td{Szb(;0QDX&NP!jK=~U zbV+fHY&~_Cxt|J;8QO4?1F_e46cHp#HbG&t~ z75=x+B2RuAvBr0RGuZUPi$NhIoCUQV;q8KeV6mgm5GRS06U7TrS5RN^xalx8`Xl4P z)_9tgJ10hSX7tN~rjn!BTG*;$yC!!^I>7-g-Z&*z0Ca2hsGP@ z;`2}O@V5YhMqVF9NnexhYARLe0f=mu@yM@~=Oy-EsF>WH|4U{(+ACiQTnTMXMp%4e> z+?4vrX;z~vXw{5UvNC~K2CN^aUbkn7^R-V}xfQpQ8GdXd8xMN2wc1 zR+I(mcgg-HQoah@CQ&Hmf`)UDYs9x`KhV2TVZ=V;(}LW}yxTg*KeCsLkNj%VF!`CZ zk>7s@{?P-7>%v(P4yJ{5E9hjvP7GZY>N?P^#!;sPqtpX>SZL=?em;gWb?+$O$N48X zkASnYF=cBGEQ+u}sB>VTLa9eNlqxCSMeHry?_j=0cn4xjVaq|x98Hb4E(-6TI#qO7 z!S*&-Y&q;9EC)*7;e8-Zl|CqO52G$@1dI{uy^?(vUq3#0~3g!(#7igK| zGQ%WcITJK6-y?zEfZGoI1#T-k*`T%^nM>gc*DK<1MORkrW;^B#?6%-0NXfWnVi5{6 z)RiKmBDuyfE%b3<@IpPw{KR?iuJMSUNgIv-UJL)S9{3ucwQm0a=La9a z-?`_!e*xW*v8{|I!E0+L=Z1W#^i$|6~{u<)Xk#L6RL&{{r&bCxV;RN_JgTO6y-ffIq z3+Hm1X}x1!`REPURcMt^@iCwwIdShE(gTy|tZlTCOkKfdElqSLx`L7^;&^Epq@mU+ zr9_-(tlC$p7%5}h0YolQ*#ehD+hAvP~*_@$A*oBI*$pAmQu;k|DP z9~~<{I#a%m@F%OtYg6HB6PcbkH<~dbZPN>z43l6S4aWJEaL^Z;R(StPxP`OH!u7c_ z>)?OCBW%u;>zVK$2RQ4LuPotNRu-mYb>@=Ep-@T$IYj-|Xt>NZA|E08DYCmD(GY5* zcf*n~WaswE`A}eT2%!koRJc(IeGW(^=rmAGBe@7N1iGLML79t=YMc_tvd4LM5fnBB z>MG-d5<|f?QwDG;m>FG}aM>NO?V-0F$`yqcFC7xLXkH<{qW2vg8**u=bqoD~@72kb z&*{rCfr9CJEN%T0@DC~eG59A`{S}jGL#vr;T1Z>tZYi8jjNe~4Po6mM{A{}&e!=4F zPjh&ld{cSv72%a*;d~w_x0Qtj4qs7zcpSKMB2<+UCa~HD!UXOwgxm>7K&{G)VFc+l z3KMg_Rzo9!8%a1&IK5Wx6*#)(y!K=GV6LpPG8{tO3fm+c&5gDzlspjKkvM9zMJ^FO z#{C0SKSI(KE(4uryf~YsQEi-0p25YTFju(ILz;(u-jhyzg^9Eeal;%_@8W^f6!43%d z80%*YKJv2MmE?-ZXk$}+f><1pJQ=NTA_Z%dmtui$EH(K+~Va0$a5$cXgs4EUJ&()lsDAg(@hEo zm2t8xGFS0kjF^W0GG-5e;p2SPZa49S&_n)Y)ggfx(H z;i@+3;P}M&$%XS~Wl%Z4w{*TezWsmoSNOuK-+})HW&O%{@^4%O(k^fwDo%7p)Ds3h zMPuSLbZi;GP+?WYIM21{5=#nzrL}g7Kukk3zo_Xu#7GA!D_{sRKNso{*6=LON(-G#yS&CyB zg2{NwLxuYRUT&bAA_1Bn`f`oP<){Fn8jY#LhNW)kOUFe&a9|xOJ?*APN<)#3K8%6V zvFYhFqizhf(I;m5aG|hsnoX=E(6mh z@KkE<=z^UdlH>?w$+YeXJn9#Q*s zB)^HW#fHZ?8~VQCz*}DAfiF!u3Ym3Zu*1wS&sbm3+UROy*f0Fa+W06tH!h5A<$V3n z_#b`%zk%~Re|@k-_`rAM3D*V4aIMv{$)g88Dr@E5*s!w83nq(OOnDTJhy zPN`fVN3bO^zJkeDG5rSWZ-UQ(o}sK*$eP|;q8aO{b9d=H9+a=%an2t{HWmp}p$q}l zMD|E!Bga8PLOfwMTF{`j2a zk!cD*jY~DY%W;BvAo^&IEewouBO4vaN*L8jGWrsRB0seRNsKza@loAd(Xhki8ZVbf zY{?Q4o06@=<$a8giGEJQmQ2e)j~-;oYE)T$kPN2AdTO-UvAGe?oNec%b}XEK_wIP| zf5GB^aS{04&wzgpemt^z@2`|IRY+sb9$KT+kij$&eTEDJeN|9;)_spu0}=`;x1)Qw z6{NI8S>mdQC89vF(R$s63JsCVKC+}|QG}07nB%

xJi!g!5>;*gCg{f-DL(8SxC> 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 Y4J+R;u4Da(I{*Lx07*qoM6N<$f|qXH)Bpeg literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-66.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-66.png new file mode 100644 index 0000000000000000000000000000000000000000..906f942de188558ce6537e7f2505cc639e52336b GIT binary patch literal 10905 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 literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-67.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-67.png new file mode 100644 index 0000000000000000000000000000000000000000..2bdb6115b07a11aeaf55bf0c95a6fae258921045 GIT binary patch literal 6613 zcmV;`87k(9P)Ybyu^S6y2tL%+bUiAwCJrgLC5y1_K-*0^-};1WtRn^taZi><=wboi|t+m!#Ypu1`+ATMEpTE3+#rGHREdkym zz%TJ*`IZ2;1$Ym9^@{KRd;F?r+$JK(dj=ybVIhtpdN6{3YO<9$$fe zJQ9Z4#ozxp^$h!dfeg!vP!VB?1P#DtZN7O>KDO5Y`uB~$-$IDFT?E))0siX%e_0|d zlOTixIX8$nXxz7lz=Qc~KVEvToyT*a{|>i|)O8a3P3iyqK+b#qky;7* zczE&m-#GTG$*|+jg@nhzgU4`Kex{Sph3(V_!1rJe_+TXb^9!|>Y#%%ce}4nawj6&1 z2IcENc;M<#bB#oJ_X)5Z_xD}_{$+r_6cI`i{BWxHtHg7ddUiA6I2VSA=N~>1{;Kae zeWC-<`TRXMR=od@{}OKPMk)J0z+ZG7&lAsoO~ZQ+2A&6x-F41I$UE=->*D@0_!j}c zyPW-Bf(WNG;iTgkJn;;TaB75;f9>H@*#1AlI2SgH@P7Rd1a`{TKG6%W*@+jy8}=Qe zZn)3>lY<{%EAr5DH4*OLckDe{2n(-E0=YHb-<1AUG5@fyE(Cq;P;i+nBNxb&3mb`N zD;Exdjr*QI2M$ja{U-u*Y&6F$ex2%|*Nu|lx~eysicHg`-Xo~@3f8+oR&=ULwcBK$WXakU!U zzwefZp;sk=diMu`O9Sl6`&WU#`x@Xc|G$%g3euh_CfmYHYj$14zcRw}RAH3n#}73h zMVcWI#}mzXmSAkmU=)#LnvT*aAJIu-l#j3`#+sOH6d^>Uy_jPgbLu0eXPSRIQXKyf zG5QYzLj@DXf6Rn$zg1zDb3Z7dzxssJyGwv3&mS&5)|CFMCVUs!$w;vS%u>x{Tj*^H z8)ur-2-8?I@(~{y;Um$Eaz)3+q%J15f}{~iUn6ORwJ{wRqq2yO3xD^B=yYO4CrBEh zdl5yZ8B4^|Jm${|VfK^e*?k4SnUi4q%}DU>E5N~u*uQFgzx#&oGs=ZM;51Xr27;uD z>6xax5maD2h}a@xJWH6&5|l(FT4OdewiAtbT1u}T9`eOaZ6l}4r!b`;aG zF={KRiE!#8Hk9V>NbxKUB=~Nk*v*8aBUxVEyetXSJLve~i&e=V7kK}5*(et#xiBe& zjWUswsiJEIW{L?BL(xofg%ClZknM<(i_xP5=VGK2VN;EjaG@18mioddOs+9X6Df@l zp?tVHAH+z7}7IZ8m zYu;l}UbaDoiUg4pWEzpEK!Qo4*qSMxDvcT|wuZvCk$TDD3M$YN;4|ylA3$FRd~OuEQRj%z0iu!!vj&l@(uh%XlxCDDBvbS@ zg~^GAzlQ(WRDu0g0j|}yfvyqqROobrL>sM1l!gsO$0#B%HTc#EI+FFE8$|+v80Ej0 z2@%DM;h<|2Nl#;D8p#!ErkE|3^S(=0E0HteC`#tO(L9Mqy$J;70;hVZD$ogKyPZ(7AvNl^S#!_ZugO zQAngnM5AU3NyGETeFQj8=fH0qzgf}5xLm^R7DBi5?hPQeLKnCb&11A^ zg>!<77UTWvfWJ(FbHl?Vkia-$oG91|$!V4g(T?IDPt|3^z&l5Pda>j8%!@KV-LHUnO>Xke*4(~n| zjrD@=dYqFQEv+ti&oy9Q^jI@7G;R@CiNa&)Ko-IPRTy~RLcrm-ejyCJsS4CTrjelk zl}9G?A2-kE9y`0i@3zd1I0=NzQ(v9O=gv1GXSzj6NhY373BKtFMI+89+ST5l&w@g{Qok>u z0!DaCoJ%6l9O+BXosOe3op z{;{VQd3uei-6ZxTsU=dL$;i=(9Fg+O8kxT>Z_j~$)$DNT`AIbY4kq`N1dztz{%+(i zR>|8w3TTFcWfB~I8%VG`I;e=SeC-Y#r==%71CD`d7 zlUO&8|B-tosOv1B&E;Pkk8O~t3NKoD3LUOQdtNNP#>eU0DQ@#Ha3K_|Bf&yqxPk~5 z*;(STspC%Sm>$lncO&IFF%FYhq7wWXG<7q(dX4hsV{3S`j3|pj3o|gT>0B!!udh`@b|qdsA0~4HC@G4;w4+^XmUbj-v2%OA@?P z9w(k`>M+{VIrCvnptL^?e6<Uo+8pWlN= zPvDacNY50RwRBH}{Ep?hQEcFel>?&!uF5ZvV7chyRXM=|_>sdXA8LnlkB)-(lQ?|l zNQ~u0$Ma`B%QuOq{}_fnzjnUlf~k~SV;7ziR85Xlwyvh|Z%cygJX37{&XfO1vpo~y z=Mla8!jET~UZm-0jj^HBdlo68Tw`OQvov)cSa{QsOfAE4GL(y#{K=ox8)W8E@?Ke*3D9P~kniqM154(*Y zI}X1VKK&Bken;+S4m6J6nz-^|kl^@5^g^dsOUl8YnA%qlXAb4}@Qz37xx& ze|e$!awz=Y6HOj#bU&h#X~ajETtgRxC{zNMMI4tM=2b&HQ+TGV1K%)xVM#VDsj(dP z9lIYoj{n{>yk|Ms@t2YR+cgn%Nkyoxm98LbsIiA<=dtI@`;OT&$FJ@<{!mUO-^m-`oc2R9-p~I z@DqRT%pqC@xE|%$M>s&(dm!*k@!efTa;DfFD6%un%U>ya61H}2XPQY7>h_EiVmDvG zlMS_4<5vVCO{<`s2Nmc>jtnT2CpC_7;kes39F^b?ykTd<@lE3CSj+Hx&*Qs}oy&WF zOMt5ozytpo1rK5S+psC~U`w+%6d08xNELT>6vbF$M6*$p)xFWYRD9J^ZgXa@0v^D} zj`)Qq?^vRS=QqLM9XXDl%%z`4;dHS}9v{>03%Km4LaNcjBlz;Z<1qE?-Lo7Vd+0mP z2A0jtk^QqJww60_!AaLrbSx7Lv9okBbh-weSUOP{*7XxhHwxuV}v4xk8 zcu?TVn7z49bZu{_*^aSw*w^t-y}oR@_~?? z%>k=HhZ^{e)MG{tzJX!l;jRk_AH1&Tw*23Tw!vCdY2 ze%-*g1o%0Ku=K!X(75ToK`jA(L8N#edKI_UT5GMf)>>=73~Q6XcWLB6+c)t20Q_9X zb8f7oXiI=!0`U6{91bpt$yn`*z|RM~oNF!nu$(Gh*Wvuj`(cK#o+*B`k_>G@ z$h!c16ZB@M(=ULh>$;jBgqy>%R^ZF~u5Mck3yVcr@oc7^AApl1AIR{% z=i}7#v?9WzORGUkfVY+8RlADL0lyy@Avi^*VI zZXoq>V;h7M0p7dMYI3D9m1y?&dI@0+r}41RYU&KHtA>>idl z^dX%32qT&}k%cRZ6or$}Fsca8mslaAh(d=$Dn6JhvPiQ#QXKxI7~T{9`!mJfQK(d2 z(LF@Bc-@fq%Uxk`Pt`I1*+^k?6+HiCgo`zHrtuwx%QemmCJ|B~Uh(2FptX=|0Rzqp zF(6vdTA1Ym1JENV65)d>9QGmK^z;seuLZ_`315E=kKwCU0dC0qtFiv!Ss3d5b|zsr zP%-y>NfhJ?(+yHzd3kz?cSxareo-AdQ7ASdg~>FT_^1n`Q&y=!s{q$+mG=X+_h&}v7D7?R{0jVZ4d67cF3^RA`=*V9 zCsQCRPau&(kz|_9MA0=uZ!@UC>CRdeXbEuL^8fXb@WmHlUjOAVjP>=$3Ymsp!*M6b z{yOlxmw2acMU(~!s&HVsQip;Unc`@y7-z!pp71m~*Ic?K!1c-h+@78YpTarsFRUPi z!X)zA;5SLowCXkEl4OY$x<<%0h0R>xQ#dYnC0EU*TLRpm{BQ0^J-1(bznv#;i|DNY zzq{gE@&BeP&LK8VnBhJls<*JaI0p6`wnFU#G)!;iynT$HnW z=91a|RjnBYVk`AD^32FQ43zEU8eyO%z;)W!NAtD)Q7O06QvPGR`iQty9=tXdtWbh= zPmMcLCxbv829~TPz;)REnkn^j%epI)zwTwhzu-9)iA=H>VyZ=@Y_q)YQ|i9LWzy0T z;B8nR>cyS6WtG~@tT0>^vJToL@Y+TI7un2QVZp6?eIG2YmXbFiE6#t0vYAv%fHxle zzoPiE6J4QHdwP8ztf-EhdkJaWo)&(iw$PXF;QZsG$}5$x&jG#(i*jEt8`lKXp@~!& zo-_`fY6)W+vV?1<=fxaR?k{%w>D85@yP`*-kIVjsz%ZLX{&Ct8;708* z4VAjPTj9XRPUK0l(BLs@w0*g5%V5F#<5_4ZIW0qw-E#00&c+e@b!+JVLy~@ z15D05gN`FERUlT2DzM6X*Q&tu{A0~N15L}d=Vh6LJS*?38cH_$3AO~dR(sUQ1D=GF zKOq!vo+a*Tx!-ifwc;tO2sAF`e=u{Tv8R`W1EwML6Rg_FN=tz2PXw#|d*+U#pM=uw zPUJ%+Z{k7|2<0i3RUmR#8U!@KFB-{Tp*=klj+pmd2brtof41e8KW|Hb>lzA5BMcmt zTenWruz_Q8=4%xwW+5M_NRTZhbJHt;pDlq85IM`tS_ZQKcBMiK^1t6Efj6fDWk(SX z!a>iK3QS5B@QEXu&PfohAVH-D=ORG)SOxy_urKdga_wvHPmRTHIkt{MiTINI3;31* z*R29oD$rB``i?u9JbcGme9r~%e*(u(e7&QX z{e^jpmH^jne}_A#0;g%%&u6m$kWXAqf@*>&F1v#j4Kg&Z>i*QY`uVHCAIuzC|`2P$`*6SPv#`p z*$5<q=4`DBh4%H8cWsb*F+|?tCWccCv9a{U00yf}4Sp5(>%?z= z-REuXCTwl9$>UFisINi`nNirlk;l5O+&Swgc2Z$hbriD_W)Xorn>Usk%v{LyW6!h9 z(M$YX_Dj#N>ptc{v%&cOtohO{lZAlY%EokXaCJv*tJuW!K|#{tpSHn*ilXHtn&KCY~L%A*4BP@ zBETXUDtlV)Eoc^TRO|VF8qDYRn_2!94~%RH@N<#?8oh)b&aqh9zqer3TK+QV4K&-6 zLf<7KtRlmL?JwOn>@SbdFH=Ox{UaxOuRNd*dV7$8?3ZxcZWPE7rFhTKL;%*Q|1uaTDb4-8~T-k z+Ik}m!R>@7IdYytb`E5Yipo0oY_h{;-5&5#v@lgMF4UR!yqY~tnHNu{bX_{6axOs& z8`Hh{J>2$IeSJcq{RtcOwMdsyePVH+Y{mTkyEy|kLGk~p85!%u7OuyapK{dzJewV3 zbSeOaQK?O0y-(l2Pv7oKA_8di3Hs5IJY|9x8vrBAc1P*-iNmb9+d)(o!}ql8XcYl~ zs=j$G!4E7;qeHSd$bVFEc*?zts)_*ALCFYlZDAr64NK7d0aMCOJ3!<#P)O5!s_e1-KyHhItk7>u?^vw_)h=~69twNthSRKtdqJZ z=locjyh9wE$5>T;SIubeS-!uzHhX_HKZ}0cwz`vqXX-y-*D;DZl1pT>ZFcEx<2E%b zYPt7UtHom7wgb9?E$!2XTE~v~&Eh6IWB}|inJMbmOtunN39l?{P*g)<*|q~|sj<6o zQD*isWQe8vZdrUYrQ9mgGELZm&>-?7IA;n?!`2-5b9SZg%j=A?4q;=mykL03e)mQ3 zrC75sOihSG&Zji6j_#Vp^k{HvH2|=)WUbK;7p9KPMEL5Ora{Z_y9B9@*V1N)9^;otAxEXY;{Gnb_oU2Fd_*}-%^aRF2>aq(COh%x-shx0N z3=W!(r=%t-g0IFGuP=ATom&3*)WL`>eB5XR+5EhQ=Ro4Bi>1C@P*^mrFo)F=LY1fj z$i=Wo3_?+H)ue>*iNs!8^AJxcR}3OhQObpxgq=T^Y{myV=+SYacRCo*8V&Wst7^ikEw)qW&^8bjb=7-eT7 zg8d`RD#E>^R{9^O+N*bAwptUzGp_o#G6;t@q)nRWr??o4O9^<|5zJ$Xra3YgKNgM- zYu`9b=KFMvvm|NtE5((1N!;^Cw$W#4fMG~cLGK0veF7_M2-j$sgZTdKAVI?IR8(RR=QmHn*MV& z`oE*X{}Af;TO3hb8M>f1L~r7ixd7sgg_c#+)-Q72N-P%a`t#iLaaY%eXWStGs;whu zEwz00M(txnnhsrj_l;xwpU7vLy8pa-;1!86@Zi+GcRLTzdWfK?S2C=RulVaO{OZdJ z6-B_)nd;rUdulO1Il)+60T8oS2AO^x*Yt5Z+3ql2sk&32#9~WMoA2f_9DqJo3S!e= zW*FA0R61Y{5Prh?3MPpxnpv_g(iz(4Z{${!P4zL<2h<=@tTSWjA*Dpn()y3(3Bs53 z1If8$R|LEH?KrASV>vtpl( z{PB2-;3ZFLUYsG`{vXac_WMJ4|*ej8xC79Q;9T=rVdSI^=E*3lUhITnGeJ#Np;@^&6^K&_YDo$?p;*nD(KuWLJSVF#}>!J2~r%|`6TJNedX9BJlD;npiZ!?&*? z8vt#q=<1{6f(VM@(;`Xeg88mo7*rBXYsQ3%KDE|;YPy#Y>}{tl!+PwksuoPR7mm>OLIYGzIcOGC4Ft(Zuy@gJl&9}hN$@K<-yO1?68ASbg~8^jns4&Koq5E%N0BA{ZT;;tzfgK#+~IVuWK(1K)e zMs-0T@%IQj8;^uZ?&ODv%a>GomY13%R%Z^m_MmkdUO^Wp5kPMZ?xPl1XDYgMtCd}vXk+)+m=pH;0GL9eQCCB;(Sn#VC6d3`$wxI`=?swl{8B$5 z=L4V<#$Co%hZ`E`$eckrZ(>fhJ)k7@9rKRU4FXQJaE&cz7;d>w9T_Xdm4jGL5~&S#BT277lu&?Hy4B6g9gg7#l(HBX}_jy1#`DVqZ{?&`&GEw~@0f#?U$JnOdLR7)0v ztu3TtrS5jsx**rqQOSaEnyZxn+LXqX9j?ek78Y2-RHHh5QPrExDa`MaAKXUU}2~A7S`?RhNe}SPNJ&MYJV6 zf$V=P-OOL7F}ZT;Hskt0%50`4mZTztwPM{dDO~}-gZ*Tn%J?u=aR!d0>Ol@o2%Q^r zX3Bn=BwqU^pK^9coMMMDFj;Q(+R_>=e0}|BR}^+@^0ckq zO70J5Rj#w959;$0X}7Dhp?wGyXgOFu*jUIt8A_<&G_h1PCr? zCG#Xrn7!Y-_jN-be(`0+e;@Y^jakCqYvf5Sh@&b;PsrcH|M0nJdfq{~ZXK@~srdY~ zsBLUY7fttzVBuIe{A}acV>BQ`cP$DDU`WP(p?rQJ+)bY{7sIo w-586Qbx_Mh2X#`9f=kca{`ElG?PTppx96LvCNC@7?=C$EaSmzs(l#LNf9Xv6r~m)} literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-70.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-70.png new file mode 100644 index 0000000000000000000000000000000000000000..44b0af3a4693fbb9210b8c705f49efae4257d847 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$lc1=YnBh`k51>$(r;B4q#jUpo4H<#FLkqt8=kmxe d05T~75AqrM85p~MHratp@pScbS?83{1OS0zBW3^q literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-71.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-71.png new file mode 100644 index 0000000000000000000000000000000000000000..714ceb099601ec63e621031a8e2678376b65788b GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP$lc1=YxZ5J-dqANuPZ!6Kid%0F8ZrWThZcPG&*hO{ d0Ax}E9^^ChGcb1jY_bEH;_2$=vd$@?2>{XNBp(0( literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-8.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/explosion/explosion2-8.png new file mode 100644 index 0000000000000000000000000000000000000000..4cf48c634dab2f609e8d79bf794869f59ea0d56b GIT binary patch literal 1742 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 PhY7%0;VrAoi4Xn*IYxms literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/.cvsignore b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/.cvsignore new file mode 100644 index 0000000..085e8ba --- /dev/null +++ b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/.cvsignore @@ -0,0 +1 @@ +Thumbs.db diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_0.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_0.png new file mode 100644 index 0000000000000000000000000000000000000000..7ddb683e3cc1519e858029e265f0a0729128876e GIT binary patch literal 3859 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 VE@Ts7uEGES002ovPDHLkV1lt%b;SSx literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_1.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_1.png new file mode 100644 index 0000000000000000000000000000000000000000..5d683a21631577febdf6193516f4299aa722ca0f GIT binary patch literal 1532 zcmV00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru)dvd$A{{OC=#2mX03CEi zSad^gZEa<4bO1wgWnpw>WFU8GbZ8({Xk{QrNlj4iWF>9@00m%4L_t(|+Ra+qa@#f# z-LrrsOR{7)PR7ople~2LPkrsL^jDj~ z#4o@8cG%xldCNY3gFpa*e1{iAfU0C9OA4qe@ML>6$}A(> zr{+NNHBS$~z=(*dAv2N`rfDhytvpVV(PZ-Dr=Q0sGYVTj;`jt!`4Ip7<#~b251;0X z^THamh50DtXf&QoX1m??;@$hrw|_V5Re-tSK?P{Uj9pMP#-7YhlS8sRdt*oA>wo?N zl%y7CCetiCq{(jkaIb1+^W|*52yhk#--wi6m@+#s-S4*d6ilb5i{-hhq8I}rlq@;y zwpqGWV^`N-r_=dtzPP{LNN6lnasb-|q)P?I2r^3!yW8Y`0o|g21=tjqYp|Id2Z1f)r^Pgx)Xsqbgh65}V%(ge1FAx>AfPD<*LJSZh5P5ub z2el&LQzmKvoMmBiZ5fxLynrY$A@_uWdK9dLz;it?(6PW&qmzCJ$VP)VdkC8`$nU_2 zj0GqRfV#5^Mo#H_mjZU3f;C?fQFkToQ?Mu@6`amr6m+j1J_S(x)6IoRb{sfJ5pO~O zd2$rOku(sAL@R+P>DGde)@DT58iSc|I0WF77)RRYlsnwy>j!|EqMY_usEcD zOvPk}u+|WZw3SRoWREy<)f~ilA~T&VFi<=c%OC(U4uRoZGg|ttmwM#K%cmW`y}02DMF@?s3id7G&Lbe1n|@jjQj$o>CXWrHFBja-P$RSdBq zfmnf?RlidmVaw8^ zZTYAE35~FJm!6)&jC@gXvz+qITs!H_$79G0i$--Ti~0~?u;K7xX%=mXsI)XH2)r7V z!+^1(_4>@C&%I3PL=R3{Z+d-AJzofmaOs=7yxfzlM}7`;Ruf=V^y-joykP7a&ZvJy zq)Bp$ukm(8UsPfzU>E`~lZ?=7+IsH*4I)C{h4fuxfc-&0knk*LJq)G5E7-nz1Qk>nXRt>9*xHr@2<*Ot@g&E7k=l#u={ny+Pw7+F-;D)H{bq9 zll^A1O4H=({U@l_3K^^jvUI<`{tUtGdPHh0_^6ezkOTcXs*gX6K*+=G<_pB!sD+v= zO$D$u4=@x-lbwi_v`<^f+CE6n*KmwL(j*bd1ljX0opm+BM)2%i{afQsGc+m*6)_@O zIwMPyeU>Iw-UeG}nxg41nt4y>*Ci+dQ|jhOyT1PY_~X#K6Bx4T4Es0i;`}N(>>ln` i^Tk^=ue3=q;PoFbz{00006VoOIv0RI60 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 LNkvXXu0mjf;O!wC literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_4.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/ground/blue_metal/blue_metal_4.png new file mode 100644 index 0000000000000000000000000000000000000000..b5f114160170f8034f7428a28debfdfbc01e738e GIT binary patch literal 4540 zcmV;t5ku~YP)00006VoOIv0RI60 z0RN!9r;`8x010qNS#tmY3ljhU3ljkVnw%H_000McNliru)d>Ux88oz~G422W03CEi zSad^gZEa<4bO1wgWnpw>WFU8GbZ8({Xk{QrNlj4iWF>9@01+TbL_t(|+O1m2j$K!B zjL1CqRTW8zl*rZuq33q@q7AeS@4WP1cg;IKAHm)bYmv%_0w`!O48r5+Zz5UL*9=DhH-~Z#kM6A~@uV@DVhr{`u zd-qAc`|!QYeD?Ip%y;84-+mpFV2xgqGE)iGg)}oW15iWC%sE;~N^FZFY;#McGNO;| z+GT=!yZhEVq`iIr-NV`W<&$q{MzYD-dpdy z^X~KSt{zLW8%d%#zPSAE$rl;x7oYx5WPj)3djM4zkTi$c7Pl}u%1Mn*hK4#`Ok7#yK5iA*YiNCE)5NMktlpBf1%B^wu(vnL?&SG~KAmdlUjSv3(nT z4cEx}i$!SLlS)|g0VDu2AaKK5Gc((eGIvFEV$X?vm^qq&O7rOJ5zqhwxui@e69h3< zxgN5c0F6~IPPrLUjmRKm^gatJjdLqc19EQ?%$v97?(SZ!B(o9*Gb=D+58J=`&14QB zQ@!^p0!HVyq!A#DG&9Us-=GpX$DNUa2v}tloyMxu80*gsdiMm(+*>=eWvS6eMDJ@v zuLTrp{a#@pvl#CxdMYEsqH=HElPMS=8Ck2)b{tZY3SpEYM}(N$h*3Z)P{=(uloBfR zaJRNB%d#w_MfS{y-XnSy4gfiUNjfdT$d8S!kR&BkSvavQQkhDCgm{G_aoGTM3^hgpFc9J|hiPk(@B>+hX+54K&Gy9CQRw)h; zyM>?sw+6~NCDxyTte~j6y)o6c(O6|d1t4bTg#hkLYi%SDvKU0Y6;wq|L`19^eI+A0 zDKpynMRV`w%IxdQ-j5L-5^3hmy_qkx!Bj^vsj(YbyLxnkFv&%(u@k- zV_mPMzOL8B&z9w&)br<8&!1f>}s&RLd{ zX6~LX+oB9XpZ@i~ApPX$zw7;Yef{FMzx(H3{N3+9`SX82fBNO;pZxywPycv+aqs89 z`X?x(9|6!{Mw3Yd3vFk;Wep&^K(pm=aBl!IB4RD!Zns^9Z8f(bQEqfy38R-N+Z3jI zYi((5p*N5at}eg&WfqsjKpGAn$yf=85-5vOzsvVF3lal)2nYTE-v1E z_`%u5-RSFtxbghw&z=-VjOZR68O2iVlv>$vUpKSz4y#~on3?%&o5hB+H#gkLDbOFrAvll#vm9ZK^r@^V-~kU zh$P%Ot1pN6MpnV9vQvVlziyIV{U^=Dv`=5mQZ(C21h|iHvCiCSFlw5HSEVjfjy<74)+@vTTxd zT?GxYB~c}8Ow!r;-Lvz1H%&20`s%Cyy?gi3dmkRmthMFgqmS?0yWiSk*2p#(*D2b_ z$t#SvK6ryOcjCpHt|{hkgPZ7-+L66tl*Q@buIBC;{@vx*SC?Pz1F2BsyQ?SXckkbS z=L2u;&fT|LTMmbFUk*i*m0N6ULZFe!6FSnk$pCFY)NWa#sYKl+(8^}mX06jI2pFu< z43ZJZ-j8Pf^_PGC?((bi^Ej6o77=@(hT|OSrT61@@WLjoI5o2p@q#aqZJxo5(*6j60w$ZUHhx4=Zi^Ji} zye7aw@KFVJ?Y(cFg(MC_I{xjQ$eLJtMI2>lm5`aOxwpm0gnD0@sv(+9DpesVWhx>v zvofR*w!ENaIV^{>)*3-GUzS5#mPmmy<5eVEYejGh)P_qpiqnYcx$>vczs8;3+@^w> zjDXu!czIz~sF1z*zHxI(%MdBnQcf2cy4}AasrG6^ zWrLkfxo%iq%%aK#$g$=SKsU#7=I)s>cp|-=ugVkB+?UoC^D09c4HrnUrphXeh(0DL znPDb$udp5fa*_nrUf&a%vz&E(2ei@4x-;|P@@Eb`WQ5uP3XIZLb!5t2qdA8c#+^a0 zjKMrdahxl>bJ-#yNZ53o%xvrcw-yU`;4-&qw+RW_u$`y2oVA@q6NyO{MuUi3LB;6m zoNDQ?{@pK1R6lwpiFXBgxIl9uoJJ{KP|J1I)_NdoCCuFfQ}(%j zHP#V_Z*Him+8Y%Z8s0QBY-d#nuvFQUQzxWAW!}nxQ_p1z1PP?Md-Kh`Df+2Q_eNhT zeu`lAu85d5jyvgx&05rrexRn3r?uv8O3Sn$bM_X%nwq6WRurAA#TygQoZGg#W+oFe z%|seoYZcJP<2592i@OUbW1`%#%`@XoGB?0|S7o*7Ke9EL95DCIa_td0=rqk5GZ`h> zapFX`+-am#8m}B8$>)A#kxdQLH(C5O$Htwz4)ZLF^ZB!KANs#$@nxjIEAZxyl|4wt(b4L;&MdM`t!*3d|I*F5(y;B)KIZYyM&HYnKyejH<9T6BDJ{@Nz!9dRpoMMJWj5nUD z%yK^gb2D!Zz-Wz*jIO)fTbq4YCv9u^k1fKf?@?vsdk$^2Hyk6IPD(vQL?g-QloI)l_64Lh`*?S$Go&?x7zQJOQQe~fvdmPBj z=pm$;dGo!N7^4}7%L3D%!LAj@Y0g$p(c1zbGO}9BHxCAqdvj8+J@m&+Er;`;{QNhq zEk!VQT9b4etxNY)lTYcyk6Jqbv^dAkK;kb3sE{bQUR#i zi_>4yE@S!QpZ)soTW_!H^&8L3Er;`qJ8y&b{zpG~>+N?=a~Q{d+?QozyqX72=5n5j z2kmr0k?npw_I~VrEkk>rgxR7*^Q>Gd-rMn@X<#PAAJyWV7GQ4-ATif z$6w!n@aW->K0H6abHZkTX3ZO`Lo;2PG5V42H5>*Y6p5%Bc#OTf$g+`8vAx_NX7o9f?sid$LRMAtl+GwhJ6V(zWAR+XfV z!R(Jq%yPTa&1^uwdh!{-D{E#4WsufxHkeqr)cZBC^nN|v+Y?u<7V6Z48?_qBum_J+|$lAz3}JdTO2-*3a`p z>xT|%8^PRl$ a>;C~1^i$c0000WFU8GbZ8({Xk{QrNlj4iWF>9@01Y}xL_t(|+U1+sjvQAR z$G=*7pYGXb>@1kraR?CLo=4z@SKz@ASG)sUAR#UgiWI~a5J?Cjv15B|_iVj)ZQT4n z>E}aDPtSM>l3ObEOx3A#zJ2+h(`Mi7C(`weeUewqY#iKc=w9_Y2p~1Hme$NA5DLJB z5Z4ImrCCw>3I)(IvrRKwn%P1``}&10x01-rN-!1$LgL4TRbI!EUX}pj8iJc<)|Cas z5Q;OOi=I@>#F#6>xX^;*>oWf$1VHm6!x6Md3+RdHrk*#=EE8j~Tq2b)D#Qs3wCvW? z(AaVXeN8>j>x7i9!Ju6t-5BGtAlUJ{B@1Yp*#?ASc()zIrC9&F_MQ2T#%5+VTj3fT z64L0p7C;}Zld@~Q0W&ob7X^W~XJ&nk*_1|_a1Rr~nXZQB$rUrm)Q0Y#)i57v&90g4 zo7wp)7fCPCzMGj#y6)2uV?N)+%-+!7V+B3an7)YFGqY37@0#x69nTtEds|no_sbfZ zJ=pH+d0p&S+XCEl-Pf`U1h6M9j?L_`nY}HB=4N)Jce^s(R1CUR`TQNNHNPz!JY-$n&V7k zw=`yKW>byp=qhExZ8N*AwVu@YeQajC64EWb_oakiJx>-WC4`;`U5fBfP$QXKYG&_= znMCjO#9#z1_jIMQo`%L(^6$3ZS?JjhB;W^fF+)IXnAuxq_Cvh$g_+%#dcy3)Xw7;Ec2n)kM}=*)J^>_Foq&F$vi6Ahah^VG~f*V<0kO$q$RiaRqi z`?r~WvLa?(xemys;Q<)BCqhfj;i<~ad>~CE(0)^YPc_Ge?)61%rn&aTybG>pW)IEm zD~)OD*_&qeu9@A{ypPQ6uV(g-3u4uC6+#PXtPPDnk$*BBPUVYEe1$r}t2R$@UBrY1 zQe{`daVuFsFfGmTzBK+VJ$qzkf0pLgW_}$3Fo2xO9D68g&ZNB*W#V& z2{lIz;Ehfy*Vzl14M}M zUyDdDV;Kx1&9ejZ&k$!eHQ$!TPo#`{3XIcB%5<-1mYTP^iVJuFv=H&R%)YNUuoS^w z<}NTcmKNt4cPat46Tg_U7ilkyTo z2DXnP#T+p!3cpbmsaOUrEPSI?(-)Q z@Q0v%-^}i)Ai62qVrl(Yb;R_t7~l_gB#55!?H8KhSogjs$sTLmnR3k&cvKEz5^wM%s-Kk?~0C}=zf8QECy{)RT7_G)DWcs^CkQ>L0*1a#Cj9+rWWw} zy#r>t(o!EmXrKT%);MSCRPSs^gUkY<*&pkBU}k^PJZ)(^29Pq=T8|YZPvMGL*czub zwf{mBcz3m}MO%mwr5LR6P9gz~#Pk!5e=H_X(ML>R3Ae=buC(8S^~_Lf%v25T%QX+R zeu9>HtZO1VVz|OW_m`KsK%s#Va&!lvMFw-;0>c?#r(-}>BR%`72ElEJ5jXn|;>%Pf zoa^}wGy5RG8$BbC|V&; z5~=mLFx6xm@Ha!_Q>ZuZAejA8?;WDg?@IuO@XrL%+mYiodXEx$e+GtjfgC%XBYo$3 z)__%4tFl0hBE@s@76Q};tYU(A(9oDR-tj`{r)KsaJ-a97-_U$1H0#;n3Gjyu?X%S| z)kWty()=R`C`VOUYXM0On%aW7r*H|@(XOEa^?nEKt;1RaG5oHG`dV{t%R>4Zo1)-~ zkO>mdzy>Kny|Sly9!LQ9lzEO2hnDN0!VWnPKvW!5f{7O0M-V$h+sZ!Q-`hqmH_Yuq zu29yx;2b({L5n$*;@2GX|3aCDioJBlC=I~Pr51S$+Usb-Ha0bB2?M0G79zUW@pA>D zAqbD~_d|gh`*Mw@1piP%bIWXCZ(#sP&I8}i%_?ADh|lkr7VJ>@z(pkbP1_|E`(6gY2`sjsOZY zH$&w6mM(T^9xIw4gso^Q2E4(c?{3JI7H0Ny-Fqqq|0zWGTvsMKDx^sdoZXtuQMZnh zz(v+Zg)6kc(*R9L5gVeK_Hqey$eGHJ9Y)wm>PgtY4Y0=|NW~d~?3M&KMT6CcKoYn` z8!dOXE+m#nI|nlPLu@#B%5lLI0630CoV!Y-XN1(xVE*kuu&d~cP+2;3b^x^cDKJRi zb2vbqGL>SM>sUZ42Hw^rTL^+)caKnP_?FjFOnGl#0QlI}`zJt-n!$G4mn)z+uMd(H z8?b4x)9mL9ybqYKD*$%^M^XHmqM(>S2&c-qr>ghg0&@)P{OwM2#Yr*2wlt+JW zD!dNZ*Ti3|&CLW#ZU-ksQkY&99F*!}SLj6FTLM3}6(E<|_xnJWa-fPYf)H{Ee$i#U`(?wQ%I)O@@rE$w3N0&Y|wmBo7hJlHo(gdNNQl{v;= zL955W3KH}l_s#6@uvR~}R9hHbW&tg1N|q>qdh+vQEf%W`y(7~n3cNr!mZ6LdQ&akvCXIh7$?pp)zYDN* zuEnMZLQ65(3vzmiF495H1C+R3&GV7ya8UJu1kpsn~$S@{VMxcNA=LnAsGkIdTxy0)WchW3L%HXu0Qdu|w=cb zpS>Q5B!D5_pJGklPZ-0^D%3Sj*M%{lLJ^aLu>t`kQNX(`B4!A9GwdSG(BVzxG93uk zAnYl6`4%={{v|=|0jMo?ZwiGi;onn$wjp0DgJ2Zk?-inT8^Li~fhqyRzKwn=g68Pj z+}AfDfHC$0N~E`ua(Wy4exJ(J{a|Gu!7dASs0(}cgz1$}iB&amf#>)9L|79{E&+cn z;FA+HByKg%*h4^I1=5>i`uA}f4wY8R>{34OA*rgS%`8z8M>saOL{9e4 z5n#3^dW^j$v*46Ub=`AYYv;EC?Kz;@0?j89U;+zT0{f5Z{QX4;pbE0Y5b16K(84X` zNZ+1{ZmF^x=~UMPS;n3O^jO6e4>Cl+3s{gjj?l#YB1pNH3SiwsQW3Cx-@GgVcIE*v zvA{NUiH(&UDe4FT^Bh(cBd&CysHI{?AGA!>i!=e5J6&u2f+V?u0Adt1bJX{xJ^Onf zCm;kLdTNs+G5{vFYEVnCgBFy&-c|2rOswKECe95H19cQ^}# zSFKP;2}b$5plVIj`Gx&ztU^V15z!eMs1sz1v7Q~HTU>X|;sT-A%W#2p>V#?qxY7oq z%qZ{X8`(GT3({Bh%h4D+y(d=*QZM`SDt|dTN7R1pK2gmE>T4;4|GUqB0dqxN&k25; Q?f?J)07*qoM6N<$f~EeBh5!Hn literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/radar.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/radar.png new file mode 100644 index 0000000000000000000000000000000000000000..29453c30b5929c5ca6cd3d9212953832a8ee9ccd GIT binary patch literal 833 zcmV-H1HSx;P)004R=004l4008;_004mK004C`008P>0026d000+nm#LZ50008a zNkl@g! zKmf6@v2jWu3tqo|1;uh8&Ie)x5XZ#C1T1*=?AZ%IYU2O@{~us87-S|u0I{&Mi+=s~ z?d^IXKM+km!P(h)zK@R&0~Z$;io~~X-yF7V*;2sB$e0K;d;zkYy1M>)E-ulp00G4E z?%mxr5)xXa&z@Zg2a2zR$~*Y_`hpGJwd**;+qc3f1`7+nWe5uk16ep9X!rx5;RitC zva+(_Qc^m;FJ4^h1_&TV6BApI*l!jVe#ZCjA8iJ?{L7cOhwAF;Y`1JV&hYrLJ_9o| zs*C^r{RTATB7={QB|}qF)8Qvip4e$<=&u(Pl=J=b=i~p=rw_3L1Q4T|8aT$=rKQa( z1O;Uoo<80Fhlz=iMOj%67?wYQuF?QXqZ$kh3}A5F0HzjphP!tkG5q`Y|Btk^C(HZy zkAeD6b=vju z82I@`7&tkF7?hPg7+6_V8LnMB%y8ktq&pWc9#sXY0SF*Q0|P5$J-2mqB2=86a~T8$ z8GxD@7


2BEt5#}5XE&z~89mNGEBf6u_Mckg6|D_2(BIe#8vCZQy1^hY zM_5=U+1@^nL0{jEK|nwNMe@Uk4-6MC?qWE2a1t=ZJem98!GjcZ0{{YuQB_qHT?`&9 zGBPqMYHDf>OiWBD694}FW4Lwe7SN?n?f_}51^@&Qqnw-^E`vd!T}VhMpP8AN6It-@ z-@o7Ay?ZwiSf*6s(g+YhjKIW=&tS3vKmaijRze;C2q2mn3=m)dipK1%r_nen00000 LNkvXXu0mjfmc>^) literal 0 HcmV?d00001 diff --git a/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/turret.png b/代码/workspace_robo4/robocode.ui/src/main/resources/net/sf/robocode/ui/images/turret.png new file mode 100644 index 0000000000000000000000000000000000000000..354febb7f454aa8285dbe089e11b956d8b403c23 GIT binary patch literal 1188 zcmZuxYfw{17~PxPTu^TGrlTZ)#hWS*D?^A#ilTBO2#Ey*#@a9{4QWlwG*ey`OeD<> zF9TWz149%Uh>T?rt;3^I0U2Hv)t36i(0N7GVWFo|MaEM$nINyHK9s~jXSR5+`pt&^Hkx&j}@LhH7(jH`gDiU1OhU&pKrr_|hxq zX)16f-E)l;fxXq1Hd#7fr82);KYb4nR1AuL!{F4^)W~tx&gJa@C6bw)9Uaptfd%a? zW;4mD^`=4Jr}Ctv`}pVFxN|`^|2?|_a?9Vxhc&xP`_H-vBxwDsUo4hm-`~5ZkhN#} zNZ6Z-_>yLvpaP6W<8r`9V6d~ZGq|axWgC&`#sEm9e`PUaU|=9!M1hMuLyhlP^^S-Z z+selMG8`}r0fI-vM`4Z3rTHWy8&!r^X9A>PYhyK)H^y_+B-B<(rdMP2c$onkrrtkOG4GejURx?mj-p3OHf^TK>@lCo9N70 zd!}3K!0b$vC~-U6$`@jPB%Q&{G02Q-?k*ch+l{2>p$qW3U8`gi+lU_p0zDLx{X7>(baD8 zp2ji*0~4+7@78ro`pDg67a2?`5tImhoRN`%^w0Q710!7E8X)N&EU#~2`n!ject;EF zSbD-4#|h|I<+o{*d9ltH3v8l%c1Y*^BL6Np&mt%}Q(UieWE=GP5ocn!dq7nRt2C7c zd8cenr*3dfbXl^D$3O|Us}+R1QnCE{!Y-y*!w-Btu+pYYz8n1fTte}|UdRY+b0g^~ zpSE+nu>Q`R?mL-$i2#RoPEeAV^4VjuWj&yPuuJpz9AZF9{@56v%-Ce-N_m%DDlzej znBm%R9fiG3s}N~Rs}8lNrqmr-vfn+No`7ZX?*!0*anfU5*vS`v9=kJCA_wkQH>+R# z{PkgZSJ3;A;ij@?Z`lL1ps?^_0c#7GF~4`^kbeIKHbBt*BJLI;j#3)2k{)5Wl4T|V z9mC~t_zx-K#B)2_&;iAqF(2{^K`4;W^&5;1zC)07!)GLnf2ClXcIe?tIL<^EhB*ut jv#?QDveC=+{}VAVy?)eUXq~ + + super-pom + + + + + + + + diff --git a/代码/workspace_robo4/super-pom/pom.xml b/代码/workspace_robo4/super-pom/pom.xml new file mode 100644 index 0000000..3a29487 --- /dev/null +++ b/代码/workspace_robo4/super-pom/pom.xml @@ -0,0 +1,179 @@ + + + 4.0.0 + net.sf.robocode + super-pom + Robocode Super POM + ${robocode.version} + pom + + Robocode + http://robocode.sf.net + + + cp1252 + 1.9.2.5 + 1.9.2.5 + + + + + net.sf.robocode + Robocode Release Repository + http://robocode.sourceforge.net/maven2/ + + + + + net.sf.robocode + Robocode Plugin Repository + http://robocode.sourceforge.net/maven2 + + + + http://robocode.sourceforge.net/maven2 + + false + net.sf.robocode-upload + robocode release repository + sftp://fnl,robocode@web.sourceforge.net/home/groups/r/ro/robocode/htdocs/maven2 + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.3 + + true + + + + org.apache.maven.plugins + maven-clean-plugin + 2.5 + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + 1.6 + 1.6 + 8859_1 + true + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.5.1 + + + org.apache.maven.plugins + maven-deploy-plugin + 2.7 + + true + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.9 + + + org.apache.maven.plugins + maven-install-plugin + 2.4 + + + org.apache.maven.plugins + maven-jar-plugin + 2.4 + + + false + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9 + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + UTF-8 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.4 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-resources-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + + + src/main/resources + false + + **/_svn/** + **/.svn/** + **/.git/** + + + + src/test/resources + false + + **/_svn/** + **/.svn/** + **/.git/** + + + + src/main/java + false + + **/*.java + **/_svn/** + **/.svn/** + **/.git/** + + + + + + + java8 + + [1.8,) + + + -Xdoclint:none + + + + diff --git a/代码/workspace_robo4/super-pom/robocode-license-header.txt b/代码/workspace_robo4/super-pom/robocode-license-header.txt new file mode 100644 index 0000000..ae134b9 --- /dev/null +++ b/代码/workspace_robo4/super-pom/robocode-license-header.txt @@ -0,0 +1,5 @@ +Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License v1.0 +which accompanies this distribution, and is available at +http://robocode.sourceforge.net/license/epl-v10.html \ No newline at end of file diff --git a/代码/workspace_robo4/tools/.gitignore b/代码/workspace_robo4/tools/.gitignore new file mode 100644 index 0000000..a65b417 --- /dev/null +++ b/代码/workspace_robo4/tools/.gitignore @@ -0,0 +1 @@ +lib diff --git a/代码/workspace_robo4/tools/.project b/代码/workspace_robo4/tools/.project new file mode 100644 index 0000000..d48fc19 --- /dev/null +++ b/代码/workspace_robo4/tools/.project @@ -0,0 +1,11 @@ + + + tools + + + + + + + + diff --git a/代码/workspace_robo4/tools/bin/ant.bat b/代码/workspace_robo4/tools/bin/ant.bat new file mode 100644 index 0000000..6d57c81 --- /dev/null +++ b/代码/workspace_robo4/tools/bin/ant.bat @@ -0,0 +1,226 @@ +@echo off + +REM Licensed to the Apache Software Foundation (ASF) under one or more +REM contributor license agreements. See the NOTICE file distributed with +REM this work for additional information regarding copyright ownership. +REM The ASF licenses this file to You under the Apache License, Version 2.0 +REM (the "License"); you may not use this file except in compliance with +REM the License. You may obtain a copy of the License at +REM +REM http://www.apache.org/licenses/LICENSE-2.0 +REM +REM Unless required by applicable law or agreed to in writing, software +REM distributed under the License is distributed on an "AS IS" BASIS, +REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +REM See the License for the specific language governing permissions and +REM limitations under the License. + +REM This is an inordinately troublesome piece of code, particularly because it +REM tries to work on both Win9x and WinNT-based systems. If we could abandon '9x +REM support, things would be much easier, but sadly, it is not yet time. +REM Be cautious about editing this, and only add WinNT specific stuff in code that +REM only runs on WinNT. + +if "%HOME%"=="" goto homeDrivePathPre +if exist "%HOME%\antrc_pre.bat" call "%HOME%\antrc_pre.bat" + +:homeDrivePathPre +if "%HOMEDRIVE%%HOMEPATH%"=="" goto userProfilePre +if "%HOMEDRIVE%%HOMEPATH%"=="%HOME%" goto userProfilePre +if exist "%HOMEDRIVE%%HOMEPATH%\antrc_pre.bat" call "%HOMEDRIVE%%HOMEPATH%\antrc_pre.bat" + +:userProfilePre +if "%USERPROFILE%"=="" goto alpha +if "%USERPROFILE%"=="%HOME%" goto alpha +if "%USERPROFILE%"=="%HOMEDRIVE%%HOMEPATH%" goto alpha +if exist "%USERPROFILE%\antrc_pre.bat" call "%USERPROFILE%\antrc_pre.bat" + +:alpha + +if "%OS%"=="Windows_NT" @setlocal +if "%OS%"=="WINNT" @setlocal + +if "%ANT_HOME%"=="" goto setDefaultAntHome + +:stripAntHome +if not _%ANT_HOME:~-1%==_\ goto checkClasspath +set ANT_HOME=%ANT_HOME:~0,-1% +goto stripAntHome + +:setDefaultAntHome +rem %~dp0 is expanded pathname of the current script under NT +set ANT_HOME=%~dp0.. + +:checkClasspath +set _USE_CLASSPATH=yes +rem CLASSPATH must not be used if it is equal to "" +if "%CLASSPATH%"=="""" set _USE_CLASSPATH=no +if "%CLASSPATH%"=="" set _USE_CLASSPATH=no + +rem Slurp the command line arguments. This loop allows for an unlimited number +rem of arguments (up to the command line limit, anyway). +set ANT_CMD_LINE_ARGS=%1 +if ""%1""=="""" goto doneStart +shift +:setupArgs +if ""%1""=="""" goto doneStart +if ""%1""==""-noclasspath"" goto clearclasspath +set ANT_CMD_LINE_ARGS=%ANT_CMD_LINE_ARGS% %1 +shift +goto setupArgs + +rem here is there is a -noclasspath in the options +:clearclasspath +set _USE_CLASSPATH=no +shift +goto setupArgs + +rem This label provides a place for the argument list loop to break out +rem and for NT handling to skip to. + +:doneStart + +if _USE_CLASSPATH==no goto findAntHome + +:stripClasspath +if not _%CLASSPATH:~-1%==_\ goto findAntHome +set CLASSPATH=%CLASSPATH:~0,-1% +goto stripClasspath + +:findAntHome +rem find ANT_HOME if it does not exist due to either an invalid value passed +rem by the user or the %0 problem on Windows 9x +if exist "%ANT_HOME%\lib\ant.jar" goto checkJava + +rem check for ant in Program Files +if not exist "%ProgramFiles%\ant" goto checkSystemDrive +set ANT_HOME=%ProgramFiles%\ant +goto checkJava + +:checkSystemDrive +rem check for ant in root directory of system drive +if not exist %SystemDrive%\ant\lib\ant.jar goto checkCDrive +set ANT_HOME=%SystemDrive%\ant +goto checkJava + +:checkCDrive +rem check for ant in C:\ant for Win9X users +if not exist C:\ant\lib\ant.jar goto noAntHome +set ANT_HOME=C:\ant +goto checkJava + +:noAntHome +echo ANT_HOME is set incorrectly or ant could not be located. Please set ANT_HOME. +goto end + +:checkJava +set _JAVACMD=%JAVACMD% + +if "%JAVA_HOME%" == "" goto noJavaHome +if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome +if "%_JAVACMD%" == "" set _JAVACMD=%JAVA_HOME%\bin\java.exe +goto checkJikes + +:noJavaHome +if "%_JAVACMD%" == "" set _JAVACMD=java.exe + +:checkJikes +if not "%JIKESPATH%"=="" goto runAntWithJikes + +:runAnt +if "%_USE_CLASSPATH%"=="no" goto runAntNoClasspath +:runAntWithClasspath +"%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% -cp "%CLASSPATH%" %ANT_CMD_LINE_ARGS% +rem Check the error code of the Ant build +if not "%OS%"=="Windows_NT" goto onError +set ANT_ERROR=%ERRORLEVEL% +goto end + +:runAntNoClasspath +"%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% %ANT_CMD_LINE_ARGS% +rem Check the error code of the Ant build +if not "%OS%"=="Windows_NT" goto onError +set ANT_ERROR=%ERRORLEVEL% +goto end + +:runAntWithJikes + +if not _%JIKESPATH:~-1%==_\ goto checkJikesAndClasspath +set JIKESPATH=%JIKESPATH:~0,-1% +goto runAntWithJikes + +:checkJikesAndClasspath + +if "%_USE_CLASSPATH%"=="no" goto runAntWithJikesNoClasspath + +:runAntWithJikesAndClasspath +"%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" "-Djikes.class.path=%JIKESPATH%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% -cp "%CLASSPATH%" %ANT_CMD_LINE_ARGS% +rem Check the error code of the Ant build +if not "%OS%"=="Windows_NT" goto onError +set ANT_ERROR=%ERRORLEVEL% +goto end + +:runAntWithJikesNoClasspath +"%_JAVACMD%" %ANT_OPTS% -classpath "%ANT_HOME%\lib\ant-launcher.jar" "-Dant.home=%ANT_HOME%" "-Djikes.class.path=%JIKESPATH%" org.apache.tools.ant.launch.Launcher %ANT_ARGS% %ANT_CMD_LINE_ARGS% +rem Check the error code of the Ant build +if not "%OS%"=="Windows_NT" goto onError +set ANT_ERROR=%ERRORLEVEL% +goto end + +:onError +rem Windows 9x way of checking the error code. It matches via brute force. +for %%i in (1 10 100) do set err%%i= +for %%i in (0 1 2) do if errorlevel %%i00 set err100=%%i +if %err100%==2 goto onError200 +if %err100%==0 set err100= +for %%i in (0 1 2 3 4 5 6 7 8 9) do if errorlevel %err100%%%i0 set err10=%%i +if "%err100%"=="" if %err10%==0 set err10= +:onError1 +for %%i in (0 1 2 3 4 5 6 7 8 9) do if errorlevel %err100%%err10%%%i set err1=%%i +goto onErrorEnd +:onError200 +for %%i in (0 1 2 3 4 5) do if errorlevel 2%%i0 set err10=%%i +if err10==5 for %%i in (0 1 2 3 4 5) do if errorlevel 25%%i set err1=%%i +if not err10==5 goto onError1 +:onErrorEnd +set ANT_ERROR=%err100%%err10%%err1% +for %%i in (1 10 100) do set err%%i= + +:end +rem bug ID 32069: resetting an undefined env variable changes the errorlevel. +if not "%_JAVACMD%"=="" set _JAVACMD= +if not "%_ANT_CMD_LINE_ARGS%"=="" set ANT_CMD_LINE_ARGS= + +if "%ANT_ERROR%"=="0" goto mainEnd + +rem Set the return code if we are not in NT. We can only set +rem a value of 1, but it's better than nothing. +if not "%OS%"=="Windows_NT" echo 1 > nul | choice /n /c:1 + +rem Set the ERRORLEVEL if we are running NT. +if "%OS%"=="Windows_NT" color 00 + +goto omega + +:mainEnd + +rem If there were no errors, we run the post script. +if "%OS%"=="Windows_NT" @endlocal +if "%OS%"=="WINNT" @endlocal + +if "%HOME%"=="" goto homeDrivePathPost +if exist "%HOME%\antrc_post.bat" call "%HOME%\antrc_post.bat" + +:homeDrivePathPost +if "%HOMEDRIVE%%HOMEPATH%"=="" goto userProfilePost +if "%HOMEDRIVE%%HOMEPATH%"=="%HOME%" goto userProfilePost +if exist "%HOMEDRIVE%%HOMEPATH%\antrc_post.bat" call "%HOMEDRIVE%%HOMEPATH%\antrc_post.bat" + +:userProfilePost +if "%USERPROFILE%"=="" goto omega +if "%USERPROFILE%"=="%HOME%" goto omega +if "%USERPROFILE%"=="%HOMEDRIVE%%HOMEPATH%" goto omega +if exist "%USERPROFILE%\antrc_post.bat" call "%USERPROFILE%\antrc_post.bat" + +:omega + diff --git a/代码/workspace_robo4/tools/bin/ant.sh b/代码/workspace_robo4/tools/bin/ant.sh new file mode 100644 index 0000000..0727ea1 --- /dev/null +++ b/代码/workspace_robo4/tools/bin/ant.sh @@ -0,0 +1,94 @@ +#! /bin/sh + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +case "`uname`" in + CYGWIN*) cygwin=true ;; + Darwin*) darwin=true ;; +esac + +#Find the necessary resources +ANT_HOME=. + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + else + JAVACMD=java + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." + echo " We cannot execute $JAVACMD" + exit +fi + +if [ -n "$CLASSPATH" ] ; then + LOCALCLASSPATH=$CLASSPATH +fi + +# add in the dependency .jar files +DIRLIBS=${ANT_HOME}/build-lib/*.jar +for i in ${DIRLIBS} +do + # if the directory is empty, then it will return the input string + # this is stupid, so case for it + if [ "$i" != "${DIRLIBS}" ] ; then + if [ -z "$LOCALCLASSPATH" ] ; then + LOCALCLASSPATH=$i + else + LOCALCLASSPATH="$i":$LOCALCLASSPATH + fi + fi +done + +if [ -n "$JAVA_HOME" ] ; then + if [ -f "$JAVA_HOME/lib/tools.jar" ] ; then + LOCALCLASSPATH=$LOCALCLASSPATH:$JAVA_HOME/lib/tools.jar + fi + + if [ -f "$JAVA_HOME/lib/classes.zip" ] ; then + LOCALCLASSPATH=$LOCALCLASSPATH:$JAVA_HOME/lib/classes.zip + fi + + # OSX hack to make Ant work with jikes + if $darwin ; then + OSXHACK="/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Classes" + if [ -d ${OSXHACK} ] ; then + for i in ${OSXHACK}/*.jar + do + JIKESPATH=$JIKESPATH:$i + done + fi + fi + +else + echo "Warning: JAVA_HOME environment variable is not set." + echo " If build fails because sun.* classes could not be found" + echo " you will need to set the JAVA_HOME environment variable" + echo " to the installation directory of java." +fi + +# supply JIKESPATH to Ant as jikes.class.path +if [ -n "$JIKESPATH" ] ; then + if [ -n "$ANT_OPTS" ] ; then + ANT_OPTS="$ANT_OPTS -Djikes.class.path=$JIKESPATH" + else + ANT_OPTS=-Djikes.class.path=$JIKESPATH + fi +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + ANT_HOME=`cygpath --path --windows "$ANT_HOME"` + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + LOCALCLASSPATH=`cygpath --path --windows "$LOCALCLASSPATH"` +fi +$JAVACMD -classpath "$LOCALCLASSPATH" -Dant.home="${ANT_HOME}" $ANT_OPTS org.apache.tools.ant.Main -e "$@" diff --git a/代码/workspace_robo4/tools/bin/m2.conf b/代码/workspace_robo4/tools/bin/m2.conf new file mode 100644 index 0000000..cc046fb --- /dev/null +++ b/代码/workspace_robo4/tools/bin/m2.conf @@ -0,0 +1,4 @@ +main is org.apache.maven.cli.MavenCli from plexus.core + +[plexus.core] +load tools/lib/*.jar diff --git a/代码/workspace_robo4/tools/bin/mvn.bat b/代码/workspace_robo4/tools/bin/mvn.bat new file mode 100644 index 0000000..8fd1f4c --- /dev/null +++ b/代码/workspace_robo4/tools/bin/mvn.bat @@ -0,0 +1,191 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set HOME=%HOMEDRIVE%%HOMEPATH%) + +@REM Execute a user defined script before this one +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" + +set ERROR_CODE=0 + +@REM set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" @setlocal +if "%OS%"=="WINNT" @setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo ERROR: JAVA_HOME not found in your environment. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto chkMHome + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory. +echo JAVA_HOME = %JAVA_HOME% +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation +echo. +goto error + +:chkMHome +if not "%M2_HOME%"=="" goto valMHome + +if "%OS%"=="Windows_NT" SET M2_HOME=%~dp0 +if "%OS%"=="Windows_NT" set M2_HOME=%M2_HOME:~0,-5% +if "%OS%"=="WINNT" SET M2_HOME=%~dp0.. +if not "%M2_HOME%"=="" goto valMHome + +echo. +echo ERROR: M2_HOME not found in your environment. +echo Please set the M2_HOME variable in your environment to match the +echo location of the Maven installation +echo. +goto error + +:valMHome + +:stripMHome +if not _%M2_HOME:~-1%==_\ goto checkMBat +set M2_HOME=%M2_HOME:~0,-1% +goto stripMHome + +:checkMBat +if exist "%M2_HOME%\bin\mvn.bat" goto init + +echo. +echo ERROR: M2_HOME is set to an invalid directory. +echo M2_HOME = %M2_HOME% +echo Please set the M2_HOME variable in your environment to match the +echo location of the Maven installation +echo. +goto error +@REM ==== END VALIDATION ==== + +:init +@REM Decide how to startup depending on the version of windows + +@REM -- Windows NT with Novell Login +if "%OS%"=="WINNT" goto WinNTNovell + +@REM -- Win98ME +if NOT "%OS%"=="Windows_NT" goto Win9xArg + +:WinNTNovell + +@REM -- 4NT shell +if "%@eval[2+2]" == "4" goto 4NTArgs + +@REM -- Regular WinNT shell +set MAVEN_CMD_LINE_ARGS=%* +goto endInit + +@REM The 4NT Shell from jp software +:4NTArgs +set MAVEN_CMD_LINE_ARGS=%$ +goto endInit + +:Win9xArg +@REM Slurp the command line arguments. This loop allows for an unlimited number +@REM of agruments (up to the command line limit, anyway). +set MAVEN_CMD_LINE_ARGS= +:Win9xApp +if %1a==a goto endInit +set MAVEN_CMD_LINE_ARGS=%MAVEN_CMD_LINE_ARGS% %1 +shift +goto Win9xApp + +@REM Reaching here means variables are defined and arguments have been captured +:endInit +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +@REM -- 4NT shell +if "%@eval[2+2]" == "4" goto 4NTCWJars + +@REM -- Regular WinNT shell +for %%i in ("%M2_HOME%"\lib\classworlds-*) do set CLASSWORLDS_JAR="%%~fi" +for %%i in ("%M2_HOME%"\lib\maven-*-uber.jar) do set MAVENUBER_JAR="%%~fi" + +goto runm2 + +@REM The 4NT Shell from jp software +:4NTCWJars +for %%i in ("%M2_HOME%\lib\classworlds-*") do set CLASSWORLDS_JAR="%%i" +goto runm2 + +@REM Start MAVEN2 +:runm2 +%MAVEN_JAVA_EXE% %MAVEN_OPTS% -classpath %CLASSWORLDS_JAR%;%MAVENUBER_JAR% "-Dclassworlds.conf=%M2_HOME%\bin\m2.conf" "-Dmaven.home=%M2_HOME%" org.codehaus.classworlds.Launcher %MAVEN_CMD_LINE_ARGS% +if ERRORLEVEL 1 goto error +goto end + +:error +if "%OS%"=="Windows_NT" @endlocal +if "%OS%"=="WINNT" @endlocal +set ERROR_CODE=1 + +:end +@REM set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" goto endNT +if "%OS%"=="WINNT" goto endNT + +@REM For old DOS remove the set variables from ENV - we assume they were not set +@REM before we started - at least we don't leave any baggage around +set MAVEN_JAVA_EXE= +set MAVEN_CMD_LINE_ARGS= +goto postExec + +:endNT +@endlocal & set ERROR_CODE=%ERROR_CODE% + +:postExec +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +@REM pause the batch file if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% + diff --git a/代码/workspace_robo4/tools/bin/mvn.sh b/代码/workspace_robo4/tools/bin/mvn.sh new file mode 100644 index 0000000..502d7db --- /dev/null +++ b/代码/workspace_robo4/tools/bin/mvn.sh @@ -0,0 +1,162 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# ---------------------------------------------------------------------------- + +QUOTED_ARGS="" +while [ "$1" != "" ] ; do + + QUOTED_ARGS="$QUOTED_ARGS \"$1\"" + shift + +done + +if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc +fi + +if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + if [ -z "$JAVA_VERSION" ] ; then + JAVA_VERSION="CurrentJDK" + else + echo "Using Java version: $JAVA_VERSION" + fi + if [ -z "$JAVA_HOME" ] ; then + JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." + echo " We cannot execute $JAVACMD" + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.classworlds.Launcher + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$HOME" ] && + HOME=`cygpath --path --windows "$HOME"` +fi + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath $PWD/tools/lib/classworlds-1.1.jar:$PWD/tools/lib/maven-2.2.1-uber.jar \ + "-Dclassworlds.conf=$PWD/tools/bin/m2.conf" \ + ${CLASSWORLDS_LAUNCHER} $QUOTED_ARGS + diff --git a/代码/workspace_robo4/tools/debugall/all.iml b/代码/workspace_robo4/tools/debugall/all.iml new file mode 100644 index 0000000..c46da8f --- /dev/null +++ b/代码/workspace_robo4/tools/debugall/all.iml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/代码/workspace_robo4/tools/jacobe/.gitignore b/代码/workspace_robo4/tools/jacobe/.gitignore new file mode 100644 index 0000000..e560d3e --- /dev/null +++ b/代码/workspace_robo4/tools/jacobe/.gitignore @@ -0,0 +1 @@ +/jacobe-ant-task.zip diff --git a/代码/workspace_robo4/tools/jacobe/ReadMe.txt b/代码/workspace_robo4/tools/jacobe/ReadMe.txt new file mode 100644 index 0000000..a645e5b --- /dev/null +++ b/代码/workspace_robo4/tools/jacobe/ReadMe.txt @@ -0,0 +1,57 @@ +==== + Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://robocode.sourceforge.net/license/epl-v10.html +==== + +Author: Flemming N. Larsen: + +The Jacobe Code Beautifier is used as code beautifier for Robocode. +You can read about it and download it from here: + +http://www.tiobe.com/index.php/content/products/jacobe/Jacobe.html + +Jacobe is quite good for Java as it follows the Java code conventions from Oracle: + +http://www.oracle.com/technetwork/java/codeconv-138413.html + +Jacobe can be integrated with Eclipse by using the Eclipse plugin for Jacobe. +The plugin can be downloaded from the same page used when downloading Jacobe +under the "Plug-ins" section. + +You can install the Jacobe plugin into Eclipse simply by unpacking the Jacobe +plugin to the root directory of Eclipse (the plugins directory must be +"overwritten" with the Jacobe plugin). + +When the Jacobe plugin has been put into the root directory of Eclipse, you +must restart Eclipse, if you had it running while putting the plugin into the +Eclipse directory. Otherwise you'll not be able to use Jacobe yet. + +I attached the robocode.cfg file, which is used for beautifying the Robocode +sources with Jacobe. You should put this file into the directory where +you have installed Jacobe, i.e. just together the sun.cfg file. + +In Eclipse (when you have added your plugin, and can see the purple bug in +the toolbar) you select "Preferences.." from the Window menu. On the +Preferences window you expand the Java (in the tree) and click Jacobe. + +Browse and select your Jacobe executable. Browse and select the +robocode.cfg file. All checkmarks should be cleared, except for "overwrite +original files". Otherwise backup files are created. Now you are ready +to code beautify following the Robocode Jacobe configuration. + +You can also code beautify the sources of Robocode by using the target named +"jacobe" in the build.xml file provided in this directory. Here you'll +need to download and install the Jacobe Ant Task: + +http://www.tiobe.com/content/products/jacobe/jacobe-ant-task.zip + +You should copy the jacode.jar file inside the jacobe-ant-task.zip file +into this folder, and also add the home folder where the Jacode executable +is located into your PATH environment variable. + +You can read more about the Jacobe Ant task here: + +http://www.tiobe.com/index.php/content/products/jacobe/jacobe_task_doc.html \ No newline at end of file diff --git a/代码/workspace_robo4/tools/jacobe/robocode.cfg b/代码/workspace_robo4/tools/jacobe/robocode.cfg new file mode 100644 index 0000000..a8c916c --- /dev/null +++ b/代码/workspace_robo4/tools/jacobe/robocode.cfg @@ -0,0 +1,301 @@ +// Jacobe configuration file for the Sun code conventions for Java +// $Id: sun.cfg,v 1.94 2006/05/31 09:29:01 stappers Exp $ +// reference: http://java.sun.com/docs/codeconv/ +// (c) 2000-2006 Tiobe Software BV -- All rights reserved +// support@jacobe.com, www.jacobe.com, Eindhoven, The Netherlands + + +// INDENTATION +// ----------- + +//--indent=4 +--indenttab=1 +--tablen=4 +//--unindentjumplabel + + +// LINE LENGTH +// ----------- + +--wrap=120 + + +// WRAPPING LINES +// -------------- + +//--wrapinfixoplineterm=1 +--wraplineterminfixop=1 +--indentcontinuation=2 +//--continuationindent=4 +//--wraplinetermcomma=1 +--wrapcommalineterm=1 +--wraparrayinitopenbracelineterm=1 +--wrapmethodcallopenparenlineterm=1 +//--wrapassoplineterm=1 + + +// COMMENTS +// -------- + +--opencommentspace=1 +//--opencommentlineterm=1 +--indentcomment=1 +//--commentstarspace=1 + +// JAVADOC +// ------- +// The rules below are only available in Jacobe Professional + +--javadocstartlineterm=1 +--linetermendjavadoc=1 +--javadocdescr +--javadocdescrlineterm=2 +--javadocauthor +--javadocauthorlineterm=1 +--javadocversion +--javadocversionlineterm=2 +--javadocparam +--javadocparamorder +--javadocparamlineterm=1 +--javadocreturn +--javadocreturnlineterm=1 +--javadocthrows +--javadocthrowsorder +--javadocthrowslineterm=1 +--javadocorder +--javadoctagspacearg=1 + + +// DECLARATIONS AND STATEMENTS +// --------------------------- + +--colonlineterm=1 +--spaceopenbrace=1 +--closebracelineterm=1 +--openbracespace=1 +--openbracespaceclosebrace=0 +--openbracelinetermclosebrace=0 +--openparenspacecloseparen=0 +--linetermopenbracket=0 +--indentbraces=0 +--indentblock=1 +//--dimopenbracketspace=0 +//--dimspaceclosebracket=0 +//--indexopenbracketspace=0 +//--indexspaceclosebracket=0 +--openbracketspaceclosebracket=0 + + +// DECLARATIONS +// ------------ + +--decllineterm=1 +--modifierslineterm=0 +--modifiersspace=1 +//--typespace=1 +--classspace=1 +--classlineterm=0 +--classlinetermopenbrace=0 +--classopenbracelineterm=1 +--classlinetermclosebrace=1 +--spaceextends=1 +--extendsspace=1 +--linetermextends=0 +--extendslineterm=0 +//--linetermimplements=0 +//--implementslineterm=0 +//--linetermthrows=0 +--methodlinetermopenbrace=0 +--methodopenbracelineterm=1 +--methodlinetermclosebrace=1 +//--arrayinitlinetermopenbrace=0 +//--arrayinitopenbracelineterm=0 +//--arrayinitlinetermclosebrace=0 +//--arrayinitclosebracelineterm=0 +//--arrayinitopenbracespace=0 +//--arrayinitspaceclosebrace=0 +--returntypelineterm=0 +//--typelineterm=0 +//--paramtypelineterm=0 +//--fortypelineterm=0 +//--declarraytoarraytype +//--linetermclass=1 +//--linetermconstructor=1 +--closebracelinetermopenbrace=1 +--importlineterm=0 +--modifierlineterm=0 +//--seplineterm=0 +//--paramopenparenlineterm=0 +//--paramlinetermcloseparen=0 +//--paramlinetermopenparen=0 +//--paramcloseparenlineterm=0 +//--paramspaceopenparen=0 +--enumcommalineterm=1 + + +// SIMPLE STATEMENTS +// ----------------- + +--statlineterm=1 +--methodcallspaceopenparen=0 +--methodcalllinetermopenparen=0 +--dotlineterm=0 +--linetermdot=0 +--linetermsep=0 +--lineterminfixop=0 +--infixoplineterm=0 +--prefixoplineterm=0 +--linetermpostfixop=0 +--linetermcomma=0 +--commalineterm=0 +--openparenlineterm=0 +--linetermcloseparen=0 +--assoplineterm=0 +--linetermassop=0 + + +// COMPOUND STATEMENTS +// ------------------- + +--blocklinetermopenbrace=0 +--blockopenbracelineterm=1 +--blocklinetermclosebrace=1 +--insertbraces +--blockstatlinetermopenbrace=0 + + +// IF STATEMENTS +// ------------- + +--spaceelse=1 +--closebracelinetermelse=0 +//--semicolonlinetermelse=1 +--elselinetermif=0 + + +// FOR STATEMENTS +// -------------- + +--forstatlineterm=0 + + +// DO-WHILE STATEMENTS +// ------------------- + +--closebracelinetermdowhile=0 +--semicolonlinetermdowhile=1 + + +// SWITCH STATEMENTS +// ----------------- + +--blanklinescase=1 +--indentcase=0 +//--insertbracescasestats + + +// TRY-CATCH STATEMENTS +// -------------------- + +--spacecatch=1 +--linetermcatch=0 +--spacefinally=1 +--linetermfinally=0 + + +// WHITE SPACE +// ----------- + +//--lineterm + + +// BLANK LINES +// ----------- + +//--blanklinescompilationunit=0 +--methodblanklines=1 +--declblanklinesstat=0 +--statblanklinesdecl=0 +--blanklinescomment=1 +--sectionblanklines=2 +--classblanklines=2 +//--enumconstantblanklinesdecl=1 + + +// SPACES +// ------ + +//--keywordspace=1 +--keywordspaceopenparen=1 +--keywordlinetermopenparen=0 +--methodnamespace=0 +--spacecomma=0 +--commaspace=1 +--spacesemicolon=0 +--semicolonspace=1 +--spacecolon=0 +--colonspace=1 +--assignspace=1 +--spaceassign=1 +--dotspace=0 +--spacedot=0 +--prefixopspace=0 +--infixopspace=1 +--spaceinfixop=1 +--spacepostfixop=0 +--spaceopenbracket=0 +--castspace=1 +--castopenparenspace=0 +--castspacecloseparen=0 +//--castopenparenlineterm=0 +//--castlinetermcloseparen=0 +//--castlinetermopenparen=0 +//--castcloseparenlineterm=0 +//--castspaceopenparen=0 +//--castcloseparenspace=0 +//--statopenparenlineterm=0 +//--statlinetermcloseparen=0 +//--statcloseparenspace=0 +//--statcloseparenlineterm=0 +//--castcloseparenspacegroupopenparen=1 +--statopenparenspace=0 +--statspacecloseparen=0 +--groupopenparenspace=0 +--groupspacecloseparen=0 +//--groupspaceopenparen=0 +//--groupcloseparenspace=0 +//--groupopenparenlineterm=0 +//--grouplinetermcloseparen=0 +//--grouplinetermopenparen=0 +//--groupcloseparenlineterm=0 +--methodopenparenspace=0 +--methodspacecloseparen=0 +//--methodopenparenlineterm=0 +//--methodlinetermcloseparen=0 +//--methodcloseparenspace=0 +//--methodcloseparenlineterm=0 +//--horspaceslineterm + +// ANNOTATIONS +// ----------- + +//--annotationatspace=0 +//--annotationatlineterm=0 +//--annotationspaceopenparen=0 +//--annotationlinetermopenparen=0 +//--annotationopenparenspace=0 +//--annotationopenparenlineterm=0 +//--annotationspacecloseparen=0 +//--annotationlinetermcloseparen=0 +//--annotationcloseparenspace=0 +//--annotationcloseparenlineterm=0 +//--annotationspaceopenbrace=0 +//--annotationlinetermopenbrace=0 +//--annotationopenbracespace=0 +//--annotationopenbracelineterm=0 +//--annotationspaceclosebrace=0 +//--annotationlinetermclosebrace=0 +//--annotationclosebracespace=0 +//--annotationclosebracelineterm=0 +//--annotationspace=1 +//--annotationlineterm=1 diff --git a/代码/workspace_robo4/tools/licenses/ant-LICENSE.txt b/代码/workspace_robo4/tools/licenses/ant-LICENSE.txt new file mode 100644 index 0000000..cdf6ff8 --- /dev/null +++ b/代码/workspace_robo4/tools/licenses/ant-LICENSE.txt @@ -0,0 +1,272 @@ +/* + * Apache License + * Version 2.0, January 2004 + * http://www.apache.org/licenses/ + * + * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + * + * 1. Definitions. + * + * "License" shall mean the terms and conditions for use, reproduction, + * and distribution as defined by Sections 1 through 9 of this document. + * + * "Licensor" shall mean the copyright owner or entity authorized by + * the copyright owner that is granting the License. + * + * "Legal Entity" shall mean the union of the acting entity and all + * other entities that control, are controlled by, or are under common + * control with that entity. For the purposes of this definition, + * "control" means (i) the power, direct or indirect, to cause the + * direction or management of such entity, whether by contract or + * otherwise, or (ii) ownership of fifty percent (50%) or more of the + * outstanding shares, or (iii) beneficial ownership of such entity. + * + * "You" (or "Your") shall mean an individual or Legal Entity + * exercising permissions granted by this License. + * + * "Source" form shall mean the preferred form for making modifications, + * including but not limited to software source code, documentation + * source, and configuration files. + * + * "Object" form shall mean any form resulting from mechanical + * transformation or translation of a Source form, including but + * not limited to compiled object code, generated documentation, + * and conversions to other media types. + * + * "Work" shall mean the work of authorship, whether in Source or + * Object form, made available under the License, as indicated by a + * copyright notice that is included in or attached to the work + * (an example is provided in the Appendix below). + * + * "Derivative Works" shall mean any work, whether in Source or Object + * form, that is based on (or derived from) the Work and for which the + * editorial revisions, annotations, elaborations, or other modifications + * represent, as a whole, an original work of authorship. For the purposes + * of this License, Derivative Works shall not include works that remain + * separable from, or merely link (or bind by name) to the interfaces of, + * the Work and Derivative Works thereof. + * + * "Contribution" shall mean any work of authorship, including + * the original version of the Work and any modifications or additions + * to that Work or Derivative Works thereof, that is intentionally + * submitted to Licensor for inclusion in the Work by the copyright owner + * or by an individual or Legal Entity authorized to submit on behalf of + * the copyright owner. For the purposes of this definition, "submitted" + * means any form of electronic, verbal, or written communication sent + * to the Licensor or its representatives, including but not limited to + * communication on electronic mailing lists, source code control systems, + * and issue tracking systems that are managed by, or on behalf of, the + * Licensor for the purpose of discussing and improving the Work, but + * excluding communication that is conspicuously marked or otherwise + * designated in writing by the copyright owner as "Not a Contribution." + * + * "Contributor" shall mean Licensor and any individual or Legal Entity + * on behalf of whom a Contribution has been received by Licensor and + * subsequently incorporated within the Work. + * + * 2. Grant of Copyright License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * copyright license to reproduce, prepare Derivative Works of, + * publicly display, publicly perform, sublicense, and distribute the + * Work and such Derivative Works in Source or Object form. + * + * 3. Grant of Patent License. Subject to the terms and conditions of + * this License, each Contributor hereby grants to You a perpetual, + * worldwide, non-exclusive, no-charge, royalty-free, irrevocable + * (except as stated in this section) patent license to make, have made, + * use, offer to sell, sell, import, and otherwise transfer the Work, + * where such license applies only to those patent claims licensable + * by such Contributor that are necessarily infringed by their + * Contribution(s) alone or by combination of their Contribution(s) + * with the Work to which such Contribution(s) was submitted. If You + * institute patent litigation against any entity (including a + * cross-claim or counterclaim in a lawsuit) alleging that the Work + * or a Contribution incorporated within the Work constitutes direct + * or contributory patent infringement, then any patent licenses + * granted to You under this License for that Work shall terminate + * as of the date such litigation is filed. + * + * 4. Redistribution. You may reproduce and distribute copies of the + * Work or Derivative Works thereof in any medium, with or without + * modifications, and in Source or Object form, provided that You + * meet the following conditions: + * + * (a) You must give any other recipients of the Work or + * Derivative Works a copy of this License; and + * + * (b) You must cause any modified files to carry prominent notices + * stating that You changed the files; and + * + * (c) You must retain, in the Source form of any Derivative Works + * that You distribute, all copyright, patent, trademark, and + * attribution notices from the Source form of the Work, + * excluding those notices that do not pertain to any part of + * the Derivative Works; and + * + * (d) If the Work includes a "NOTICE" text file as part of its + * distribution, then any Derivative Works that You distribute must + * include a readable copy of the attribution notices contained + * within such NOTICE file, excluding those notices that do not + * pertain to any part of the Derivative Works, in at least one + * of the following places: within a NOTICE text file distributed + * as part of the Derivative Works; within the Source form or + * documentation, if provided along with the Derivative Works; or, + * within a display generated by the Derivative Works, if and + * wherever such third-party notices normally appear. The contents + * of the NOTICE file are for informational purposes only and + * do not modify the License. You may add Your own attribution + * notices within Derivative Works that You distribute, alongside + * or as an addendum to the NOTICE text from the Work, provided + * that such additional attribution notices cannot be construed + * as modifying the License. + * + * You may add Your own copyright statement to Your modifications and + * may provide additional or different license terms and conditions + * for use, reproduction, or distribution of Your modifications, or + * for any such Derivative Works as a whole, provided Your use, + * reproduction, and distribution of the Work otherwise complies with + * the conditions stated in this License. + * + * 5. Submission of Contributions. Unless You explicitly state otherwise, + * any Contribution intentionally submitted for inclusion in the Work + * by You to the Licensor shall be under the terms and conditions of + * this License, without any additional terms or conditions. + * Notwithstanding the above, nothing herein shall supersede or modify + * the terms of any separate license agreement you may have executed + * with Licensor regarding such Contributions. + * + * 6. Trademarks. This License does not grant permission to use the trade + * names, trademarks, service marks, or product names of the Licensor, + * except as required for reasonable and customary use in describing the + * origin of the Work and reproducing the content of the NOTICE file. + * + * 7. Disclaimer of Warranty. Unless required by applicable law or + * agreed to in writing, Licensor provides the Work (and each + * Contributor provides its Contributions) on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied, including, without limitation, any warranties or conditions + * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + * PARTICULAR PURPOSE. You are solely responsible for determining the + * appropriateness of using or redistributing the Work and assume any + * risks associated with Your exercise of permissions under this License. + * + * 8. Limitation of Liability. In no event and under no legal theory, + * whether in tort (including negligence), contract, or otherwise, + * unless required by applicable law (such as deliberate and grossly + * negligent acts) or agreed to in writing, shall any Contributor be + * liable to You for damages, including any direct, indirect, special, + * incidental, or consequential damages of any character arising as a + * result of this License or out of the use or inability to use the + * Work (including but not limited to damages for loss of goodwill, + * work stoppage, computer failure or malfunction, or any and all + * other commercial damages or losses), even if such Contributor + * has been advised of the possibility of such damages. + * + * 9. Accepting Warranty or Additional Liability. While redistributing + * the Work or Derivative Works thereof, You may choose to offer, + * and charge a fee for, acceptance of support, warranty, indemnity, + * or other liability obligations and/or rights consistent with this + * License. However, in accepting such obligations, You may act only + * on Your own behalf and on Your sole responsibility, not on behalf + * of any other Contributor, and only if You agree to indemnify, + * defend, and hold each Contributor harmless for any liability + * incurred by, or claims asserted against, such Contributor by reason + * of your accepting any such warranty or additional liability. + * + * END OF TERMS AND CONDITIONS + * + * APPENDIX: How to apply the Apache License to your work. + * + * To apply the Apache License to your work, attach the following + * boilerplate notice, with the fields enclosed by brackets "[]" + * replaced with your own identifying information. (Don't include + * the brackets!) The text should be enclosed in the appropriate + * comment syntax for the file format. We also recommend that a + * file or class name and description of purpose be included on the + * same "printed page" as the copyright notice for easier + * identification within third-party archives. + * + * Copyright [yyyy] [name of copyright owner] + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +W3C SOFTWARE NOTICE AND LICENSE +http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +This work (and included software, documentation such as READMEs, or other +related items) is being provided by the copyright holders under the following +license. By obtaining, using and/or copying this work, you (the licensee) agree +that you have read, understood, and will comply with the following terms and +conditions. + +Permission to copy, modify, and distribute this software and its documentation, +with or without modification, for any purpose and without fee or royalty is +hereby granted, provided that you include the following on ALL copies of the +software and documentation or portions thereof, including modifications: + + 1. The full text of this NOTICE in a location viewable to users of the + redistributed or derivative work. + 2. Any pre-existing intellectual property disclaimers, notices, or terms + and conditions. If none exist, the W3C Software Short Notice should be + included (hypertext is preferred, text is permitted) within the body + of any redistributed or derivative code. + 3. Notice of any changes or modifications to the files, including the date + changes were made. (We recommend you provide URIs to the location from + which the code is derived.) + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE +NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT +THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY +PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION. + +The name and trademarks of copyright holders may NOT be used in advertising or +publicity pertaining to the software without specific, written prior permission. +Title to copyright in this software and any associated documentation will at +all times remain with copyright holders. + +____________________________________ + +This formulation of W3C's notice and license became active on December 31 2002. +This version removes the copyright ownership notice such that this license can +be used with materials other than those owned by the W3C, reflects that ERCIM +is now a host of the W3C, includes references to this specific dated version of +the license, and removes the ambiguous grant of "use". Otherwise, this version +is the same as the previous version and is written so as to preserve the Free +Software Foundation's assessment of GPL compatibility and OSI's certification +under the Open Source Definition. Please see our Copyright FAQ for common +questions about using materials from our site, including specific terms and +conditions for packages like libwww, Amaya, and Jigsaw. Other questions about +this notice can be directed to site-policy@w3.org. + +Joseph Reagle + +This license came from: http://www.megginson.com/SAX/copying.html + However please note future versions of SAX may be covered + under http://saxproject.org/?selected=pd + +SAX2 is Free! + +I hereby abandon any property rights to SAX 2.0 (the Simple API for +XML), and release all of the SAX 2.0 source code, compiled code, and +documentation contained in this distribution into the Public Domain. +SAX comes with NO WARRANTY or guarantee of fitness for any +purpose. + +David Megginson, david@megginson.com +2000-05-05 diff --git a/代码/workspace_robo4/tools/licenses/ant-NOTICE.txt b/代码/workspace_robo4/tools/licenses/ant-NOTICE.txt new file mode 100644 index 0000000..4c88cc6 --- /dev/null +++ b/代码/workspace_robo4/tools/licenses/ant-NOTICE.txt @@ -0,0 +1,26 @@ + ========================================================================= + == NOTICE file corresponding to the section 4 d of == + == the Apache License, Version 2.0, == + == in this case for the Apache Ant distribution. == + ========================================================================= + + Apache Ant + Copyright 1999-2008 The Apache Software Foundation + + This product includes software developed by + The Apache Software Foundation (http://www.apache.org/). + + This product includes also software developed by : + - the W3C consortium (http://www.w3c.org) , + - the SAX project (http://www.saxproject.org) + + The task is based on code Copyright (c) 2002, Landmark + Graphics Corp that has been kindly donated to the Apache Software + Foundation. + + Portions of this software were originally based on the following: + - software copyright (c) 1999, IBM Corporation., http://www.ibm.com. + - software copyright (c) 1999, Sun Microsystems., http://www.sun.com. + - voluntary contributions made by Paul Eng on behalf of the + Apache Software Foundation that were originally developed at iClick, Inc., + software copyright (c) 1999. diff --git a/代码/workspace_robo4/tools/licenses/mvn-LICENSE.txt b/代码/workspace_robo4/tools/licenses/mvn-LICENSE.txt new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/代码/workspace_robo4/tools/licenses/mvn-LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/代码/workspace_robo4/tools/licenses/mvn-NOTICE.txt b/代码/workspace_robo4/tools/licenses/mvn-NOTICE.txt new file mode 100644 index 0000000..ee40ae9 --- /dev/null +++ b/代码/workspace_robo4/tools/licenses/mvn-NOTICE.txt @@ -0,0 +1,11 @@ + ========================================================================= + == NOTICE file corresponding to the section 4 d of == + == the Apache License, Version 2.0, == + == in this case for the Apache Maven distribution. == + ========================================================================= + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +This product includes software (Plexus and Classworlds) developed by +The Codehaus Foundation (http://www.codehaus.org/). diff --git a/代码/workspace_robo4/tools/loadTools.cmd b/代码/workspace_robo4/tools/loadTools.cmd new file mode 100644 index 0000000..b2926f2 --- /dev/null +++ b/代码/workspace_robo4/tools/loadTools.cmd @@ -0,0 +1,19 @@ +@REM +@REM Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +@REM All rights reserved. This program and the accompanying materials +@REM are made available under the terms of the Eclipse Public License v1.0 +@REM which accompanies this distribution, and is available at +@REM http://robocode.sourceforge.net/license/epl-v10.html +@REM + +@echo off + +if not exist "%~dp0\lib" ( + mkdir "%~dp0\lib" +) + +if not exist "%~dp0\loader\Loader.class" ( + javac "%~dp0\loader\Loader.java" +) + +java -cp "%~dp0/loader" Loader http://robocode.sourceforge.net/tools/libs/ "%~dp0/lib/" ant.jar ant-contrib-0.6.jar ant-launcher.jar jacobe.jar junit.jar classworlds-1.1.jar maven-2.2.1-uber.jar \ No newline at end of file diff --git a/代码/workspace_robo4/tools/loadTools.sh b/代码/workspace_robo4/tools/loadTools.sh new file mode 100644 index 0000000..00d595e --- /dev/null +++ b/代码/workspace_robo4/tools/loadTools.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://robocode.sourceforge.net/license/epl-v10.html +# + + +dp0=${0%/*} + +if [ ! -d "$dp0/lib" ]; then + mkdir "$dp0/lib" +fi + +if [ ! -e "$dp0/loader/Loader.class" ]; then + javac "$dp0/loader/Loader.java" +fi + +java -cp "$dp0/loader" Loader http://robocode.sourceforge.net/tools/libs/ "$dp0/lib/" ant.jar ant-contrib-0.6.jar ant-launcher.jar jacobe.jar junit.jar classworlds-1.1.jar maven-2.2.1-uber.jar diff --git a/代码/workspace_robo4/tools/loader/Loader.java b/代码/workspace_robo4/tools/loader/Loader.java new file mode 100644 index 0000000..b5e0488 --- /dev/null +++ b/代码/workspace_robo4/tools/loader/Loader.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2001-2016 Mathew A. Nelson and Robocode contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://robocode.sourceforge.net/license/epl-v10.html + */ +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.net.URLConnection; + + +/** + * @author Pavel Savara (original) + */ +public class Loader { + public static void main(String[] args) throws IOException { + for (int i = 2; i < args.length; i++) { + System.out.print("Downloading " + args[0] + args[i] + " to " + args[1] + " [..."); + downloadFile(args[0], args[1], args[i]); + System.out.println("...] done"); + } + } + + private static void downloadFile(String libraries, String directory, String file) throws IOException { + URL url = new URL(libraries + file); + final URLConnection con = url.openConnection(); + InputStream is = null; + FileOutputStream fos = null; + + try { + is = con.getInputStream(); + fos = new FileOutputStream(directory + file); + do { + final int b = is.read(); + + if (b == -1) { + break; + } else { + fos.write(b); + } + } while (true); + } finally { + if (fos != null) { + fos.close(); + } + if (is != null) { + is.close(); + } + } + } +} diff --git a/代码/workspace_robo4/versions.md b/代码/workspace_robo4/versions.md new file mode 100644 index 0000000..4363a97 --- /dev/null +++ b/代码/workspace_robo4/versions.md @@ -0,0 +1,3082 @@ +## Version 1.9.2.5 (30-Dec-2015) + +### Bug fixes +* [Bug-378][]: robocode.robocodeGL.system.GLRenderer ClassNotFoundException. +* [Bug-380][]: Yet another historical bot related bug. +* Robot Editor: Source files were set to modified (starred) as soon as they were loaded. The modification state remained, even when no changes were made to the source file or when undoing all changes. Therefore the editor would always bring up a dialog with a warning, that the source file needed to be saved before closing the editor. + +### Change +* [Req-160][]: Fixed width font in console. Some systems did not used monospaced font in console windows. + +## Version 1.9.2.4 (20-Nov-2014) + +### Bug fixes +* [Req-159][]: Fix overkilled garbage collection on static fields. + * Robocode garbage collected practically any static field on a robot to prevent memory leaks (see [Bug-244][]). +* [Bug-375][]: Wrong width and height returned for .NET robots. + * The .NET API return 40 instead of 36 with the Width and Height properties. + +### Changes +* Upgraded Eclipse Compiler for Java (ECJ) to version 4.4. +* Upgraded jni4net to version 0.8.7.0. + +### Other +* Got rid of various issues (e.g. license headers) with the source files of Robocode in order to create a Debian distribution of Robocode. + * Thanks goes to Markus Koschany for all the help and support to make this possible. + +## Version 1.9.2.3 (15-Sep-2014) +* [Bug-374][]: Wrong size report for minirumble in v1.9.2.2. + +## Version 1.9.2.2 (03-Sep-2014) +* [Bug-373][]: Wrong robot size calculation in version 1.9.0 - 1.9.2. + +## Version 1.9.2.1 (21-May-2014) + +### Bug fixes +* [Bug-371][]: High cpu usage on editor. +* [Bug-372][]: Cannot load battle file when ``-DNOSECURITY=true`` is enabled - ``java.lang.IllegalAccessError``. + +## Version 1.9.2.0 (23-Apr-2014) + +### New feature +* Initial positions and headings added to the Control API. + * A new constructor has been added to the ``BattleSpecification`` for the ``RobocodeEngine`` so that it is possible to set the initial position and heading of each participant robot. This new constructor takes an additional parameter named ``initialSetups`` that is an array of ``RobotSetup`` instances. + * The ``RobotSetup`` is a new class introduced with this version that contains the initial position and heading for an individual robot. + +### Bug fixes +* [Bug-370][]: Robot Packager cannot find robot .properties file in development path. +* Fixed issue with the Robot Editor, where the caret position was not updated fast enough when typing very fast. + +## Version 1.9.1.0 (22-Mar-2014) + +### Bug fixes +* [Bug-366][]: Receiving enemy's real name on HitByBulletEvent. + * The previous fix was not correct for the owner and victim for the HitByBulletEvent and HitBulletEvent. +* [Bug-368][]: Issues with sentries + * All listed issues have been fixed. + * A bullet from a sentry robot will not be able to hit another bullet within the "safe zone" any more, but will still be able to hit another bullet within the sentry border area. + * When sentry robots are present on the battle field, the initial random positions will be located within the safe zone. This avoids robots from being punished by sentry robots from the start of the battle, as the robot did not enter the sentry border by itself. +* [Bug-369][]: RoboRumble: NoClassDefFoundError for CodeSizeCalculator. +* The missing property ``robocode.battle.sentryBorderSize`` has now been added to the .battle file format. +* Fixed the twinduel.sh file which was using a invalid file name for the configuration file. +* Added desktop files for FreeBSD. + +### New features +* Due to one of the ideas in [Bug-368][], a new method ``getNumSentries()`` for Java and a ``NumSentries`` read-only property for .NET was added to the ``Robot`` and ``RobotStatus`` classes, and to the ``IBasicRobotPeer`` interface as well. + +### Changes +* Upgraded Eclipse Compiler for Java (ECJ) to version 4.3.1. + +## Version 1.9.0.0 (16-Feb-2014) The Border Sentry Robot Release + +### Bug fixes +* [Bug-364][]: Robot Packager does not include the robot data dir in the .jar file. + * The Robot packager has now been extended with an option to include data files too when packaging a robot. +* [Bug-366][]: Receiving enemy's real name on HitByBulletEvent. +* Fixed various issues with the Robot Editor, e.g. letters written in the wrong error when typing text fast. +* Fixed issue when loading a robot jar file with no package (default package), which was found by Daniel Yeung, who also had a fix for it. :-) + +### New features +* *BorderSentry interface*: Added a new robot type (the BorderSentry) that allows you to implement border sentry robots, which are robots that guards the walls of the battlefield against "wall-crawlers" and "corner" robots. + * The Border Sentry robot is dedicated to Liam Noonan from Limerick Institute of Technology and the Robocode Ireland event in general. :-) + * The inspiration for this type of robot comes from the TV series named [Robot Wars](http://www.ukgameshows.com/ukgs/Robot_Wars). + * Note that border sentry robots... + * have 400 additional energy points meaning that a border sentry robot starts with 500 energy points! + * only appear at the borders of the battlefield, when a new round is started defined by the "border sentry size", which is a game rules that can be adjusted similar to other game rules. The default border sentry size is 100 units. + * can only make damage to other robot types within the *sentry border*, but not to robots in the "safe zone", which is the area inside the sentry border. + * can receive damage from other robots. But robots will not gain energy points from the border sentry robots (due to Mathew Nelson's excellent point regarding using sentry robots as "Energy Batteries" ;-) ). + * does not receive scores in the Ranking Panel nor Battle Results, even though you can see its score, like ramming damage, bullet damage etc. The goal for the border sentry robot is to be a referee, but not a player that can win or loose the battle. + * A new method names ``getSentryBorderSize()`` has been added to the Robot classes that returns the size / attack range from the edge of the borders, where BorderSentry robots are able to hit other robot types. + * A new method named ``isSentryRobot()`` has been added to the ``ScannedRobotEvent`` event class. + * When there is only one regular robot left on the battle field with one or more border sentry robots, the round is automatically ended. + * A new sample robot has been added named ``samplesentry.BorderGuard``. Try it out against your robot(s) or e.g. ``sample.Corners`` and ``sample.Walls``. + * An additional option has been added to the View Options in the Preferences to enable and disable the visual appearance of the sentry border, which is painted in transparent red (danger zone). +* [Req-156][]: Codesize added to properties file. + * The Robot Packager now adds a new property named ``robot.codesize`` which will be set to the value calculated by the built-in Codesize tool when compiling the robot and/or team. The Codesize value is the effective code size measured in bytes which is used by e.g. the RoboRumble to categorize robots into MicroBot, MiniBot and MegaBot etc. +* Improved the names of the menu items on the Robot menu. + +## Version 1.8.3.0 (04-Oct-2013) The Editor Theme Release + +### Bug fixes +* [Bug-363][]: No Last Survivor Bonus being given. +* The ``getWidth()`` and ``getHeight()`` methods on the Robot class have always returned 40, even though a robot is 36x36 pixels in size. + * Hence, ``getWidth()`` and ``getHeight()`` have been changed to return the correct width and height, which is 36. +* Fixed Robot Editor issues: + * ``NullPointerException`` occurring with a new source file that was not saved before being compiled. + * Issue where the caret position was set to the end of a source file when reading it into the editor. + +### Changes +* [Req-121][]: Issues with editor font. + * A new Editor Theme Configurator has been added the allows changing the font, text colors and styles for the Robocode Editor. + * Two built-in themes have been provided for Robocode: + * Robocode White Theme + * Robocode Black Theme + * When selecting a theme, Robocode will automatically use this theme the next time Robocode is started. + * When changing a theme, a new custom theme can be created and saved. Note that it is possible to overwrite existing themes. + * Editor themes are stored within the /theme/editor directory as theme property files, which makes it possible to modify these in a normal text editor, but also share the themes. + * The Editor Theme Configurator is available from the Robot Editor menu under View -> Change Editor Theme. +* The line numbers area in the Robocode Editor has been improved as well: + * The background and text colors for the line numbers can be changed. + * Line numbers are now right aligned + extra space has been added to the right. +* The Find & Replace dialog has got a better layout. + +## Version 1.8.2.0 (22-Jun-2013) + +### Bug fixes +* [Bug-357][]: Tab characters are inserted in the last line of a robot source file when opening it. + * This bug was only partially fixed with version 1.8.1.0. +* [Bug-358][]: Robot in default package cannot write to files. Should at least get a warning. +* [Bug-361][]: Problem in the text editor related with the .java file modification. +* [Bug-362][]: Rumble client does not remove participants in wrong codesize group. + * Thanks goes to Julian Kent ("Skilgannon") for providing a solution for this. :-) + +### Changes +* Improved the UI regarding Battle Rules: + * All Battle Rules have been assembled into one single Rules tab. + * Number of Round has been moved from the New Battle dialog to the Rules tab. + * Improved the visualization of the battle field size. + * Added input validation to text fields. +* [Req-64][]: Change default battle settings like e.g. "Number of Rounds". + * When the battle rules are changed in the user interface, Robocode will remember these as the user's default settings. + * A new Restore Defaults button has been added to get the game default settings back. +* Source code editor is now always maximized when opening and robot file or creating a new one. + +## Version 1.8.1.0 (24-Mar-2013) + +### Bug fixes +* [Bug-335][]/[Bug-336][]: Skipped turns ... issues. +* [Bug-349][]: Instances of RobocodeEngine don't seem to be independent - memory leak and performance decrease. +* [Bug-350][]: Bullet id from battle record XML file is sometimes -1 causing a NumberFormatException. +* [Bug-351][]: Robot.onBattleEnded(BattleEndedEvent) provides wrong scores. +* [Bug-352][]: Results from BattleCompletedEvent.getIndexedResults() are always sorted. +* [Bug-353][]: RobocodeEngine.setVisible() can cause a NullPointerException. +* [Bug-354][]: Replaying an XML record can cause an ArrayIndexOutOfBoundsException. +* [Bug-355][]: Priority battles not accepted for mini/micro/nano rumbles. +* [Bug-356][]: Update Roborumble URLs from Darkcanuck to LiteRumble. +* [Bug-357][]: Tab characters are inserted in the last line of a robot source file when opening it. + +## Version 1.8.0.0 (30-Jan-2013) + +### Bug fix +* [Bug-346][]: Cannot extract sources from robot packages. +* [Bug-348][]: .NET: UnauthorizedAccessException in AppDomainShell.Dispose(). + +### Changes +* Robocode has been updated to Java 6, and hence this will be the new minimum requirement for running Robocode from this version. +* The icon for Robocode was upgraded to a 256x256 pixel resolution. +* Added the new properties ``-DlogMessagesEnabled=true|false`` and ``-DlogErrorsEnabled=true|false`` for enabling and disabling log messages and log errors. + * The robocode.control.RobocodeEngine has got two similar methods: ``setLogMessagesEnabled(boolean)`` and ``setLogErrorsEnabled(boolean)`` + +## Version 1.7.4.4 (21-Nov-2012) + +### Bug fix +* [Bug-347][]: /bin/sh^M bad interpreter. + * All .sh and .command files contained the Windows ^M characters so these files could not be executed. + +## Version 1.7.4.3 (17-Nov-2012) + +### Bug Fixes +* [Bug-344][]: BattleAdaptor missing in ``robocode.control.events``. +* [Bug-345][]: Graphics still being rendered when minimized. +* [Bug-333][]: .NET runs release dll not debug dll so can't debug. + * Implemented a work-around so that the local robot repository is rebuild when removing a development path. + +### Changes +* Robocode sources are now put on [GitHub](https://github.com/robo-code/robocode). +* Upgraded the .NET plug-in to use Visual Studio Express 2010. +* The versions.txt has been changed to versions.md: + * The versions.txt was converted into [Markdown][] syntax in order to make it easier to convert into e.g. HTML, and because GitHub will automatically translate it into HTML when viewing this file in a browser. + * Thus, this file has been renamed from 'versions.txt' into 'versions.md'. + * The web page with the new versions.md can be viewed [here](https://github.com/robo-code/robocode/blob/master/versions.md). + * In addition, links to all reported bugs and feature requests have been inserted into versions.md so it is easy to browse to the reports and requests to find more details. + +## Version 1.7.4.2 (16-Aug-2012) + +### Bug Fixes +* [Bug-338][]: "Accept-Encoding: gzip" not in Roborumble HTTP Headers. +* [Bug-339][]: All Text Missing. + * Reverting fix for [Bug-332][] ("Use OpenGL backend under linux"), which caused too much trouble. +* [Bug-340][]: Robocode crash on window resize (linux-opengl). + * Reverting fix for [Bug-332][] ("Use OpenGL backend under linux"), which caused too much trouble. +* [Bug-341][]: InteractiveRobots gets error "After the event was added...". +* [Bug-342][]: New bots not given priority. + +### Changes +* The built-in [RoboRumble][] client is now able to decompress "gzip" and "deflate" content with HTTP connections with RoboRumble servers that supports it. + +## Version 1.7.4.1 (02-Jul-2012) + +### Bug Fixes +* [Bug-337][]: Hangups with New Editor in 1.7.4.0. + * Notice, that the editor can still be quite slow with large source files. Work is still in progress to speed it up. + * Several other minor bug fixes with the new editor, like e.g. undoing and redoing tab indentation. + +## Version 1.7.4.0 (07-Jun-2012) + +### Bug Fixes +* [Bug-332][]: Use OpenGL backend under linux. + * The ``-Dsun.java2d.opengl=True`` property has been set up per default in the "robocode.sh" file in order to enable OpenGL hardware acceleration per default for Linux and Solaris. +* [Bug-334][]: Snapshot API never shows bullets in "HIT_WALL" status. +* [Bug-328][]: Issue with the robocode.dll + \# chars in the path for a dll. + * This applies to the .NET plug-in. + +### New Features +* [Req-147][]: The snapshot API is ambiguous for bullets shot by teams. + * Two new methods have been added: + * [IRobotSnapshot.getRobotIndex()][] that returns a unique id between all robots participating in a battle. + * [IRobotSnapshot.getTeamIndex()][] that returns a unique id between all participating robots or -1 if a robot is not a member of a team. + * The existing [IRobotSnapshot.getContestantIndex()][] will return the team id if it is not -1, otherwise the robot id is returned. + +### Changes +* The Robocode Editor (source code editor) has been completely replaced by a new and improved editor. Expect some bugs! + +## Version 1.7.3.6 (29-Apr-2012) + +### Bug Fixes +* [Bug-331][]: RoboRumble client has infinite timeout. + * Default *connection timeout*, *read timeout* and *session timeout* have been set to 10 seconds. + +### New Features +* A new config file has been added for [RoboRumble][] in the roborumble directory in the robocode directory named "roborumble.properties". + * With this config file it is possible to configure the *connection timeout*, *read timeout* and *session timeout* used when downloading robots and uploading results. +* [Req-144]: Mac ... start with icon and name. + +### Changes +* Upgraded Eclipse Compiler for Java (ECJ) to version 3.7.2. + +## Version 1.7.3.5 (11-Mar-2012) + +### Bug Fixes +* [Bug-326][]: Package of team fails to load in team battles. +* Fixed minor issue where the Robot Packager tells that a NanoBot can be 250 bytes and a MiniBot 750 bytes, when these must be lesser than 250 and 750 bytes. + +## Version 1.7.3.4 (04-Dec-2011) + +### Bug Fixes +* [Bug-323][]: Robocode can't find the ECJ (Eclipse Compiler for Java) +* [Bug-319][]: Package name allows bad chars. + * This issue was not fixed entirely. Corrected text regarding use of lower-case letters in package name. +* Bug: Changes to the rendering options did not take effect immediately for the battle view. + +### New Features +* [Req-134][]: Calculate codesize after compile in editor. + +### Changes +* Upgraded Eclipse Compiler for Java (ECJ) to version 3.7.1. + +## Version 1.7.3.3 (05-Nov-2011) + +### Bug Fixes +* [Bug-311][]: ``out.write(int)`` uses up allocated printing quickly. +* [Bug-315][]: Unable to change drawing color in .NET (C\#). +* [Bug-318][]: Installer throws ``NumberFormatException`` on Linux 3.0. +* [Bug-319][]: Package name allows bad chars. +* [Bug-320][]: "About" window colors are awful. + +### Changes +* The layout of the About Box has been completely redesigned. +* If running on Java 1.6 or newer, OS/system based font antialiasing will be enabled. +* Upgraded to Maven 2.2.1 used for building Robocode. + * Cleaned up the build, improved the speed, and got rid of issue with building and testing every twice. +* Upgraded Eclipse Compiler for Java (ECJ) to version 3.7. +* Upgraded jni4net (Java <-> .NET bridge) to version 0.8.6.0. + +## Version 1.7.3.2 (23-Aug-2011) + +### Bug Fixes +* [Bug-313][]: Robocode .NET does not work on Java 7. +* [Bug-312][]: Enabling Paint Freezes Robocode. +* Fixed problem with XML serialization of just killed robot. +* Fixed bug in temporary record cleanup. + +### New Features +* Implemented deserialization of XML with short tags. + * The command line argument ``-replay`` now supports zipped XML. + +### Changes +* Various optimizations to let [RoboRumble][] start up and run faster. + * E.g. sound module and image loading is disabled when running the rumble. +* Imroved XML deserialization. +* [Patch-1][]: Improved priority battle handling. + * Patch by Jerome Lavigne ("Darkcanuck") - Improved priority battle handling in [RoboRumble][]. + * This change will help improve the efficiency of the [RoboRumble][] system and allow battles to be distributed more evenly + fix some inconsistent console output. + * Improves [RoboRumble][] client-side processing of priority battles received from the rumble server. Specifically: + 1. Priority battles will be discarded for bots that the client knows are no longer in the participants list (the client is aware of bot removals before the server is). + 2. Duplicate priority battles received from the server will be discarded (the server does not maintain state of which battles are sent to specific clients, so duplicates can be common). +* Upgraded to jni4net 0.8.5.1 (fixes [Bug-313][] above). + +## Version 1.7.3.1 (28-Jul-2011) + +### Bug Fixes +* [Bug-302][]: Hide enemy name implementation bug. +* [Bug-303][]: ``bullet.equals`` semantic has been change in 1.7.3.0 version. +* [Bug-304][]: ``setColor(null)`` causes NPE. +* [Bug-305][]: TeamRumble priority battles bug. +* [Bug-306][]: Rumble sh scripts for launching do not handle spaces in path. +* [Bug-307][]: Console output cannot handle non-ascii names. +* [Bug-308][]: ``ConcurrentModificationException`` in ``URLJarCollector``. +* [Bug-309][]: robot in development generates * into filename. +* [Bug-310][]: Interface Robot skips turns at end of round. +* Bug: ``BulletHitEvent.getBullet().getVictim()`` always returned null. + +### New Features +* [Req-135][]: Twin Duel configuration files. + * Twin Duel configuration files for the [RoboRumble][] client are now included. + +### Changes +* The Robot Editor is now saving and loading source files in UTF-8 (Unicode). +* Upgraded to use jni4net v0.8.4. + +## Version 1.7.3.0 (20-May-2011) + +### Bug Fixes +* [Bug-301][]: ``getTurnRateRadians`` incorrect for negative velocity. +* Fixed issues with unit-testing and building Robocode on Linux. + +## Version 1.7.3.0 Beta (26-Mar-2011) + +### Bug Fixes +* [Bug-222][]: Some of sound not working. + * The gunshot sound was not working. +* [Bug-297][]: x,y coords between ``BulletHitEvent`` & ``HitByBulletEvent`` differ. +* [Bug-299][]: Custom events no longer firing after clearing event queue. +* Fixed typo in the documentation with valid range of values for the battlefield width and height. + * Thanks goes to Tams Balog for pointing this out. + +### New Features +* Added "Enable auto recording" option to the Common Options, which automatically generates a zipped XML record for every battle. + * Works only when "Enable replay recording" is enabled (is automatically set when enabling auto recording). +* [Req-124][]: Ability to save the properties file for robots in dev. path. +* [Req-129][]: ``Rules.getBulletSpeed``. + * It is about keeping the bullet power within 0.1 - 3.0, even when input is lesser or greater than this valid range. +* [Req-128][]: In battle name hiding. + * A general solution has been provided. A new game rule, "hide enemy names", can be enabled or disabled. + +### Changes +* Upgraded to use jni4net v0.8.3. + +## Version 1.7.2.2 (04-Nov-2010) + +### Bug Fixes +* Fixed "3 * PI / 4 means West" in the Robot API, which should be "3 * PI / 2 means West". + * Thanks goes to Gottl Johannes for pointing this out. + +## Version 1.7.2.2 Beta (02-Oct-2010) + +### Bug Fixes +* [Bug-290][]: Development Options remove wrong item. +* [Bug-291][]: JavaDoc missing ``_Robot`` and similar +* [Bug-292][]: Robot PrintStream doesn't handle write in a portable fashion. +* [Bug-293][]: Wrong headings with the JuniorRobot. + * Thanks goes to Mr. Kschan for finding and providing a fix for this bug. :-) + +### New sample robots +* Tuan Anh Nguyen provided a modified version of the interactive sample robot named ``Interactive_v2``, which use absolute movement (up, left, down, right) on the screen that can be easier to control than the original ``Interactive`` sample robot. + * Both Interactive robots now use both the arrow keys and the W, A, S, D key for moving the robot. +* Sample robots have been written for the \#F language which are put in the "/samples/SampleFs" directory. + * These \#F sample robots are available with the .NET plug-in and comes along with Visual Studio project files. + +### New Features +* Implemented Robocode .NET Control API plug-in (robocode.control.dll) with documentation. +* [Req-115][]: Installed package should contain readme file. + * Added ReadMe.txt (using Markdown syntax) and ReadMe.html. + * The ReadMe is available from the Help menu. +* [Req-118][]: Enable/disable development paths. + * Check boxes for each of the entries in has been added to the Preferences -> Development Options. +* [Req-119][]: Provide JuniorRobot template for inexperienced users + +### Changes +* Robocode has been upgraded to use jni4net v0.8 with CLR 4.0 support. +* It is not necessary to specify ``-Dsun.io.useCanonCaches=false`` anymore with the startup scripts for Robocode and [RoboRumble][] as this property is now automatically set internally when running Robocode under Windows. + * Hence, this property has been removed from all .bat, .sh, and .command files for Robocode. +* Robocode will not notify about Beta versions anymore per default. + * However, a new option in the Common Options (under Preferences) makes it possible to enable/disable notifications about new Beta versions. +* The tabs for the "Common" and "Development Options" in the Preferences window are now the first tabs. + +## Version 1.7.2.1 (05-Aug-2010) + +### Bug Fixes +* [Bug-283][]: Possible for robot to kill other robot threads. +* [Bug-287][]: Zipped robots data files are not extracted. +* [Bug-284][]: Robot Packager doesn't package source file in Eclipse proj. +* [Bug-215][]: Missed onRobotDeath events. + * Thanks goes to ForNeVeR for finding and solving this bug. +* [Bug-282][]: Cannot see robot with no package in New Battle dialog. +* [Bug-285][]: Robot Packaging Wizard doesn't save value for Next & Back. +* [Bug-286][]: ``ClassNotFoundException at RobotClassLoader.java:271``. +* [Bug-288][]: "skipped" turns at start with ``-Ddebug=true``. +* [Bug-289][]: Exclude filters not working. +* Bug: Sometimes the compiler window was hanging for several seconds, even though the compiler had finished compiling. + +### Changes +* The Robot Packing Wizard will now only allow word characters (letters, digits, dots, *but not spaces*) with the version field. +* Added ``robocode.annotation.SafeStatic``, which can be used to suppress warnings in the robot console for a robot that uses a static Robot reference on a field. + * Note that this means that your robot will need to clean the static field, when a new round is started. + * This annotation was suggested by Nat Pavasant: + + @SafeStatic + private static AdvancedRobot robot; +* Added syntax highlightning on Java annotations for the Robot Editor. + +## Version 1.7.2.1 Beta (19-Jun-2010) + +### Bug Fixes +* [Bug-231][]: Lockup on start if too many bots in robots dir (cont'd). + * Additional fixes were made. +* Fixed some issues with the robot repository when file URLs contains spaces, where robots were sometimes disappearing from the repository. + +### Changes +* [Req-99][]: Move away from Jikes towards ECJ. + * Jikes 1.22 has been replaced with the Eclipse Compiler for Java (ECJ) 3.5.2. + +## Version 1.7.2.0 (28-May-2010) The ".NET robots are now supported" release + +### Bug Fixes +* Bug: Robots were disabled when skipping 30 skipping non-consecutive turns (or 120 turns when performing I/O operations). + * Now, Robocode is only disabling robots when the robot skips 30 consecutive turns, which is the original behavior, and which has been broken since version 1.6.1.4. +* [Bug-275][]: Duplicate version numbers prevents uploading. +* [Bug-276][]: ``tzu.TheArtOfWar 1.2`` gets ``NullPointerExceptions``. +* [Bug-278][]: Attempting to install robocode over an existing install NPEs. +* [Bug-281][]: The robocode.command is missing the execute permissions bit. +* [Bug-277][]: Problems with ``Graphics2D.fill/draw(Shape)``. +* [Bug-280][]: NPE when uploading results. +* [Bug-274][]: "Ignoring" messages in rumble are duplicated. +* [Bug-269][]: Minor visual bug - Currently selected robot gets covered. +* Bug: A security exception was thrown with development robots trying to access their data directory. + +### Changes +* Robocode will now only install batch files relevant to the hosting system, e.g., .bat files are not installed under Unix/Linux/Mac OS X, and .sh files are not installed under Windows. +* Furthermore, .command files are only installed under Mac OS X, and has now the execution permission bit set (due to [Bug-281][]). +* Robocode will now write out a warning in the robot console when a robot is detected that uses static references to a robot, i.e. static fields that are declared as e.g. a ``Robot``, ``AdvancedRobot``, ``TeamRobot`` etc. (typically references to the robot itself). + * A static reference to a robot can cause unwanted behavior with the robot accessing these. Hence, it is strongly recommended that static robot references in a robot class or within its helper classes are changed into non-static references and that the robot is recompiled afterwards. + * In every round, Robocode is creating new instances of the individual robot, meaning that static references to former ``Robot`` objects points to "dead" ``Robot`` objects that are not used anymore in the game, and which cannot be garbage collected during the battle when there is static references to these. + +## Version 1.7.2.0 Beta 3 (29-Apr-2010) The ".NET robots are now supported" release +Thanks goes to Alex Schultz for keep finding bugs, but also helping out solving these. :-) + +### Bug Fixes +* [Bug-271][]: Battle engine consumes more CPU power over time. +* [Bug-267][]: Strange issue first time running roborumble in 1.7.2.0 Beta2. +* [Bug-272][]: ``isTeammate()`` sometimes returns false with teammates. +* [Bug-263][]: Cannot extract downloaded robot for editing in Robot Editor. +* [Bug-270][]: Strange thread exceptions with kid.DeltaSquad in 1.7. +* [Bug-228][]: ``Krabb.sliNk.GarmTeam 0.9v`` locks up in new beta. +* [Bug-265][]: Occasionally losing the bit of text in the robot console. +* [Bug-255][]: ``java.lang.Error: Interrupted attempt to aquire read lock``. +* Bug: Teams with versions could not be found in a development path. +* Bug: Files in ``/robots/.data`` or ``/robots/.robotcache`` directory were put into an underscore sub-directory. +* Bug: The "Kill Robot" button in the robot console windows was often disabled. + +### Changes +* The robot console now uses a rolling buffer so when the number of lines in the robot console exceeds the max number of lines (500), the oldest lines are removed, and ``^^^ TEXT TRUNCATED ^^^`` is written in the top. + * Previously half of the text was truncated when the max number of lines was reached. + +## Version 1.7.2.0 Beta 2 (14-Mar-2010) The ".NET robots are now supported" release + +### Bug Fixes +* [Bug-254][]: Roborumble doesn't upload with ``EXECUTE=NOT``. +* [Bug-257][]: Team RoboRumble uploading is broken. +* [Bug-262][]: TeamRumble: Cannot find robot in nested .jar files. +* [Bug-244][]: Robot static data isn't being GCed after battle. + * Additional fixes were made to solve this issue. +* [Bug-258][]: ``isTeammate()`` called on null gives ``NullPointerException``. +* [Bug-260][]: ``ArrayIndexOutOfBoundsException`` when starting team battle. +* [Bug-250][]: Installer installs ``AutoExtract$1.class``. +* [Bug-252][]: ``yk.JahRoslav 1.1`` throws ``WinException``. +* [Bug-259][]: ``jlm.javaDisturbance`` loses substantial score in 1.7.2 Beta. +* [Bug-261][]: (.NET) condition tested on concurrently modified collection. + +### License Change +* We have changed license from Common Public License (CPL) v1.0 into Eclipse Puplic License (EPL) v1.0. + +## Version 1.7.2.0 Beta (15-Feb-2010) The ".NET robots are now supported" release + +### Bug Fixes +* [Bug-244][]: Robot static data isn't being GCed after battle. +* [Bug-245][]: Removing directories from "development options" doesn't work. +* [Bug-247][]: Version ordering is somewhat strange with letters. +* [Bug-243][]: Robot console text sometimes disappears. +* [Bug-240][]: ``morbid.MorbidPriest_1.0`` fails to load. +* Bug in ``RobotClassLoader`` causing ``ClassNotFoundException`` for some robots during robot class load. +* Fixed a ``NullPointerException`` occuring when Robocode is (re)loading the robot repository after a developer path has been removed. + +### New Features +* .NET Robocode plug-in. + * It is now possible to code robots in .NET and let them engage in Robocode battles. :-) +* [Req-101][]: ``onRoundEnded()``. + * It is now possible for robots to get notified when a round has ended. + * The ``onRoundEnded()`` event handler receives a new ``RoundEndedEvent`` that contains information about the number of turns in the round and total turns in the whole battle when the event occurred. + * The ``robocode.control.RoundEndedEvent`` in the Control API has been extended with a new method named ``getTotalTurns()`` similar to the new ``robocode.RoundEndedEvent`` for the Robot API. +* [Req-114][]: RateControlRobot vs. TeamRobot. + * The ``RateControlRobot`` is now a ``TeamRobot`` meaning that it can participate in team battles. +* [Req-113][]: Skipped turn events. + * Added ``getSkippedTurn()`` method on the ``SkippedTurnEvent`` class, which returns the turn that was skipped. + * The ``SkippedTurnEvent.getTime()`` returns the time when the ``SkippedTurnEvent`` was processed by the robot, which is always later when the robot is skipping turns. + * The message ``SYSTEM: you skipped turn`` has been improved, so it will tell which turn that was skipped like ``SYSTEM: john.Doh skipped turn 43``. +* [Req-80][]: Screenshot of battleview. + * Press Ctrl+T on Windows and Linux, and Command+T for Mac OS in order to take a screenshot of the battle view. + * The screenshot will be saved in the Robocode folder named "screenshots", and the filename will be a timestamp for when the screenshot was taken. +* [Req-89][]: Launch Robocode from .br (battle record) files. + * Robocode is now able to launch from from .battle (battle specification) and .br (battle record) files in Windows. +* [Req-86][]: Rankings should be visible when Robocode is minimized. + * A new View Option has been implemented to preventing speedup when minimized. + * This new View Option can now be set in the Preferences by putting a check mark into "Prevent speedup when minimized". +* [Req-93][]: Rename ``/robots/.robotcache`` to ``/robots/.data``. + +### Changes +* Browser support has been improved for Mac OS, Unix and Linux, which in most cases did not work properly. + * In previous versions of Robocode, the browser.sh was used to start up the user's preferred browser. The browser.sh file is not being used anymore. Hence, this file can safely be removed from your Robocode installation dir. + * Now, Robocode will start up a browser under Mac OS, Unix and Linux with no use of scripts. +* The Development Options dialog in the Preferences has been improved: + * Changed from using single interval selection to multi selection interval. + * Adding an existing path is ignored. + * The list of path is automatically sorted. + +## Version 1.7.1.6 (06-Jan-2010) + +### Bug Fixes +* [Bug-237][]: OS X 10.6: Cannot run Robocode from robocode.sh. + * It must be run from the new robocode.command file instead. +* [Bug-238][]: OS X 10.6: The editor cannot see the JD + * It must be run from the new robocode.command file instead. +* The ``onDeathEvent(DeathEvent)`` method was called too late, when a new round was about to start. Not when the robot has died. +* [Bug-231][]: Lockup on start if too many bots in robots dir (cont'd) + * Additional fix was made to locate multiple robots under the same package. +* Changed the robot painting so that everything that goes into the painting buffer is always painted, and remaining painting operations exceeding the buffer capacity are always dropped. + * Previously, only the last painting operations exceeding the painting buffer were executed. + +### New Features +* The amount of used memory and total memory is now shown in the title bar of Robocode. + * This is useful to see how much memory your robots are consuming. + +### Changes +* If the robot paints too much between actions, an improved error message is written out in the robot console. + * But from this version of Robocode this message is only written out once. +* A ``SecurityException`` is now thrown if a robot exceeds its max. data file quota, meaning that it uses more than 200.000 bytes its data files in total. + +## Version 1.7.1.6 Beta (10-Dec-2009) + +### Bug Fixes +* [Bug-236][]: Robot Editor doesn't accept packagename with dot (.) in it. +* [Bug-234][]: Source is not included. + * Additional fix was made for this issue. +* [Bug-231][]: Lockup on start if too many bots in robots dir (cont'd) + +### Requests +* [Req-92][]: Scrollable properties. + * All console windows including the Robot Console and Properties are now scrollable, and all have the same look. + +### Changes +* It is now possible to add paths to robot project inside an Eclipse workspace under the Development Options in the Preferences. + * Robocode will read the .classpath file in the project in order to locate both class files, properties files, and java files. + * This means that the Robot Packager is now able to include your source files when you use Eclipse, and it supports multiple source paths. + * **Note:** Robocode does not support linked sources or include and exclude filters. +* Changed the messages given when creating a new robot with the Robot Editor regarding robot name and package name. + +## Version 1.7.1.5 (11-Nov-2009) + +### Bug Fixes +* ``RobocodeFileOutputStream.getName()`` always returned ``null`` instead of the filename. +* Robots listed in e.g. the New Battle window was sorted like: 1.1.1, 1.1.10y, 1.1.2, 1.1.10 (alpha-numerical). + * But version numbers with an ending letter like in "1.1.10y" like in the versions just listed, were not placed in the correct order. + * Notice that 1.1.10y is between 1.1.1 and 1.1.2. This bug has been fixed so the versions in the example now will be sorted correctly like: 1.1.1, 1.1.2, 1.1.10, 1.1.10y. + +## Version 1.7.1.5 Beta (14-Oct-2009) + +### Bug Fixes +* [Bug-232][]: ``Graphics2D.getTransform()`` throws NPE. +* [Bug-233][]: "Teleport" + * occurred when robot's distance remaining was very large. +* [Bug-234][]: Source is not included. + * ``robot.java.source.included`` was not set in the robot.properties file. + +## Version 1.7.1.4 (25-Sep-2009) + +### Bug Fixes +* [Bug-226][]: ``java.io.FileNotFoundException`` in ``RobotFileSystemManager.init``. +* [Bug-227][]: Can't load ``Katana 1.0`` or ``DrussGT 1.3.1wilo``. +* [Bug-230][]: Lockup on start if too many bots in robots dir. +* [Bug-229][]: ``IllegalArgumentException`` on painting in some robots? +* Fixed ``NullPointerException`` that could occur with the ``-battle`` command-line option. + +### Changes + +#### Banning +* The previous 1.7.x.x versions have been very strict so that robots that could not be loaded, started, skipped too many turns etc. would be disallowed to participate in battles. + * With the bug fix for [Bug-227][] above this policy has been changed so robots are only "banned" if they cause a security violation or they could not be loaded or started (meaning that they will not be allowed to run). + * In addition, ALL security violations are always written out in both the main console and robot's console. A message will be written out in the main console like ``xxx has caused a security violation. This robot has been banned and will not be allowed to participate in battles``. + +#### Painting +* With the bug fix for [Bug-229][] a change was made so a robot will now receive this message in its console window, if it is painting too much between actions: + + SYSTEM: This robot is painting too much between actions. Max. capacity has been reached. +* Notice that a robot is not allowed to perform an unlimited amount of paint operations for two reasons: + 1. It takes up a lot of memory as the painting operations are recorded in a buffer before being processed, and potentially this buffer must be recorded to a file (for replays). + * A robot is allowed to use up to a maximum of 64 KiB per paint action. An average painting operation like e.g. ``fillRect(x, y, width, height)`` takes up 15 bytes, meaning that more than 4000 painting operations should be possible per paint action, which is a lot. + 2. It takes a lot of CPU cycles to process the painting buffer to the display making the painting slow if the buffer is too large. +* It is possible to remove the limit for the robots painting buffer by using the existing command-line option: ``-Ddebug=true``. + +## Version 1.7.1.4 Beta (26-Aug-2009) +This version is dedicated for the [RoboRumble][] community where many issues seen with the RoboRumble client have been solved. + +Thank you all for reporting as many known issues as possible, and also help out solving these - especially with the issue seen with the robot movement that had a big impact on the scores and rankings! :-) + +A big thanks goes to Patrick Cupka ("Voidious"), Julian Kent ("Skilgannon"), "Positive" and Nat Pavasant ("Nat") for their combined work with developing and testing the new and improved robot movement regarding acceleration and deceleration rules ([Bug-214][]). :-) + +### Bug Fixes +* [Bug-214][]: Accel/decel rules introduced in 1.7.1.3 causes trouble. +* [Bug-215][]: Missed onRobotDeath events. +* [Bug-212][]: Team jar files reported as corrupted. +* [Bug-208][]: Does not extract .properties files into bot data dirs. + * The previous fix for this issue did not work properly as the file sizes were truncated to 0 bytes. +* [Bug-216][]: Sometimes too few results for robots are displayed. +* [Bug-213][]: ``NullPointerException`` when setting classpath directory. +* [Bug-209][]: [Codesize] Invalid entry point in codesize-1.1.jar. + * Previous fix was not working properly. +* [Bug-218][]: Robocode enters infinite loop with the Restart button. +* Bug: The RateControlRobot (Beta) returned rates in radians instead of degrees with the methods: ``getTurnRate()``, ``getGunRotationRate()``, and ``getRadarRotationRate()``. + +### Changes for RoboRumble +* Updated the PARTICIPANTSURL in the roborumble.txt, meleerumble.txt, and teamrumble.txt. + +## Version 1.7.1.3 (08-Jul-2009) + +### Bug Fixes +* [Bug-210][]: Bullet and Ram Damage Bonuses are wrong. +* [Bug-208][]: Does not extract .properties files into bot data dirs. +* [Bug-207][]: Access denied ``javax.swing`` ``-DNOSECURITY=true``. +* [Bug-209][]: [Codesize] Invalid entry point in codesize-1.1.jar. +* Bug: Sometimes the "Show results when battle(s) ends" in the Common Options was disabled when running the RobocodeEngine, even though the setting had been enabled earlier. +* A ``NullPointerException`` occurred when closing the Preferences window, when no sound device is present in the system. + +### Changes +* The default font on the ``Graphics`` context when using ``onPaint(Graphics2D)`` or ``getGraphics()`` has been changed to the "Dialog" font. + +## Version 1.7.1.3 Beta (08-Jun-2009) + +### Bug Fixes +* ``AdvancedRobot.setMaxTurnRate()`` did not work properly since version 1.5.4. +* [Bug-205][]: Wrong survival scores sent by rumble client. +* [Bug-206][]: Funny behaviors with robot graphics/painting. + +### New RateControlRobot (Beta) +* Joshua Galecki has provided a new robot type, the ``RateControlRobot``, which is an extension of the ``AdvancedRobot``. +* The ``RateControlRobot`` class has been created in an attempt to allow more realistic robots. + * That is, many real/physical robots are given commands in terms of rates ("move forward one meter per second"). Hence, the ``RateControlRobot`` helps simulating a real robot. +* With this release, we ask the community for feedback and we will announce it as stable in one of next major releases. So please report issues or change requests etc. for this new robot type. + +### Changes for RoboRumble +* Added validation of each of the participant lines of the participant list. + * If a participant line is invalid due to e.g. wrong format/syntax or bad URL, then an error message is written out and the participant is ignored. +* The format of the lines in the participant lines is the same as usual. + * Accepted lines must follow this format: ``,(|)``, where must match the regular expression ``[\\w\\.]+[ ][\\w\\.-]+``, the must be a HTTP URL pointing at the robot .jar file, and the must be a number. The and are mutual exclusive. + * Example of accepted lines: + + johndoe.SomeRobot 1.0,http://somewhere.com/SomeRobot\_1\_0.jar + johndoe.SomeRobot 1.0,321 + +* Removed the info message "Trying to download " from the console output. + +### Other changes +* The Development Options has become more usable, as Ruben Moreno Montoliu has added a list of paths and buttons for adding and removing directories, full resizable. +* Updated the Javadoc with a note for the ``setAdjustXX()`` robot methods, which are ignored when turning with infinite values. + +## Version 1.7.1.2 (25-May-2009) + +### Bug Fixes +* [Bug-199][]: FontMetrics StackOverflowError. +* [Bug-200][]: ``Graphics2D.setFont()`` has no effect. +* [Bug-201][]: ``setMaxVelocity(lower than current) + reverse`` direction bug. +* [Bug-196][]: Wrong file path used for development bots. + * Refixed. +* [Bug-202][]: Installer says to run robocode.jar. +* [Bug-204][]: Nanobot rumble not sending melee or team parameters. + * Thanks goes to Jerome Lavigne ("Darkcanuck") for this fix. +* Fixed three bugs introduced with the Beta version found using new test units: + * One bug where the speed would immediately drop to max. velocity when calling ``setMaxVelocity()`` - disregarding the acceleration and deceleration rules. + * Another bug where the turn rate was a bit wrong when moving back and turning left in the same time. + * A third bug where the robot continued to move backwards when it should have stopped due to ``setAhead(0)`` or ``setBack(0)``. + +## Version 1.7.1.2 Beta (08-May-2009) + +### Bug Fixes +* [Bug-139][]: Bug in RobotPeer.updateMovement? + * Robocode was not moving 100% according to it's own rules. Now it is. +* [Bug-192][]: Fair Play! + * With two identical robots in a battle against each other, the first robots was much more likely to win, which was not fair. +* [Bug-195][]: Client tries to remove all participants. + * When RoboRumble, TeamRumble, and/or MeleeRumble downloaded the participants list and did not receive a ``HTTP_OK`` or an empty list, the participants list was emptied. This caused problems with the RoboRumble server. +* [Bug-196][]: Wrong file path used for development bots. + Added option ``-DALWAYSUSECACHEFORDATA`` for anyone who liked it better. +* [Bug-197][]: Melee rumble doesn't use "smart battles". + * Thanks goes to Jerome Lavigne ("Darkcanuck") for this fix. + * Smart battles are also known as "priority battles". +* Fixed several ``ArrayOutOfBoundsExceptions`` occurring when starting a battle with fewer robots than a battle just played with more robots. + +### Changes for RoboRumble +* The participants URL for RoboRumble, MeleeRumble, and TeamRumble have been updated to use the participant lists from the new RoboWiki: + * [RoboRumble](http://robowiki.net/wiki/RoboRumble/Participants). + * [MeleeRumble](http://robowiki.net/wiki/RoboRumble/Participants/Melee). + * [TeamRumble](http://robowiki.net/wiki/RoboRumble/Participants/Teams). + +### Other changes +* Updated the Help menu to point at the new RoboWiki regarding the Online Help and FAQ. +* RobocodeEngine control class: Added additional ``runBattle()`` method where it is possible to specify the initial positions of the robots when starting a battle. +* The about box was updated, where contributors are now written in bold and in a green color. + +## Version 1.7.1.1 (10-Apr-2009) +With this release we have focused on eliminating as many problems seen with [RoboRumble][] as possible. Hence, this version should hopefully prove stable as the new RoboRumble client. + +### Bug Fixes for RoboRumble +* [Bug-188][]: Meleerumble using 2 bots instead of 10. + * Now the ``MELEEBOTS`` (number of robots that participate in a melee battle) works as expected. +* [Bug-193][]: TeamRumble uploading result for Robot instead of team. +* [Bug-187][]: Not enough java memory allocated in launch scripts. + * The launch scripts for RoboRumble and TeamRumble were changed so it is allowed to use up to 512 MB heap memory, and MeleeRumble is allowed to use up to 1024 MB. +* [Bug-191][]: ``EOFException`` during repository rebuild. + * Exception is now reported in a simplified way. +* [Bug-194][]: JarJar multi-registration. + * RoboRumble was not reusing the same RobocodeEngine instance. + +### Other bug fixes +* [Bug-169][]: ``pe.SandboxDT_3.02`` stopped working in 1.6.2 and later version. + * We had broken semantics of ``getTeammates()`` to return empty array when there is no team. +* [Bug-189][]: API - cannot subclass Event in 1.7.1. +* [Bug-190][]: Errors with some robot classes when rebuilding database. +* [Bug-185][]: Webpage button lay over robot description. +* [Bug-186][]: Rounds number do not saved between run. + +### JuniorRobot changes +* Bug - The event variables ``scannedXX`` and ``hitXX`` on the JuniorRobot was not reset to -1 (or -99) when nothing was scanned or hit. +* [Req-90][]: Prevent JuniorRobot to be unresponsive. +* **Change:** JuniorRobot will now automatically scan for enemies when it is not moving. + +## Version 1.7.1 (24-Mar-2009) + +### Bug Fixes +* [Bug-176][]: Editor UNDO does delete the line when no undo left. +* [Bug-180][]: Editor: Find (set cursor position). +* [Bug-182][]: roborumble.sh and teamrumble.sh are broken. +* [Bug-183][]: ``NullPointerException`` in ``BattlesRunner.runBattlesImpl``. +* [Bug-184][]: Custom event priority broken. + +### Changes +* The New Battle dialog is now larger per default. +* The layout of the View Options and Sound Options tab in the Preferences has been improved. + * An error dialog is shown when the input field for the desired TPS is out of range. + +## Version 1.7.1 Beta 2 (11-Mar-2009) + +### Bug Fixes +* [Bug-178][]: Typing to find bot no longer works. +* [Bug-181][]: API: Typo in Documentation ``onBulletMissed(BulletMissedEvent)``. +* [Bug-179][]: Event.setTime() method should not be hidden. + * Put back ``setTime()`` method of ``Event``, the security is now handled other way instead of hiding the field. +* Fixed the problem with loading team robots from nested .jar files. +* On Ubuntu (Linux) the "Default window size" did not work properly. + +### Internal Changes +* On SUN's JVM enabled caching of .jar files opened thru ``URLConnection``. + * Solved problem with closing such files by implementing ``URLJarCollector``. + +## Version 1.7.1 Beta (01-Mar-2009) +With this release we give BIG thanks to Nat Pavasant who have put in great effort in testing and finding as many bugs in Robocode as possible. He has been a great help with testing especially [RoboRumble][] functionality. + +Currently, there is one known issue, which will be fixed with the next Beta or in the final release of version 1.7.1. This is critical for e.g. the TeamRumble, so please notice the known issue below. + +### Known issue +* With this version Robocode cannot handle team packages containing robot .jar files, i.e. robot packages. + +### Bug Fixes +* [Bug-166][]: Bots referencing ``robocode.robocodeGL`` broken. +* [Bug-168][]: Bots inconviently stop working if they go over time limit. +* [Bug-172][]: Robot console fails to display some deaths/wins. +* [Bug-174][]: Robot console is sometimes empty. +* [Bug-173][]: Robot packager can be activated once per running. +* [Bug-175][]: Development robots cause problems with data files. +* [Bug-171][]: A battleview size exceed 800x600 filled with black. +* [Bug-165][]: ``NullPointerException`` when using ``-battle`` option from cmd-line. +* [Bug-170][]: Robot Colors don't stick between rounds. +* [Bug-177][]: Open battle menu dialog is not loading robots. +* Bug: The command line usage of Robocode was not printed out at all when using the ``-?`` or ``-help`` option. + +### New Features +* Added ``getCurrentWorkingDir()`` + ``getRobotsDir()`` to the ``robocode.control.RobocodeEngine``. +* [Req-86][]: Rankings should be visible when Robocode is minimized. + * This feature has been added and it is possible to control the behavior from Common Options in the Preferences with the "Don't hide Rankings when main window is minimized", which is enabled per default. +* [Req-88][]: Command Line option for saving a battle record file. + * Two new command line options have been added for Robocode, i.e. ``-record `` and ``-recordXML ``. + * The ``-record option`` records the battle as a binary and zipped battle record. Here I propose that the specified filename should is something like record.br. + * The ``-recordXML`` does the same as the -record option, but saves the battle record as an XML file. Here I suggest that you use a filename like record.br.xml. +* [Req-49][]: Speedup time required for rebuilding robot database. + +### RoboRumble Changes +* Changed the link for [http://rumble.fervir.com/rumble](http://rumble.fervir.com/rumble) into [http://darkcanuck.net/rumble](http://darkcanuck.net/rumble) as the RoboRumble server fervir is down and with unstable ranking. + * The current ranking at Darkcanuck's server is alive. Almost all clients are point to Darkcanuck's now. Hence, it is updated now. +* [Req-82][]: Launch upload result in separate thread. + * Results from the [RoboRumble][] client is now uploaded in a seperate thread. +* [Req-84][]: Added append option in copy method (``FileTransfer`` class). + +### Internal Changes +* The robot repository has been updated. It is no longer extracting .jar files. + * It also remembers last timestamp on file so detection of the changes is really fast. Only data files are extracted now. + * Data files for non-packed robots were moved to .robotcache as well. +* VersionManager is now able to detect if the Robocode version was upgraded since last run. +* Blocking security issue with relative path in ``getDataFile()`` method. +* Improved security in RobotClassLoader. +* Reimplemented RobotPackager. +* ``BulletSnapshot`` has now method ``getBulletId()`` which gives identity of bullet for UI. + +## Version 1.7.0.2 (16-Feb-2009) + +### Bug Fix +* The fix for [Bug-164][] (Compiler Classpath Suggestion) backfired, as the entire text field in the window with the compiler properties would now be quoted. + * Hence, the compiler would not be able to compile, and it was not possible to change the compiler preferences from the GUI. + +## Version 1.7.0.1 (14-Feb-2009) + +### Bug Fixes +* [Bug-163][]: Spaces or native names in name of robocode directory. + * Some users experienced problems with starting Robocode. Hence, all startup batch and shell files for Windows, Linux, Mac OS X etc. have been corrected. +* [Bug-164][]: Compiler Classpath Suggestion. + * When running Robocode in a folder with spaces, the compiler classpath was not quoted. Hence, the compiler would not work. + +## Version 1.7 (11-Feb-2009) + +### Bug Fixes +* [Bug-160][]: Battle Results screen displaying old results. + * The results where not updated on the Battle Results windows between battles. +* [Bug-161][]: Robot disabled by any other than losing energy can recover. + * Robots disabled due to bad behaviour could regain energy by hitting another robot by a bullet after it had been disabled. + * Now this is only possible when the robot has disabled itself by using all its energy, and will be able recover energy by hitting an enemy, which is allowed. +* [Bug-162][]: Team battle. + * Robots like ``abc.Shadow 3.83``, ``davidalves.Phoenix 1.02``, and ``kawigi.micro.Shiz 1.1``, ``kawigi.micro.ShizPair 1.1`` caused a ``NullPointerException`` and would not show up on the battle window. + +## Version 1.7 Beta 2 (26-Jan-2009) + +### Bug Fixes +* [Bug-158][]: Ubuntu throws ``NullPointerException`` in main. + * This bug occurred when trying to startup Robocode. +* [Bug-159][]: Installation fail on windows if directory contain space. + +### Changes +* Improved the version checking for new Robocode versions available for download. + +## Version 1.7 Beta (19-Jan-2009) +* This version represents a completely new infrastructure of Robocode making it easier to extend and maintain for the future. It does not contain New Features compared to the previous version of Robocode, but focus on working the same way as the previous versions despite of all the restructurings. + +### Bug Fixes +* [Bug-156][]: Spammy output on robot console windows. + +### Internal Changes +* Robocode was modularized using the dependency injection framework PicoContainer. + * This work includes introduction of many interfaces to existing components. +* Introduced Maven2 as build setup where the whole directory layout is based on the standard Maven structure. +* Rewritten the ``RobotClassLoader`` so it is able to load .jar file in the future. +* Rewritten security layer to use ``AccessController`` and ``CodeSource`` for detection of trusted code. +* Redesigned ``RobocodeProperties`` to ``SettingsManager`` and introduced ``ISettingsListener``. +* Implemented ``RbSerializer`` to be able to implement IPC (Inter-Process Communication) in future. + * This should make it possible to extend Robocode for more platforms like e.g. Microsoft .NET. +* Redesigned ``RepositoryManager`` and nearby to hide implementation details. +* Moved all implementation of Robocode to the package ``net.sf.robocode``. + * The old package ``robocode`` is now "used only" for API to outer world in order to keep backwards compability. + +## Version 1.6.2 (04-Jan-2009) + +### Bug Fixes +* [Bug-154][]: Robot name missing when replaying XML record. +* [Bug-153][]: Junior Robot ``turnAheadRight`` bug. + * When a JuniorRobot was calling ``turnAheadRight()``, ``turnAheadLeft()``, ``turnBackRight()``, or ``turnBackLeft()``, the following exception occurred causing the robot to be terminated: + + java.lang.ClassCastException: robocode.peer.proxies.StandardRobotProxy +* [Bug-151][]: Exception when changing between ``Robot`` to ``AdvancedRobot``. + * When a robot was changed from a ``Robot`` into an ``AdvancedRobot`` and recompiled, the game would cast a ``ClassCastException`` if a battle was started or restarted including that particular robot. + * However, this bug did not occur with new battles where the list of robots was refreshed (by pressing Ctrl+R). + +## Version 1.6.2 Beta 4 (22-Dec-2008) + +### Bug Fixes +* Fixed open battle dialog, which was not loading. +* Fixed recorder NPE. +* Fixed serialization problems of scan arc (``Arc2D``). +* Fixed problem with reloading robot repository on each next battle dialog. + +## Version 1.6.2 Beta 3 (18-Dec-2008) + +### Changes +* Published new battle events and battle snapshots in the Control API, i.e. in the ``robocode.control`` package. +* Added missing Javadocs (HTML documentation) to public Robocode API classes. + +### Bug Fixes +* The current scoring (not the total scoring) was calculated wrong from version 1.6.1. + * The current Ramming Kill Bonus was set to current bullet kill bonus, which gave wrong ranking in the Ranking Panel. +* [Bug-148][]: Wrong bullet power. + * Wrong bullet power could be reported back from ``Bullet.getPower()``, which could be ``> Rules.MAX_BULLET_POWER`` or ``< Rules.MIN_BULLET_POWER``. +* [Bug-147][]: gunHeat is negative. + * gunHeat could be negative, which should never occur. +* [Bug-149][]: Replay exception. + * An ``ArrayIndexOutOfBoundsException`` occurred in some situations. +* Fixed problem with ``RobocodeEngine.setVisible(true)``, where the ``RobocodeEngine`` would hang forever. + +## Version 1.6.2 Beta 2 (07-Dec-2008) + +### Bug Fixes +* Fixed problem with Bullet identity. +* Battle cleanup concurrency issue. +* Fixed problem with robots without package. +* AWT AppContext cleanup. +* Fixed versions comparison problem. + +### Changes +* Mostly cleanup of code and documentation. +* Improved compatibility with RobocodeJGAP. +* Development robot version names were visible in the robot repository. + +## Version 1.6.2 Beta (25-Nov-2008) + +### Bug Fixes +* [Req-78][]: Visual debugging without cpu penalty. + * Now Robocode gives a robot unlimited time when painting is enabled on UI (in the robot dialog) for that robot. +* Robocode will not load non-valid robots from repository anymore. +* Fixed placement of the robot dialogs (aka. robot console windows). +* Exception on robot's ``Condition`` doesn't break further processing now. +* [Bug-146][]: Spammy output when running roborumble. + * Output from RoboRumble was spammy when outputting log after the first battle. +* ``java.lang.IllegalArgumentException: Line unsupported: interface Clip supporting format`` could occur when starting Robocode. +* [Bug-81][]: Replay recording does not record paintings. + +### New Features +* [Req-24][]: Recording of battles. (fully implemented) + * Battle recording and replay: Saving to binary and xml file. +* [Req-63][]: Replay should store debug graphics. + * Robot painting and debug properties are now being recorded, but robot painting is not exported to xml. + * Recording is slowing down the game and eats memory and disk space. Hence, you need to enable it in options, as it is disabled per default. +* New command line option ``-replay`` for replaying a battle record. +* New dialog for battle console and battle turn snapshots. +* Robot dialog: New tab-page with robot properties. +* The robot API has been extended with a new ``setDebugProperty()`` method. + * See the ``sample.PaintingRobot`` robot for example of usage. +* [Req-31][]: Redirecting Robot output, running without GUI. + * The ``robocode.control`` package has been improved so that the ``RobocodeEngine`` is able to return much more detailed information about was is going on inside the battle for each turn, round, and battle thru a new ``IBattleListener`` interface. + * With the new ``RobocodeEngine`` it is possible to a detailed snapshot of the game state, e.g. the states of all robots and bullets, and also get the messages sent to the robot console etc. +* [Req-77][]: Better "lifebar" display. + * Robot buttons on the Battle View is now showing the amount of energy and score as two coloured bars within the robot button. + +### Changes +* Redesigned ``RobotPeer`` and ``Battle``. + * Now we send messages between threads instead of synchronizing individual properties. + * Code here is much more readable now. +* Most synchronization is now interlocked. +* Event manager, priority and dispatch of events refactored. +* The methods ``setPriority()`` and ``setTime()`` on the ``Event`` classes are no longer part of the Robot API. + * These methods were used internally by the game. + * Events are final classes now. +* More unit tests were added. +* ``Graphics2DProxy`` optimized. +* Interactive robots are better detected to not waste time of non-interactive robots. +* Team messages are deserialized on receiver robot thread. +* Got rid of robot loader thread. + * Now Robocode is loading on robot's thread, where we got more security. +* Introduced new interfaces for code components. +* Robot threads have ``NORM_PRIORITY - 1``, AWT UI have ``NORM_PRIORITY + 2``. +* [Req-75][]: Add client version to POST data sent to server. + * We now upload the [RoboRumble][] client version when uploading results to the RoboRumble server. +* Robots which are "wrong behaving" are removed from the robot repository and are not given another chance to run. + * This goes for skipped turns, for unstoppable robots and for robots with class loading troubles. +* Changed the formatting of this versions.txt file in order to improve readability. + +## Version 1.6.1.4 (14-Nov-2008) + +### Bug Fixes +* Loosing robots were not receiving ``onBattleEnded(BattleEndedEvent)`` events. +* A new security issue fix for robots that were able to execute code thru the Event Dispatch Thread (EDT). + * **Robots that try to access the EDT will be disabled!** +* [Bug-144][]: drawArc does not work as expected. + * Both ``drawArc()`` and ``fillArc()`` are now using the Robocode coordinate and angle system. +* [Bug-143][]: Blank console window when compiling. + * Some systems still had this issue, so a new fix has been applied. + +### New feature +* [Req-65][]: Score % display. + * The results and current rankings (during a battle) is now showing the score as percentage(s) in parenthesis right beside the score points like e.g. '7875 (12%)' for the total score in the results and '21 / 2900 (7 / 14%)' with the current rankings. + * Thanks goes to Endre Palatinus, Eniko Nagy, Attila Csizofszki and Laszlo Vigh for this contribution! + +### Changes +* The command-line option ``EXPERIMENTAL`` (= ``true`` or ``false``) allowing access to the robot interface peer is now working for the ``RobocodeEngine`` class also. + +## Version 1.6.1.3 (24-Oct-2008) + +### Bug Fixes +* [Bug-143][]: Blank console window when compiling. + * This bug was introduced in 1.6.1.2. + * When trying to compile a robot that would give a compiler error, the output console window for the compiler could be blank on Windows system and/or hang. + * Now the compiler error is output correctly as in previous versions. +* [Bug-137][]: Roborumble ``ITERATE`` broken. + * When running RoboRumble with ``ITERATE=YES``, ``DOWNLOAD=YES``, and ``RUNONLY=SERVER``, the ratings were only read once, not per iteration. + * This bug fix removes a very old bug and the need of using a batch file as workaround in order to do the loop with updated ratings. +* [Bug-141][]: The ``-DROBOTPATH=`` option does not work. +* [Bug-142][]: Broken .sh files. + * An misplaced colon character was included in the teamrumble.sh file. +* Fixed issue with first time access to a robot's data directory after startup, where the robot was not allowed to write to it's own file. + +### Changes +* [Bug-130][]: Various usability issues. + * The list of available robots in the 'New Battle' dialog is now automatically refreshed before it is being shown, when a new robot has been compiled or a robot has been removed. + * The 'Save' and 'Save As' in the File menu of the Robot Editor is now enabled and disabled depending if there is anything to save or not. + +## Version 1.6.1.2 (12-Sep-2008) + +### Bug Fixes +* RoboRumble: Sometimes results were given to the wrong robots, which gave a problem with the robot rankings in the RoboRumble, TeamRumble and MeleeRumble. + * Thanks goes to Joachim Hofer ("Qohnil") for fixing this issue! :-) +* RoboRumble: Robots that read their data file got the following error message: + + Preventing unknown thread from access: (java.io.FilePermission... +* ``ArrayOutOfBoundsException`` could occur when accessing the ``Graphics2D`` object returned by the ``getGraphics()`` method on the ``Robot```classes. +* The ``draw(Shape)`` method on the ``Graphics2D`` object returned by the ``getGraphics()`` method could not draw lines. +* The ``onMousePressed()`` event was called twice instead of only one time per mouse press. + +## Version 1.6.1.1 (28-Aug-2008) + +### Bug Fixes +* Issues with the scoring. + * Sometimes the robots were ranked incorrectly compared to their total scores given in the battle results. +* When disabling the security (``-DNOSECURITY=true``) it would not be possible to run any battles as the following error would occur: + + RobocodeFileOutputStream.threadManager cannot be null! +* [Bug-135][]: ``-battle`` broken. + * When using a battle file, the battles were not displayed one the GUI. +* [Bug-134][]: Robot problem after Options->Clean robot cache. + * Robots that tried to access their data file, like e.g. ``sample.SittingDuck`` got a ``AccessControlException``. +* [Bug-131][]: Sometimes the compiler window hangs. + * This bug only occurred when the compiler gave compilation errors. +* ``IllegalArgumentException`` occurred when calling ``setStroke()`` or ``setComposite()`` on the ``Graphics2D`` object returned by the new ``getGraphics()`` method on the Robot. + +### Changes +* The intro battle will only be shown if a battle file has not been specified using the ``-battle`` command-line argument and Robocode is being run for the first time since installation. + * Previously, the intro battle was always shown even though a battle file had been specified. + +## Version 1.6.1 (17-Aug-2008) + +### Bug Fixes +* [Bug-125][]: TimeoutExceptions occur when debugging in Eclipse. + +### Changes + +#### New Methods +* Added ``getGraphics()`` to ``Robot`` and ``IBasicRobotPeer``. + * A robot is now able to paint itself at any time, and not only using the ``onPaint()`` event handler. +* Added ``getStatusEvents()`` to ``AdvancedRobot`` and ``IAdvancedRobotPeer``. + * A robot is now able to handle status events in the middle of an event handler. + +#### New Event +* [Req-66][]: "onBattleIEnd(*)" Event. + * The the ``onBattleEnded()`` event handler is provided through the new ``IBasicEvents2`` class. + * The new event ``BattleEndedEvent`` has been added. + * When this event occur the new event handler ``onBattleEnded()`` will be called on the robot, i.e. when the battle is ended. + * When reading the ``BattleEndedEvent`` it is possible to read out the results of the battle of the individual robot or team. + * In addition, it is possible to check if the battle was aborted by the game or user. + * The battle results will only be available if the battle is not aborted (where the results does not count). + +#### Paint Events +* Paint events are now put in the robot event queue, meaning that the robots will pay CPU time when their ``onPaint()`` event handler is called. +* Added the ``PaintEvent``, which makes it possible to set the event priority of paint events using the ``AdvancedRobot.setEventPriority()``. + +#### Mouse and Keyboard Events +* Mouse and keyboard events have added as new pulic classes and put into the robot event queue. + * The robots will pay CPU time when their ``onMouseXX()`` and ``onKeyXX()`` event handlers are called. + +#### Package Name +* [Req-70][]: Longer package name allowed. + * The max. length of a robot's full package name has been extended from 16 to 32 characters. + * The Robocode Repository is able to handle this (verified with Dan Lynn). + +#### New TPS Slider +* The TPS slider has been redesigned to be more exponential, so it covers battle in slow speed (1-30 TPS), higher speed (30 - 120 TPS), and fast speed (120 - 1000 TPS). +* If you set the slider to max. TPS the game will run as fast as possible. + * This feature already existed in earlier versions. +* If you set the slider to minimum (0 TPS) the game will pause. + * This is a new feature. + +#### The FPS (Frames Per Second) +* The max. FPS is now fixed to be max. 50 FPS allowing the TPS (turns per second) to be even faster. + +#### New Title Bar +* The title on the Robocode window is now showing the current turn in a battle, and is updated every half second. +* The layout of the information shown in the title has been improved a bit. + +#### Dialogs +* The About box, New Battle Dialog, Preferences Dialog, Ranking Dialog, and the Compiler Preferences Dialog are now modal. +* It is now possible to close the New Battle and Results Dialog by pressing the Esc key. + +#### Ranking Panel +* The menu item for the Ranking Panel is now hidden when replaying a battle. + * The Ranking Panel is now being hidden if it is visible, when a battle is being replayed. + * The reason for hiding the Ranking Panel is that the replay feature does not support displaying the current rankings during the replay, i.e. the current scores are not recorded. + +#### Command-line Options +* Added the new ``-DPARALLEL`` option (set to ``true`` or ``false``), which allows robots to run in parallel intended to take advantage of more CPU's available in the system. + * This option may speedup battles with multiple CPU time consuming robots. However, the time measuring is not per robot. +* Added the new ``-DRANDOMSEED`` option (set to a random seed value), which enables the new repeatable and deterministic random generator. + * The benefit of using this option to make it easier to test and debug your robots, as your robots will appear in the exactly same positions, when you rerun a battle. +* The ``-DPARALLEL`` and ``-DRANDOMSEED`` option has no effect when running RoboRumble, MeleeRumble, and TeamRumble. + +#### New Random Generator +* Added a new deterministic and repeatable random generator is used by the game and overrides the random generator used throughout the whole virtual Java machine. + * Methods like e.g. ``Math.random()`` will be using the exactly the same deterministic random generator enforced by Robocode. +* The new random generator will only be deterministic, if the ``-DRANDOMSEED`` option is enabled, i.e. when ``-DRANDOMSEED=12345678`` (or another value). Otherwise the the battles will run truly randomized. + +#### System Logging +* The system log output has now been split, so logged errors are sent to ``System.err`` and logged messages are sent to ``System.out``. + * This makes it possible to filter out messages from errors when reading out the logs from Robocode. +* The system log also includes a full stack trace when errors are logged, making it easier to determine where an error has occurred. + +#### Various Usability Issues +* [Bug-130][]: Various usability issues. + * Added "Enable all" and "Disable all" button in the View Options of the Preferences. + * When the TPS slider is set to 0, the game is paused, and the Pause/Resume button set to paused mode. + * When the TPS is 0 and the Pause/Resume button is pressed, the game will resume at 1 TPS, and the TPS slider will now move to 1. + * In the New Battle window, the focus is now kept in the list of available robots when one of the two 'Add' buttons has been pressed. + * Previously the focus was lost, and you had to reselect robots in the list of available robots in order to add more robots. + * Multiple robots can now be added to a battle by using the arrow keys with e.g. the Alt+A. + * Rearranged the order of menu items here and there, and also improved the name of some menus. + +## Version 1.6.0.1 (03-Jun-2008) + +### Bug Fixes +* [Req-74][]: Option for enabling/disabling robot timeouts. + * It was not possible anymore to debug robots from Eclipse as ``TimeoutExceptions`` occurred when trying to resume from a breakpoint. + * Now, Robocode must be started by adding the option ``-Ddebug=true`` to the VM arguments when debugging Robocode from Eclipse (or any other IDE). + * The documentation (Wiki) about how to debug robots using Eclipse using the ``-Ddebug=true`` option will be updated. +* Fixed missing internal robot proxy layer introduced in Robocode 1.6.0. + +## Version 1.6.0 (01-May-2008) + +### Bug Fixes +* The CPU constant was not calculated the first time Robocode was started up. +* [Bug-123][]: Compiler fails to build due to CR/LF in scripts. + * Removed ^M characters from the buildJikes.sh file so that the Jikes compiler can be built under *nix based system like Linux and Mac OS X. +* Fixed a security issue where robots could access the internals of the Robocode game thru the AWT Event Queue. + * Robots that try to access the AWT Event Queue will now be disabled due to "bad behaviour". + +### New Robot Interfaces +* A new package named ``robocode.robotinterfaces`` has been introduced, which contains pure Java robot interfaces for basic, advanced, interactive, junior and team robots. + * See the Robocode Javadocs (HTML) documentation for more details about these new interfaces [here](http://robocode.sourceforge.net/docs/robocode/robocode/robotinterfaces/package-summary.html). +* The main purpose of the new robot interfaces is to make it possible for robot developers to create new robot types with their own API, but also to create robots using other programming languages, which requires used of interfaces instead of classes. +* The robot interfaces obeys the rules within Robocode, so it is not possible to create new game rules. However, it is possible to create new robot types with other methods names etc. (new API) based on the new robot interfaces. Also note that is is possible to create your own robots based directly on the robot interfaces. +* See the new '/robots/sampleex' directory for some examples of how to use these new interfaces in Java. +* The introduction of the new robot interfaces required a great deal of changes and cleanup of the internal structures of Robocode, but for the better (future). +* A new command line option has been made for Robocode named ``EXPERIMENTAL``, which must be set to ``true`` in order to allow the robots to access the internal robot peer with the robot interfaces for performing robot operations. + * When this flag is not set, you'll get a SecurityException in your robot if it is inherited from a robot interface. + * This option must be set in the robocode.bat or robocode.sh like ``-DEXPERIMENTAL=true``. + * **Note** that this experimental option might be removed in the future so that robots are always allowed to access the robot peer from the new robot interfaces. +* Most work with the robot interfaces was performed by Pavel Savara that has joined the development of Robocode, who have done a tremendous job with the new robot interfaces. + +### Other Changes +* Added a "Make all bullets white" option to the Rendering Options. +* When this option is enabled, all bullets on the battle field will be painted in white. + * Use this options when you need to see all bullets on the battle field, i.e. when bullet colors are almost invisible. That is, some robots might try make the bullets "invisible" to cheat the observer. + * Thanks goes to [Robocode Ireland](http://robocode.ie/) for holding a turnament showing that this option was crusial when battles are shown on a big screen for a large audience. +* Lots of the Javadoc (HTML) documentation for the Robocode APIs were updated. + +## Version 1.5.4 (15-Feb-2008) + +### Bug Fixes +* [Req-62][]: Fix for massive turn skipping when cpu constant < granularity. + * The CPU constant was way too little compared to version 1.4.9. + * This is a critical bug when Robocode is used for competitions like the [RoboRumble][]. + * Now the CPU calculation has been improved by using a heavy math benchmark that have been adopted from Robert D. Maupin ("Chase-san"). +* The method for determining if a robot has exceeded it's CPU time limit has been improved to use nano second precision (using ``System.nanoTime()``), to get rid of an issue with millisecond granularity that is too coarse. + * This method was created by Julian Kent ("Skilgannon"). + +## Version 1.5.3 (30-Jan-2008) + +### Bug Fixes +* [Bug-122][]: Not all shortcut keys work on MacOS. +* Some of the mnemonics on the menus on the Help menu did not work correctly. +* ``NullPointerException`` occurred when clicking a robot button on the right side of the battle view, when no battle was running. + +### Changes +* Keyboard shortcuts have been replaced to comply with OSes where the function keys (F1 - F12) are not available or have a specific purpose, and thus should not be overridden. + * The F5 shortcut key for refreshing the list of available robots in the New Battle, Robot Packager, Robot Extractor, and Team Creator window has been changed to 'modifier key' + R, i.e. Ctrl+R on Windows and Linux, and Command+R for Mac OS. + * The F6 shortcut key for 'Compile' has been changed to 'modifier key' + B, i.e. Ctrl+B on Windows and Linux, and Command+B for Mac OS. + * The F3 shortcut key for 'Find Next' has been changed to 'modifier key' + G, i.e. Ctrl+G on Windows and Linux, and Command+G for Mac OS. +* When a robot or team is being packaged an UUID is added in the .properties and/or .team files in the newly generated robot or team archive file (robot/team .jar file). + * The UUID is a unique identifier for the robot or team, which is generated every time a robot or team package is being created or overwritten. +* This feature has been made to support New Features provided in Robocode Repository, which is currently being updated. + +## Version 1.5.2 (08-Jan-2008) + +### Bug Fix +* On some systems Robocode would not start up when trying to run robocode.bat or robocode.sh. + +## Version 1.5.1 (12-Dec-2007) + +### Bug Fix +* Fixed security flaw with the Event Dispatch Thread, where robots could use the ``SwingUtilities.invokeLater()`` for running any code they should like to. + * Thanks goes to John Cleland who reported this security flaw and provided some very good examples of robots that could do some nasty cheats/hacks. + +## Version 1.5 (05-Dec-2007) + +### Bug Fixes +* [Bug-115][]: AWTException with RoboRumble on OS X. +* [Bug-97][]: Exception when packaging robots. + +### Changes +* [Req-58][]: HitRobotEvent - damage. + * Redundant ``HitRobotEvents`` are no longer occurring when Robocode is performing collision detection between two robots. + * Previously, if a collision occurred between a stationary robot (i.e. not moving) and another robot that was moving, then two ``HitRobotEvents`` would first be sent to each robot based on the stationary robot - even though no damage was done. Next, two ``HitRobotEvents`` would be sent to each robot based on the robot that was moving, which **was** causing damage. + * Now ``HitRobotEvents`` will only occur when damage is done to each robot. No ``HitRobotEvents`` will be ever be sent when no damage is done. That is, when a stationary robot is "colliding" with another robot. +* [Req-57][]: Events processed in chronological order. + * The events in the robot event queue are now sorted in chronological order so that events that occurred before newer events gets processed first. + * Previously, the event queue was ordered based on the event priorities so that the events with the highest priorities were processed first. + * This could cause some problems with robots with skipped turns, as their event queue would potentially contain events from different time frames. + * Now it is perfectly safe for robots to assume that events occurring before other event are processed first. + * Events occurring in the same time frame is still sorted based on their priorities so that the events with higher priorities are processed before events with lower priorities. +* [Req-53][]: More control over the event queue. + * The priority of the ``DeathEvent`` was changed from the reserved priority 100 to -1 in order to allow robots to process all pending events before they die. + * Previously, robots were not able to process all events when it died as the ``DeathEvent`` was having the highest possible priority. + * Now, when the ``DeathEvent`` has the lowest priority, meaning that this event will be the last event left on the robot's event queue before it dies. That is, all events in the event queue have already been processed when reaching the ``DeathEvent``. +* [Req-60][]: Enhanced CPU constant calculation. + * The CPU constant is now measured in nanoseconds rather than milliseconds. + * Using New Features introduced of Java 5.0 that provides more precise timing and also offer better granularity of timings. +* [Req-64][]: Change default battle settings like e.g. "Number of Rounds". + * The "Number of Rounds" value on the New Battle Dialog is now saved and restored when the game is restarted, i.e. Robocode remember Number of Rounds you used the last time. +* Improved the output of the command line usage of Robocode when called from the command line with the ``-?`` or ``-help`` option. + +### New Features +* [Req-54][]: All input received from events. + * The Robot class has got a new ``onStatus(StatusEvent e)`` method. + * This event handler is automatically called for each turn of a battle, which contain a complete snapshot of the current robot state at that specific time/turn. + * This new method makes it possible to map a specific robot class field value to a specific time. +* [Req-56][]: Robots Cache Cleaner. + * Added the Robot Cache Cleaner tool created by Aaron Rotenberg ("AaronR"). + * This tool is used for cleaning the cache files of the robots, which is very useful with the [RoboRumble][] client, where most problems with the robot repository can be solved by cleaning the robot cache files. + * This tool is activation by selecting "Clean Robot Cache" in the Options menu or by running the tool from a command line (standing in the robocode home directory): + + java -cp ./libs/robocode.jar;./libs/cachecleaner.jar ar.robocode.cachecleaner.CacheCleaner + +## Version 1.4.9 (07-Nov-2007) + +### Bug Fixes +* [Bug-120][]: The renderering is slower on Vista than XP? +* [Bug-116][]: Exclude filter removes bots from the RoboRumble. + * [RoboRumble][] participants excluded with the ``EXCLUDE`` filter were removed from the ratings, which is not the intension. + * In addition, if trailing white-spaces occurred with the comma-separated list for the ``EXCLUDE`` filter, the filter did not filter out participants correctly. + * With the release of 1.4.8 this bug was claimed to be fixed, but unfortunately the bug fix was missing in the build of the 1.4.8 release. +* Corrected bug seen with the ``JuniorRobot``, when first calling ``turnAheadLeft(100,90)`` and then ``turnRight(90)`` right after this call, where the robot turn quickly to the left, but slowly to the right. +* The calculation of the possible frame rate (FPS) was calculated incorrectly. + * This caused Robocode to run with lower FPS (when rendering battles on the GUI) compared to what is possible with the available hardware. + * With this bug fix, Robocode will render the battles even faster than before in most cases. + +### Changes +* When a new CPU constant is being calculated it will now take the system time granularity (OS dependent) into account. + * Previously, if the CPU constant was less than the time millis granularity, then skipped turns could occur on robots when the CPU constant < system time millis granularity. + +## Version 1.4.8 (25-Oct-2007) + +### Bug Fixes +* [Bug-114][]: Wait Interrupted Message. + * With Robocode 1.4.7 a minor bug was introduced so that the robot console printed out "Wait interrupted" when a round was completed. +* [Bug-117][]: Sound card is being dodgey/not detected by OS causes error. +* [Bug-118][]: Battles fail when executing with Eclipse debugger. + * When debugging robots or the Robocode game itself within Eclipse on Windows, the Java VM was crashing with an "Access Violation". + +## Version 1.4.7 (09-Oct-2007) + +### Bug Fixes +* [Bug-112][]: Forcing stop: no score will be generated. + * Some robots did not receive any score even though they won the battle. + * The cause of this bug was due to Robocode that did not always detect if the robot's thread(s) had been properly terminated. + * Thanks goes to Eric Simonton, David Alves, and Aaron Rotenberg ("AaronR") for help solving this issue! +* Teams located in the '/robots/.robotcache' directory were still put into the robot.database file. + * Thus, teams located in the .robotcache directory were incorrectly shown in the New Battle dialog. +* [Bug-110][]: Partial match recording replay. + * "Ghost" rounds: When stopping a battle while recording was enabled and then replaying the recorded battle, Robocode would show the last rounds of the battle even though no recording occurred for these rounds. +* [Bug-113][]: ``-battle`` option runs at full speed. + * When using the ``-battle`` option Robocode would run at full speed, i.e. the TPS set to maximum, even though the GUI was enabled with a predefined TPS. + * Now, the TPS is only set to maximum when the ``-nodisplay`` option is being used. +* [Bug-111][]: Wasted time at end of each round. + * Robocode was wasting time on trying to wake up robots that were dead. + * Robocode was blocked for the amount of milliseconds defined by the CPU constant when a robot was killed in a battle, as Robocode was waiting for the dead robot to wake up for exactly this amount of time. +* [Bug-85][]: No window position in-bounding. + * When starting Robocode, saved window locations (x and y coordinate) of a window might not fit into any of the available screens/displays (e.g. virtual desktop). + * Robocode will now center windows into the current screen displayed. + +### Robocode Changes +* The Stop button is now only enabled when a battle is running and will will be disabled after the battle has ended. + +### RoboRumble Changes +* The configurations files roborumble.txt, meleerumble.txt, and teamrumble.txt have been improved: + * All properties are now documented and have been grouped more logically. + * The ``BATTLESPERBOT`` property has been raised to 2000 for the RoboRumble and MeleeRumble. +* [Req-55][]: Exclude Filter for RoboRumble. + * An exclude filter has now been added, which makes it possible to exclude participants that causes trouble somehow. + * The exclude filter is controlled using the new ``EXCLUDE`` property, which takes a comma-separate list of participants where the wildcards * and ? can be used + * Excluded participants are not added to the participants file, and will not be downloaded or take part in battles. + +## Version 1.4.6 (25-Sep-2007) + +### Bug Fixes +* [Bug-107][]: Bullet hit locations reported inaccurately. + * The coordinates of a ``Bullet`` from a bullet event like ``HitByBulletEvent()`` was not correct as the coordinates of the bullets would follow the bullet explosion on the robot it has hit. + * Now the coordinates of the ``Bullet`` will not change when it hits a robot or another bullet, even though the coordinates of the bullet explosion will change internally (for painting the explosion). + * This means that the coordinates of a bullet received from a bullet event will actually be on the real bullet line. + * The initial explosion painting on a robot has also changed so it shows exactly where the bullet has hit the robot. +* When Robocode cleaned up the robot database a ``NullPointerException`` could occur if the robot database was pointing to a missing file. +* [Bug-108][]: It is possible to restart a battle without any robots. + * The Restart button was enabled when no battles had previously been started. +* [Bug-106][]: Incorrect repaint of paused battlefield. + * The areas of the battle field was repainted with the black background together with the Robocode logo when the game was paused and the battle window was repainted. Hence, it was not possible to see the current state of the game on the battle field. +* [Bug-98][]: When minimized doesn't show actual tps. + * When the Robocode window was minimized the actual TPS and FPS were not shown. +* When installing new versions of Robocode on top of an existing Robocode installation, the About window did not have the right height. + +### Changes +* The color of each bullet is now independent on the current color set with the ``setBulletColor()`` method. + * Previously, all bullets were instantly changing their colors when ``setBulletColor()`` was called. + * Now, the color of the bullet will stick to the bullet color set when the bullet was fired. +* Improved the "Check for new version", so that is able to differ between release type as alpha, beta, and final release types. + +## Version 1.4.5 (17-Sep-2007) The "Fair Play" release + +### Bug Fixes +* [Bug-104][]: Reproducable scoring bug. + * Unfair play: Two robots with the same code (but different names) would get different scores instead of a 50-50 split. + * Robots listed before other robots in a battle would gain a minor benefit compared to the other robots. This was in particular the case if they killed each other at the same time. Then the robot listed first would get a "half turn" advantage over the other robot. + * Now, the ordering does not matter anymore, as when ever the robots are checked one at a time in sequence, then they will be checked in random order. +* [Bug-103][]: ConcurrentModificationException. + * ``ConcurrentModificationException`` could still occur when called one of the ``getXXEvent`` methods with an ``AdvancedRobot``. + * Now all ``getXXEvent`` methods like e.g. ``getAllEvents()`` are all synchronized directly with the internal event queue of the robot before reading out the events. +* [Bug-105][]: ``testingCondition`` flag not reset. + * Test Condition flag of a robot was not reset between rounds. + * If the robot thread was disabled while testing a condition for a custom event all following rounds will trigger an exception: + + robocode.exception.RobotException: You cannot take action inside Condition.test(). You should handleonCustomEvent instead. + +* [Bug-101][]: "Keyboard lockup" with interactive robots. + * The sample robot named ``sample.Interactive`` has been changed for Robocode 1.4.5 so it continues moving forward or back when the UP or DOWN arrow key is being pressed down. Previously, the robot would only move 50 pixel when pressing down the UP or down arrow key, which was not intuitive compared to the behaviour with traditional first person shooter games. Thus, this looked like a bug. +* [Bug-87][]: Round indicator incorrect. + * Again, the title of Robocode was incorrectly showing round N+1 of N when a battle was ended. +* Memory leaks occurring during a round due to missing cleanup of bullets have been removed. + * Note that _ALL_ bullets were actually cleaned up, when ending the battle (containing one or several rounds). + * One good side-effect of this bug fix is that the game is speeded up, especially when running in minimized mode, as the game does not have to perform unnecessary calculations on bullets that is not visible on the battle field anymore. + +### Changes +* The sample robot named ``sample.Interactive`` has been changed so it continues moving forward or back when the UP or DOWN arrow key is being pressed down. + * Previously, the robot would only move 50 pixel when pressing down the UP or down arrow key, which was not intuitive compared to the behaviour with traditional first person shooter games. Thus, this looked like a bug. + +## Version 1.4.4 (09-Sep-2007) + +### Bug Fixes +* With version 1.4.3 a bug was introduced so that ``battleAborted()`` was called in the ``robocode.control.RobocodeListener`` when the battle was not aborted, i.e. when a battle completes successfully. + * This bug caused Robocode clients as e.g. RoboRumble to hang! +* Removed Windows end-of-line characters from the .sh files for RoboRumble. + +### Change +* Robocode now throws a ``NullPointerException`` if the condition parameter has been set to null when calling ``addCustomEvent()`` or ``removeCustomEvent()`` on an ``AdvancedRobot``. + +## Version 1.4.3 (07-Sep-2007) + +### Bug Fixes +* [Bug-95][]: OutOfMemory: Robots are Being Left on the Stack. + * Major bug fixes was done by Nathaniel Troutman to get rid of large memory leaks, especially when creating and destroying ``robocode.control.RobocodeEngine`` instances many times. + * Most of the memory leaks were caused by circular references between internal classes/objects in Robocode. Now, these such circular references are cleaned up. +* The configuration files for RoboRumble was completely missing under the /roborumble folder, i.e. the meleerumble.txt, roborumble.txt, and teamrumble.txt. +* [Bug-94][]: Inconsistent Behavoir of ``RobocodeEngine.setVisible()``. + * This fix was done by Nathaniel Troutman. + * When invoking the RobocodeEngine to directly run a battle(s) and calling ``RobocodeEngine.setVisible(true)``, and then later call ``RobocodeEngine.setVisible(false)`` the results dialog would still show up at the end of a battle. +* [Bug-96][]: Initializing Label even when no display. + * Did another fix where a dummy AWT (GUI) component was created even though the GUI was disabled causing problems when trying to run e.g. RoboRumble remotely without the GUI enabled. +* [Req-52][]: The 'New Battle' window sometimes is spamed with .robotcache. + * Sometimes the "New Batle" window would show robot classes that reside in the .robotcache folder under the /robots folder. This occurred when the robot database was (re)builded, e.g. if the robot.database file was missing. +* [Bug-99][]: Clicking on a bottom area results in ``ClassCastException``. + * When running battles including the MyFirstJunior and the pressing the mouse button outside of the battle field a ``ClassCastException`` would occur. +* [Bug-100][]: Double-clicking "restart". + * When double-clicking the Restart button for the battle window the UI could lock up completely trying to play all battles, and it would not be possible to stop the battle. + +## Version 1.4.2 (26-Aug-2007) + +### Bug Fixes +* [Bug-92][]: RoboRumble tries to connect with GUI. + * RoboRumble was invoking AWT (GUI) stuff when running, which caused problems on systems without support graphical display or running [RoboRumble][] remotely behind a firewall. +* [Bug-102][]: Bots can hold memory after being destroyed. + * When running ``robocode.control.RobocodeEngine`` it caused memory leaks each time a new instance of the ``RobocodeEngine`` was created, even though the object was completely destroyed. +* [Bug-93][]: ``onPaint(Graphics2D g)`` called prematurely. + * The ``onPaint()`` method was invoked just before the robot got the chance of updating it's internal world model. + * Now the battle view is updated as the first thing right after the robots have updated their internal model. +* [Bug-71][]: RobocodeEngine becomes slower the more battles that are run. + * The Robocode engine was halted with spurious exceptions when an exception occurred inside an ``onPaint()`` method in a robot, i.e. when the robot itself causes an exception inside ``onPaint()``. + * Now, whenever an exception occurs inside the ``onPaint()`` method of a robot, the exception is now being catched by Robocode and printed out in the robot console. + * Due to this bug exception handlers have now been added to all ``onKeyXX`` and ``onMouseXX`` events, where the exceptions are now printed out to the robot console. +* A ``ConcurrentModificationException`` bug did still occur with the internal ``EventQueue`` of a robot. + +## Version 1.4.1 (19-Aug-2007) + +### Bug Fix +* [Bug-91][]: ``ConcurrentModificationException``. + * A couple of ``ConcurrentModificationException`` bugs were introduced with version 1.4, which are now fixed. + * Thank goes to Helge Rhodin ("Krabb") for help with solving the bug! + +## Version 1.4 (14-Aug-2007) The "Junior Robot" release + +### Bug Fixes +* [Bug-88][]: Scorch layer. + * I changed the behaviour of the scorch marks + plus a lot more. +* Static fields on robots were not cleaned up anymore after each battle has ended. +* [Bug-90][]: Limit per round, not turn. + * When printing to ``out`` in ``onScannedRobot()`` event before a ``scan()`` call, the the logging to out would stop with an system error that to much is printed out. + +### Changes + +#### Added JuniorRobot +* The ``JuniorRobot`` class is simpler to use than the ``Robot`` class and has a simplified model, in purpose of teaching programming skills to inexperienced in programming students. + * This new robot type has been designed by Nutch Poovarawan / Cubic Creative team. +* Added ``sample.MyFirstJuniorRobot``. + * This robot is very similar to ``MyFirstRobot``, but tracks it's scanned enemy better. + +#### GUI: Changed Menu Shortcut Key +* Robocode forced the use of the Ctrl key to be used as menu shortcut key. + * Now Robocode ask the Java VM what menu shortcut key to use. +* This change means that Mac OS X users should now use the Command key instead of the control key. + * Thanks goes to Nutch Poovarawan for the tip of how to do this! :-) + +#### Improved Battle View a bit +* A red border is now painted around the battlefield when the battleview's height and/or width is larger than the battlefield. +* Explosions are painted outside the battlefield, when the battleview is larger than the battlefield. +* The text for the Robot names and scores are now "clipped" to the width and height of the battleview instead of the battlefield. + +#### Added "Recalculate CPU constant" to the Options Menu +* [Req-50][]: Recalculate CPU Constant. + * This makes it possible to force recalculation of the CPU constant. + +#### RoboRumble Changes +* Redundant RoboRumble config files are now removed from the /config folder. +* Changed ``UPLOAD=NOT`` to ``UPLOAD=YES`` as default, i.e. the results are now automatically uploaded to the RoboRumble server. + +## Version 1.3.5 (04-Jul-2007) The "Fast renderings" release + +### Bug Fixes +* [Bug-87][]: Round indicator incorrect. + * The title was displaying "Playing round N+1 of N" when the battle has ended. +* [Bug-86][]: Using UI removes focus from interactive bots. + * Key events are now received even though the battle view does not have the focus. + +### Changes + +#### Faster Rendering +* The battle rendering is now 30-50% faster due to image buffering (but uses more memory). +* A new "Buffer images" option under the Rendering Options can be enabled/disabled on the fly while playing a battle. + * By default, "Buffer images" is enabled which makes the rendering faster, but which also uses additional memory. +* Due to the faster renderings, explosion debris is now enabled by default. + +#### Controlling Robocode +* The container classes in the robocode.control package are now Serializable, which makes it easy to load and store, battle specifications, results etc., but also to send these over the network. + +## Version 1.3.4 (27-Jun-2007) The "Interactive" release + +### Bug Fixes +* [Bug-84][]: Preferences page problem on machine w/out sound card. + * ``NullPointerException`` occurred when trying to open the Sound Options page from the Preferences when no sound card (or actually audio mixer) is present in the system. + +### New Features +* The Robot class has now been extended with keyboard and mouse events/methods: + * ``onKeyTyped(KeyEvent)`` + * ``onKeyPressed(KeyEvent)`` + * ``onKeyReleased(KeyEvent)`` + * ``onMouseMoved(MouseEvent)`` + * ``onMouseClicked(MouseEvent)`` + * ``onMousePressed(MouseEvent)`` + * ``onMouseReleased(MouseEvent)`` + * ``onMouseEntered(MouseEvent)`` + * ``onMouseExited(MouseEvent)`` + * ``onMouseDragged(MouseEvent)`` + * ``onMouseWheelMoved(MouseEvent)`` + + These New Features adds a new dimension to the game, i.e. you could make robots that must be controlled entirely manual, semi-automized robots, or press various key for changing between various robot strategies, e.g. when debugging. + + Thus, it is now possible to create robots where multiple human players battle against each other, or compete against existing legacy robots. + +### New Sample Robot +* A new sample robot named "Interactive" has been added to demonstrate how to control a robot using keyboard and mouse events only. +* This robot is controlled by the arrow keys and/or the mouse wheel, and let the gun point towards the current coordinate of the mouse pointer used for aiming. Mouse buttons are used for firing bullets with various fire power. + +### Minor Changes +* The background Robocode logo has been changed into green and the Robocode slogan "Build the best, destroy the rest" was added. + +## Version 1.3.3 (22-Jun-2007) + +### Bug Fixes +* [Bug-82][]: Undo comment does not change font color of code. + * Wrong colors when undoing and redoing multiline comment in the Robot Editor +* When a battle was stopped a new battle could start before the previous battle was closed down. +* When restarting a battle while it was paused caused strange behaviour with new battles, and the "Next Turn" button stopped working. +* [Bug-83][]: Ranking Panel Does not update number of competitors. + * In some situations the Rankings Panel did not show the results for all robots. + * This could be seen if first playing a battle with only 2 robots, and then start a new battle with more robots. In this case, only the rankings for the top 2 robots were shown. + +### Changes +* The Rankings Panel and Results Dialog are now automatically packed to fit the table containing the rankings/results. + +## Version 1.3.2 (09-Jun-2007) + +### Bug Fixes +* The ``sample.SittingDuck`` would not start when no GUI is enabled. +* The Look and Feel is not set if the GUI is disabled. +* The robocode.sh ignored command line arguments (e.g. under Linux and Mac). +* [Bug-80][]: Results file is empty with the command line. + * When setting the ``-result`` parameter from the command line the results file was empty. + +### Changes +* When specifying the ``-battle`` parameter the .battle extension and battle directory can be omitted. + * Hence you can write ``-battle sample`` instead of ``-battle battles/sample.battle``. + * If a specified battle file does not exist Robocode will now exit with an error. +* If you specify the ``-results`` parameter the last results will now always be printed out, i.e. with and without the GUI enabled. Otherwise, if the GUI is not enabled (by setting the ``-nodisplay`` parameter) then the last results will be printed out to system out. + +## Version 1.3.1 (30-May-2007) + +### Bug Fixes +* When loading a battle, the robots specified in the battle file were not selected on the battle dialog. +* When the intro battle has finished the battle settings are now reset to the default battle settings. + * This fixes the issue were the fixed robot starting positions are still used in new battles and where the "Number of Rounds" was set to 1 instead of 10. +* [Bug-79][]: Output displayed in bursts. + * The output in the robot console windows were written out in bulks instead of immediately. +* Bugs fixed in RoboRumble which could cause a ``IllegalThreadStateException``. + +### Changes +* Robocode will now print out an error message and just proceed if problems arise with trying to set the Look and Feel (LAF) to the system LAF. +* [Req-44][]: Restart tweak. + * When stopping or restarting a battle, the battle will now stop immediately instead of continuing for a while showing robot explosions when the robots are being terminated due to the stop. +* [Req-45][]: Reset compiler cancel button. + * Added confirm dialog when trying to reset the compiler preferences from the Compiler -> Options -> Reset Compiler in the Robocode Editor in order to prevent the compiler preferences to be reset by accident. + +### New Features +* Added link to Java 5.0 Documentation in the Help menu. + +## Version 1.3 (17-May-2007) Now featuring the RoboRumble client + +### Bug Fixes +* [Bug-78][]: Robots are disabled with no timer or countdown. +* [Bug-74][]: Java FilePermission error during startup. + * The Event Dispatch Thread was denied access by the Robocode Security Manager. +* [Bug-75][]: ``getTeammates()`` problem. + * Changed back the ``TeamRobot.getTeammates()`` to return ``null`` if no teammates are available. + * This rollback was done in order to keep compatibility with robots developed for older versions of Robocode. +* [Bug-72][]: The game won't play sounds on 2nd launch. + * No sounds were played (when enabled) when Robocode was launched the second time. +* [Bug-73][]: Sound don't work. +* [Bug-76][]: Unique error. + * Lots of synchronizations issues and potential ``ConcurrentModificationExceptions`` have been fixed. +* [Bug-70][]: Version 1.2.6A incompatible with Roboleague. + * The bug causes this exception: + + Exception in thread "Thread-4" java.lang.NoSuchMethodError: robocode.control.RobotResults.getRamDamageBonus() +* [Bug-69][]: Robot causes Null Pointer Exception. + * Fixed ``NullPointerException`` occurred when a robot is forced to stop. +* When using ``robocode.control.RobocodeEngine`` it was not possible to play team battles. Instead an ``ArrayOutOfBoundsException`` occurred. +* ``robocode.control.RobotResults.getRamDamage()`` incorrectly returned a double instead of an integer. + * This bug caused problems with running Robocode on RoboLeague. +* The "Enable replay recording" got set if it was not set after running Robocode without the robocode.properties file the first time. +* ``NullPointerException`` could occur when using ``robocode.control.RobocodeEngine`` and the GUI was not enabled. +* The text field for the filename in the robot packager was way too high. +* In RoboRumble, the codesize of some robots were incorrectly calculated to be 0 bytes, and hence these robots was not able to participate in [RoboRumble][] battles. +* This was due to the codesize tool, which could not analyze .jar files inside .jars. + +### Changes + +#### RoboRumble Client is now built-in +* [Req-39][]: Support for RR@Home + * RoboRumble@Home client, originally developed by Albert Prez, is now built-in. + * [RoboRumble][] is the ultimate collaborative effort to have a live, up-to-date ranking of bots. + * It uses the power of available robocoder's computers to distribute the effort of running battles and building the rankings. + * For more information about RoboRumble@Home you should read its [home page](http://robowiki.net/wiki/RoboRumble). + * The version of the RoboRumble client included in Robocode is an updated version of the original one that can run with the current version of Robocode and which has been ported to Java 5. + * Configuration files has been updated, and are available in the 'roborumble' folder. + * Issues with downloading robots from the Robocode Repository site has been fixed. + * Special thanks goes to Gert Heijenk ("GrubbmGait") who did a tremendous job with lots of alpha testing regarding the new RoboRumble@Home built into Robocode! :-D + +#### Codesize +* [Req-38][]: Codesize. + * The codesize tool by Christian D. Schnell has been added to support the built-in [RoboRumle][] plus a new feature for getting the codesize and robot codesize class (MiniBot, MegaBot etc.) when a robot is being packaged. + * This tool has now been taken over by Flemming N. Larsen (agreed with Christian) and updated to version 1.1, which can handle files > 2KB, and also analyse .jar files inside .jar files. + +#### Start Positions +* [Req-36][]: Initial Placement. + * Added feature that allows specifying the initial start positions of the robots on the battlefield. + * By specifying positions by setting ``robocode.battle.initialPositions`` in a .battle using this format ``(x1,y1,heading1),(x2,y2,heading2),(?,?,?)`` you can specify the initial location and heading for each robot specified with ``robocode.battle.selectedRobots``. + * One example is: + + (50,50,90),(100,100,?),? + + * This means that: + 1. the 1st robot starts at (50,50) with a heading of 90 degrees, + 2. the 2nd robot starts at (100,100,?) with a random heading, + 3. the 3rd (and last) robot starts at a random position with a random heading. + + * See the battle/intro.battle for an example of how to use this option. + +#### Robot and Control API +* Added a new method called ``getNameAndVersion()`` to the ``robocode.control.RobotSpecification``. + * This method was added to better support [RoboRumble][] and similar ranking programs. +* Changed the ``TeamRobot.broadcastMessage()`` so it does not throw an ``IOException`` when the robot is not in a team. + +#### Improved File Structure +* The file structure of Robocode has been slightly improved. +* All .jar files including robocode.jar are now located in the libs folder. +* The robot.database and .robotcache files has been moved to the robots folder. +* All RoboRumble related files are located in the roborumble folder. + +## Version 1.2.6A (11-Mar-2007) + +### Bug Fixes +* A ``NullPointerException`` occurred if the battle view was not initialized. +* This bug made it impossible to control Robocode via the ``robocode.control`` package when attempting to show the battle window. + +### Changes +* [Req-37][]: Running Score Window. + * The Ranking Panel and Battle Results are now windows instead of dialoges. + * This means that the Ranking Panel and Battle Results will still be visible when the game is running in minimized mode. + +## Version 1.2.6 (06-Mar-2007) + +### Bug Fixes +* [Bug-66][]: Crash: starting a new round while et.Predator 1.8 is playing. + * With some robots, a ``java.lang.NoClassDefFoundError`` occurred when Robocode tried to cleanup the static fields occupied by the robot when the battles are over. +* [Bug-67][]: Some issues with MessageEvent + priority. + * These 4 issues were fixed: + 1. In the Robocode API -> AdvancedRobot -> setEventPriority there is information about all event priorities except MessageEvent priority. + 2. You can call ``getEventPriority("MessageEvent")``, but when you call ``setEventPriority("MessageEvent", someValue)`` you gets a ``"SYSTEM: Unknown event class: MessageEvent"`` message and the priority doesn't change. (using ``TeamRobot``). + 3. ``getEventPriority("MessageEvent")`` returns 80, so (if it is true) it "collides" with ``CustomEvent`` priority which is also 80 by default. This way you can't assume which event will be called first basing on its priority. + 4. Unlike it is done for other events, there is no ``getMessageEvents()`` function. +* [Bug-68][]: Preferences not saved. + * The rendering options was not set correctly when loading these between battle sessions. +* When using the ``RobocodeEngine.setVisible(true)`` the Robocode window was shown with the wrong size and without the native Look & Feel. + +### Changes + +#### New TeamRobot Method +* Added missing ``getMessageEvents()`` to the ``TeamRobot``. + +#### Default Event Priorities +* The changes were made as some events "shared" the same default priority, making it hard to tell which event would occur before the other. +* ``BulletHitBulletEvent`` priority was changed from 50 to 55. + * Previously, both ``BulletHitEvents`` and ``BulletHitBulletEvents`` used priority = 50. +* ``MessageEvent`` priority was changed from 80 to 75. + * Previously, both ``CustomEvents`` and ``MessageEvents`` used priority = 80. +* The Ranking Panel has been enhanced. + +#### Ranking Panel +* Now the Ranking Panel contains the same columns as the Battle Results. +* Both the current scores and total scores are shown together where it makes sense. +* The column names of both the Ranking Panel and Battle Results have been improved. + +#### New Pause/Debug Button +* [Req-35][]: Pause Button. + * A Pause/Debug button has been added to the Robot Console window. + * This is handy if you want to pause the game when only your robot's console window is open when the game is minimized. + +#### Battle Window +* The Pause/Debug button on the Battle Window has been changed into a toggle button. +* The "Next Turn" button is now always visible, but not alvays enabled. + +#### Documentation +* The documentation of the Robocode API (Javadoc) has been improved a lot. + +#### Installer +* The Installer is now checking is the user is running Java 5.0 or newer. +* If the Java version is older than 5.0, then an error message will display telling the user to install at least JRE 5.0 or JDK 5.0, and the installation is terminated. + +#### robocode.sh +* robocode.sh has been updated. + * Armin Voetter has contributed with an improved version of robocode.sh so that the script resolves the path to Robocode by itself. + +## Version 1.2.5A (19-Feb-2007) + +### Bug Fix +* On some systems Robocode could not start up due to a ``NullPointerException`` in the internal sound manager/cache. + +## Version 1.2.5 (18-Feb-2007) + +### Bug Fixes +* [Bug-65][]: Cannot run robocode after installation. +* [Bug-63][]: BulletHitBullet only destroys one bullet. + * When two bullets collided, one of the bullets was not destroyed, but continued. +* [Bug-64][]: Exception when referencing length of an array of ``String``. + * ``TeamRobot.getTeammates()`` returned ``null`` instead of an empty array when no teammates are available. +* [Bug-62][]: Memory "Leak". + * Memory leak could occur on robots using large objects on static fields. + * Robocode now clean all static object fields that are not final after each battle, but not between rounds. That is, the static fields are now garbage collected. +* Some ``ConcurrentModificationException`` issues were removed. + +#### Changes + +### Sound Effects (SFX) +* The sound effects in Robocode can now be changed. + * This is done by specifying the file for each sound effect using the ``file.sfx.xxx`` property keys in the robocode.properties file, e.g. the ``file.sfx.gunshot`` for setting the sound effect for gunshot. + + * ``robocode.file.sfx.gunshot``: the sound of a gun shot. + * ``robocode.file.sfx.robotCollision``: the sound of a robot colliding with another robot. + * ``robocode.file.sfx.wallCollision``: the sound of a robot hitting the wall. + * ``robocode.file.sfx.robotDeath``: the sound of a robot dying, i.e. exploding. + * ``robocode.file.sfx.bulletHitsRobot``: the sound of a bullet hitting a robot. + * ``robocode.file.sfx.bulletHitsBullet``: the sound of a bullet colliding with another bullet. + +* The supported sound formats can be found [here](http://java.sun.com/j2se/1.5.0/docs/guide/sound/). + +#### Music Support +* Robocode now supports music. +* By specifying the file for each music file using these properties in the robocode.properties file for setting: + + * ``file.music.theme``: the startup theme music. + * ``file.music.background``: background music during battles. + * ``file.music.endOfBattle``: the "end of battle" music when a battle is over. + +* The supported music formats can be found [here](http://java.sun.com/j2se/1.5.0/docs/guide/sound/). + +#### Misc. +* The column names in the Battle Results window have been improved. +* Keys in the robocode.properties file (the configuration file) are now automatically sorted when saved. +* Previously the keys were put in random order each time the property file was saved. + +## Version 1.2.4 (25-Jan-2007) + +### Bug Fixes +* [Bug-60][]: ``ConcurrentModificationException`` when extracting robots. + * This exception sometimes occurred when robots were imported when Robocode was starting up. +* [Bug-59][]: Issue when setting the priority of a ``BulletHitBulletEvent``. + * Added methods for setting and getting the priority of ``BulletHitBulletEvent`` that was missing completely in Robocode?! +* Removed ``IndexOutOfBoundsException`` when replaying battles. +* Explosion debrise was shown in the lower left corner (0,0) when starting battles and battle ground is set to visible. +* [Bug-61][]: Hang when checking for new version with no Internet access. + * Robocode could hang when checking for a new version when no Internet connection was available. + * Now a 5 second timeout has been added to prevent Robocode from hanging. + +### Changes + +#### Robots Die Faster +* [Req-33][]: Making robots die quicker (graphically). + * Robocode stops painting the battlefield and playing sounds when a battle is ended after 35 turns. + * However, the robots still have 120 turns until they are really killed like Robocode is used to, but the battle continues like if it was running in minimized mode (fast). + +#### Options +* The common options for enabling replay recording has been changed to disabled per default. + * When running lots of battles in a row with replay recording enabled Robocode runs out of memory, which causes problems when running tournaments. +* Added "View Explosion Debris" option in the View Options. + * Explosion debris is diabled per default as this feature can slow down the game with 25% - 50% when viewing battles. + +#### Javadocs +* [Req-34][]: Provide javadoc for robocode.util.Utils and robocode.control. + * Javadocs have been provided for: + * The ``robocode.util.Utils`` class providing angle normalizing methods. + * The ``robocode.control`` package used for controlling Robocode externally. + +#### Files +* Fixed incosistency with .jar files located in the robot folder. +* Robot packages (.jar files) is now only extracted from the root of the robots folder. +* In previous Robocode versions when starting up Robocode without a robot.database file and .robotcache directory, Robocode would extract Robot packages from the root of the robot folder and also the sub folders. When running Robocode the first time without these files, robots from the sub folders were shown (if available), but not the following times when Robocode was started up. + * This fix was done by Robert D. Maupin ("Chase-san"). + +## Version 1.2.3B (14-Jan-2007) + +### Bug Fixes +* [Bug-58][]: ``NullPointerException`` during replay. + * Titus Chen made a bug fix for a ``NullPointerException`` that caused a replay to stop. + * This occurred when "Pan" was enabled for the mixer in the Sound Options during a replay. +* When using robocode databases ("robot.database") created with version 1.2.3 and earlier version in version 1.2.3A, Robocode crashed in the startup with a ``ClassCastException``. + +## Version 1.2.3A (12-Jan-2007) + +### Bug Fix +* [Bug-57][]: ``ConcurrentModificationException``. + * Removed a ``ConcurrentModificationException`` that occurred when processing robot events. + +### Changes +* Robert D. Maupin ("Chase-san") replaced all old type Java containers like ``Vector``, ``Hashtable``, ``Enumeration`` with the newer and faster types like ``ArrayList``, ``HashMap``, and ``Set``. + * This improves the performance a bit, especially when running in "minimized" mode. + +## Version 1.2.3 (10-Jan-2007) + +### Bug Fixes +* Removed ``NullPointerException`` when trying to restart the initial intro battle. +* [Bug-54][]: Flickering when constantly changing colors. + * Titus Chen made a fix for this fix, which occurred when the max. amount of robot colors (i.e. 256) was exceeded. +* [Bug-55][]: Incorrect score after replay. + * Thanks goes to Titus Chen for reporting this issue + providing a fix for this issue. +* Minor bug fix in the Extract Results dialog, where an empty line was following each line of text. + +### Changes + +#### Added Replay Feature +* A new "Replay" button has been added to the toolbar at the buttom of the battle screen. + * The replay feature makes it possible to replay a battle. +* In a comming version of Robocode, it will be possible to load and save replays. +* [Req-24][]: Recording of battles. (partially implemented) + * Added "Enable replay recording" option to the Common Options for enabling and disabling replay recording as replay recording eats lots of memory. + * When the replay recording is disabled, the "Replay" button will not be available. + +#### Improved the security manager +* Robots are not allowed to access any internal Robocode packages anymore, except for the ``robocode.util`` package in order to let legacy robots access the ``robocode.util.Utils`` class, e.g. for calling ``normalRelativeAngle()`` etc. + +#### New hotkey +* Hotkey added for exiting Robocode quickly. + * It is now possible to exit from Robocode by pressing Alt+F4 in the main window of Robocode. Note that the main window must be active. + +## Version 1.2.2 (14-Dec-2006) + +### Bug Fixes +* [Bug-52][]: Extra hit wall events. + * Extra ``HitWallEvents`` were occuring. + * Thanks goes to Titus Chen for reporting this issue + providing a fix for this issue. +* [Bug-53][]: Teams not always ranked correctly. + * Thanks goes to Titus Chen for reporting this issue + providing a fix for this issue as well. +* In addition, the ranking scores and final battle results have been made consistent. +* The radar scan arc was not painted correctly if the radar was moving towards left. +* Sometimes ``ArrayIndexOutOfBoundsExceptions`` occurred when adding and/or removing robots in the robots folder. + +### Changes +* [Req-30][]: UI Control for adjusting the TPS quickly. + * Added TPS slider to the toolbar on the battle window so the TPS can be changed quickly. +* [Req-32][]: Bullet size. + * Bullet sizes has been improved. + * Very small bullets will always be visible, even on large 5000x5000 battle fields. +* Removed the "Allow robots to change colors repeatedly" from the View Options. + * This option did not have any affect as the current rendering engine always allows robots to change colors repeatedly. + +## Version 1.2.1A (26-Nov-2006) + +### Bug Fixes +* [Bug-51][]: Hit wall problems. + * Hitting wall with an exact angle of 0, 90, 180 or 270 degrees caused a robot to disappear from the battlefield (could be seen with the sample robots Corner and Wall). + * Thanks goes to Titus Chen for reporting this issue + providing a fix for this issue. + +## Version 1.2.1 (24-Nov-2006) + +### Bug Fixes +* [Bug-50][]: Bottom-left corner anomaly. + * The check for wall collision did not work properly in some situations due to rounding problems with float vs double precision. +* [Bug-49][]: Robot gets stuck off-screen. +* [Bug-48][]: ``isMyFault()`` returns ``false`` despite moving toward the robot. + * ``HitRobotEvent.isMyFault()`` returned ``false`` despite the fact that the robot was moving toward the robot it collided with. + * This was the case when ``distanceRemaining == 0`` even though this could occur on purpose if the move was set to ``distanceRemaining``. +* [Bug-47][]: Teleportation in version 1.2. + * Teleportation when hitting wall and ``abs(sin(heading)) > 0.00001`` or ``abs(cos(heading)) > 0.00001``. +* [Bug-46][]: Gun Method returns too soon. + * The ``turnGun(double)`` method returned before the gun rotation had returned. +* [Bug-41][]: More bad bullet collision detections. + * Bad bullet collision detection algorithm was replaced with [Paul Bourke's 2D line intersection algorithm](http://paulbourke.net/geometry/lineline2d/). + +## Version 1.2 (05-Nov-2006) + +### Bug Fixes +* [Bug-24][]: Robots hangs when running looong battles (and pausing). + * This issue which was not really fixed in 1.1.5. +* [Bug-37][]: Bad bullet collision detection. +* [Bug-42][]: "Number of rounds" box is not tall enough on Gnome/Linux. + * Some text fields in e.g. the "New Battle" were not tall enough to show their content on for e.g. Gnome/Linux. +* [Bug-43][]: Layout is bad for Gnome/Linux. + * It was hard to read the text on the buttons on the Rendering Options. The text was cut off. + +### Changes + +#### Security option +* [Req-21][]: Option for accessing external .jars + * The ``NOSECURITY`` option has been extended so it is now possible to access 3rd party jar files. + * If you want to access other jars in your robot you'll have to disable the security in Robocode by setting the ``NOSECURITY`` option to true, i.e. adding ``-DNOSECURITY=true`` in robocode.bat (under Windows) or robocode.sh (under Mac and Linux). + * You'll also have to add the jar file to your ``CLASSPATH`` or put it into the /lib/ext folder of your Java Runtime Environment (JRE), if adding it to the ``CLASSPATH`` does not work. + +#### Results can be saved in CSV File +* [Req-25][]: Save battle results to file. + * Results can now be saved in the Comma Separated Value (CSV) File Format. + * A "Save" button has been added to the battle results dialog. + +#### Battle Results / Ranking panel +* The rank and name of the robots in the battle results dialog and in ranking panel has been splitted up into two independent colums, i.e "Rank" and "Name". + * This was necessary in order to save the rank and name independently in a file. + +#### Browser +* [Req-26][]: Invoke default browser from Help. + * The default browser under Windows is now used when browsing e.g. the Online Help. + * The browser.bat file has been removed as there is no need for it anymore. + +## Version 1.1.5 (22-Oct-2006) + +### Bug Fixes +* [Bug-40][]: Half of ``BulletHitBulletEvents`` are created improperly. + * Fixed ``BulletHitBulletEvents`` where half of them referred to the wrong bullet. +* [Bug-39][]: Final results not always ranked correctly. +* [Bug-36][]: License text in installer has wierd image at the buttom. + * Updated the Common Public License to the original version. + +### Change +* The Ranking Panel total score is now updated on the fly. + +## Version 1.1.4B (19-Oct-2006) + +### Bug Fixes +* [Bug-24][]: Robots hangs when running looong battles (and pausing). +* [Bug-34][]: Getting ``null`` on ``getName()``. + * The ``getName()`` on ``ScannedRobotEvent`` returned ``null``. +* [Bug-35][]: robocode.sh contains invalid ^M character. + * Fixed the robocode.sh (Unix) file which contained a ^M (Microsoft DOS/Windows character), which caused this file to be unusable for starting Robocode. + +## Version 1.1.4A (15-Oct-2006) + +### Bug Fixes +* [Bug-33][]: Sound is cut off after a round or two. + * The sounds were cut off after first round. +* [Bug-31][]: Ranking Panel does not save its size and position. + * The Ranking Panel position and size was not saved in the window.properties file. +* [Bug-30][]: ``ad.Quest`` robot causes ``ConcurrentModificationException``. + * This exception occurred in the robot event queue. +* Periodic ``NullPointerException`` removed from battle view. + +## Version 1.1.4 (14-Oct-2006) + +### Bug Fixes +* The Battle View was not updated on the primary monitor display on a dual monitor system. +* [Bug-28][]: Enabling sound makes Robocode crash. + * When enabling sounds on-the-fly where it was originally disabled, Robocode crashed/halted with a ``NullPointerException``. +* [Bug-29][]: Runtime exception when opening new battle. + * Removed a ``NullPointerException`` occurring when opening a battle the first time with a new version of Robocode. +* [Bug-21][]: Replace function generates extra tab. + * When inserting text by 'copy and paste' or 'search and replace' into the Editor, extra tabs were sometimes added. +* [Req-19][]: Possible to install Robocode on Windows Vista. + * Robocode icons has been updated. +* Lots of internal optimizations of Robocode has been made to speed up the game. + +### Changes + +#### Ranking Panel +* Ranking Panel added to the Options menu. + * Thanks goes to Luis Crespo for this new feature. +* This panel shows the current robot rankings during battles. + +#### Single-step Debugging +* It is now possible to do single-step debugging in Robocode. + * Thanks goes to Luis Crespo for this new feature. + * The "Pause" button has been extended into "Pause/Debug", and a "Next Turn" button is available to perform one turn at a time, which is vital for single-step debugging. +* A new ``Rules`` class was added containing helper methods and constants for Robocode rules. + +#### Common Options +* [Req-23][]: Preference to allow disabling of the scorecard pop-up. + * Common Options has been added that currently contains "Show results when battle(s) ends", which is used for enabling or disabling showing the results dialog when the battle(s) ends. + +## Version 1.1.3 (20-Sep-2006) The "Java 5 and Sound" release + +### Bug Fixes +* [Bug-25][]: Wrong score for 1st place results in some battles. + * Wrong 1st place scores for robots, which got 1 point for winning and also 1 point for the death of an enemy robot, and hence got 2 points instead of just 1 point for the 1st place. +* [Req-18][]: Better notification about new Robocode versions. + * Improved the notification about new available Robocode versions. +* [Bug-19][]: Confused updater. + * Now Robocode will only give a notification about a new available version if the version number is greater than the version retrieved from the robocode.jar file. + * The check interval has been changed from 10 days into 5 days. +* [Bug-26][]: Battlefield graphics is not always updated. + +### Changes + +#### Moved to Java 5.0 +* The minimum requirement for Robocode is from now on Java 5 (1.5.0). + * You must have at least a JRE 5.0 (1.5.0) or JDK 5.0. + * Robocode has also been tested with the upcomming Java 6 (1.6.0) where it seems to run just fine. + +#### Sound Effects added +* [Req-15][]: Optional sound effects. + * Sounds have been added to Robocode along with Sound Options. + * Thanks goes to Luis Crespo for this cool new feature. + * You are able to change between available mixers (on your system). + * Panning is supported, so that explosions in e.g. the left side of the screen is louder in the left speaker. + * Volume is supported, so that e.g. a bullet with more power makes more noise. + * **Note:** Some mixers performs better, but might not support volume and/or panning. + * A new command line option, ``-nosound``, has been added in order to turn off sound support. + * This feature should prove useful on systems without sound support. + +#### New Methods for Setting Colors +* The ``setColors(bodyColor, gunColor, radarColor)`` has been reintroduced. +* The ``setColors(bodyColor, gunColor, radarColor, bulletColor, scanColor)`` has been added. +* The ``setAllColor(color)`` has been added. + +#### Misc. +* [Req-17][]: New splashscreen picture. + * The Robocode logo on the splash screen and battle view is now rendered using Java2D. + * The layout of the Developer Options was improved a bit. + +## Version 1.1.2 (20-Aug-2006) The "Robocode is now TPS centric instead of FPS centric" release + +### Bug Fixes +* [Bug-22][]: Bad buildJikes.sh in 1.1.1 + * The ``buildJikes.sh`` contained the ^M (DOS return-carrige characters), which do not belong in a Unix/Linux file. ;-) +* The radar color was sometimes painted with too much lumination (white). + +### Changes + +#### TPS centric instead of FPS centric +* [Req-12][]: Faster framerates / Turns per second. + * Robocode is no longer FPS (Frames Per Second) centric, meaning that 1 turn (time unit) = 1 frame. + * Robocode is now TPS (Turns Per Second) centric, meaning that 1 turn is not necessarily equal to 1 frame anymore. + * You specify how many turns you want to compute every second (desired TPS), and Robocode will render as many frames as possible depending on the TPS. + * If the TPS is higher than the FPS, some turns are not rendered. However, this does not mean that turns are skipped. + * The higher TPS, the lower the FPS will get. + * The better graphics hardware acceleration the higher TPS and FPS. + * Replaced the ``-fps`` (Frames Per Second) command line option with the ``-tps`` (Turns Per Second) option. + * Now there is an option to display both the TPS and FPS in the titlebar in the View Options. + +#### Rendering Options +* Added Rendering Options to the Preferences. +* It now possible to change the settings for Antialiasing, Text Antialiasing, Rendering Method, and number of rendering buffers. + +#### Explosion rendering +* [Req-11][]: Explosion on robots dependent on bullet energy. + * Explosions are no longer pre-scaled in 6 fixed sizes, but instead scaled real-time using Java2D. + * The explosion sizes are now more precise depending on bullet damage, and the memory usage for the explosions has been brought down by not using pre-scaled explosion images. + * This fixed the painting of explosions on the iMac, where explosions were painted as filled circles with version 1.1 and 1.1.1. + * Bullets are now painted as filled energy balls with a size that depends on the bullet energy. +* [Req-13][]: Bullets are sometimes too small. + * The size (circle area) is calculated so that: + * A bullet with power = 0.1 (minimum power) uses 1 pixel. + * A bullet with power = 3 (maximum power) uses 30 pixels. + * In addition, explosions when a bullet hits a robot or another bullet are also depending on the bullet energy. + +#### New Option +* Added the option "Visible Explosions" in the View Options to the Preferences. +* This option makes it possible to enable and disable the painting of explosions. + +#### Setting Robot Colors +* The ``setColors(bodyColor, gunColor, radarColor)`` method is now deprecated. + * Replaced by ``setBodyColor()``, ``setRadarColor()``, and ``setScanColor()``. +* [Req-10][]: Coloring of bullets and scan arcs. + * Added ``setBulletColor()`` for changing the bullet color, and ``setScanColor()`` for changing the scan color (used for drawing scan arcs). + +#### Improved Sample Robots +* [Req-20][]: Robot templates must be updated regarding deprecated methods. + * All sample robots has been updated. + * Deprecated methods are replaced by current methods. + * Colors has been added to each robot, except for MyFirstRobot, which should be kept as simple as possible. + +#### Added Restart Button +* [Req-14][]: Restart Button. + * Restart button has been added in order to restart a battle. + +#### New "No Display" Option +* [Req-4][]: Prevent API from loading unused features. + * No graphical components are loaded anymore when Robocode is run from the command line with the ``-nodisplay`` option. + * This feature has been added in order to run Robocode on Unix-like systems that don't have X installed on them or for running Robocode as a kind of server, e.g. for [RoboRumble][]. + +#### Added Browse Button +* [Req-16][]: Browse button in Development Options. + +#### Keyboard Mnemonics +* Changed some keyboard mnemonics in the View Options in the Preferences. + +## Version 1.1.1 (06-Jul-2006) + +### Bug Fixes +* [Bug-16][]: Too many skipped turn because of CPU speed detection. + * Robots than ran fine under v1.0.6 were skipping turns like crazy under v1.0.7. + * The CPU speed detection has been changed to accept 50 times as many clock cycles than with with v1.0.7. +* [Bug-6][]: Text-Output Errors. + * Robot text-output error has been fixed according to the solution provided by Matt (msj(at)sysmatrix(dot)net). +* [Bug-15][]: "Visible ground" option is not saved. + * The state of the "View option" was not loaded correctly, and hence always set to enabled everytime Robocode was restarted. +* [Bug-11][]: A bug at ``updateMovement()`` in ``RobotPeer.java``. + * The ``updateMovement()`` that checked for ``distanceRemaining > 1`` instead of ``distanceRemaining > 0`` when slowing down. +* [Bug-14][]: Radar color is wrong. + * The radar was not colored correctly due to a bug in the coloring filter. +* [Bug-17][]: Robot editor's window list retains old windows. + * The Robocode editor's window menu did not remove closed windows properly when muliple windows were opened in the editor. +* [Bug-12][]: Autoextract hangs on Mac 10.3.9. +* [Bug-13][]: Compiling may fail - Mac 10.3.9. + * Issues with installing and compiling under Mac 10.3.9 were fixed. +* [Bug-18][]: Blank console in battles between two bots. +* [Req-2][]: Keep window size of "New battle" window. + * The window position and sizes were not loaded properly from the windows.properties file. + * The battle window is no longer reset every time a new battle is started, and the window size and position is now saved into the windows.properties file. +* Various part of Robocode did not work properly if installed into a folder containing spaces, e.g. compiling and viewing the API documentation did not work. + +### Changes + +#### 1200x1200 Battle Field +* [Req-3][]: More precise battlefieldsize configuration. + * Added 1200x1200 battle field size as one of the standard sizes, and set the size step to 100. + * This feature was added to accommodate [RoboRumble][]. + +#### Robot Colors +* The robot colors are now painted using a true HSL color model. +* The change to use the HSL color model fixed the bug regarding none or wrong coloring. +* Also, the lumination of the robot colors has been changed. + +#### Robocode SG Support +* [Req-7][]: Graphical "debug" facilities like with RobocodeGL. + * Added a checkbox to enable Robocode SG painting in the robot console. + * The "Debug paint" button in the robot console has been renamed to "Paint". +* [Req-8][]: Debug Graphics - SG Option. + * The "Paint" button enables painting in general, and by trickering "Robocode SG", the robot (debug) painting will be rendered as Robocode SG does it. + +#### Command line / batch files +* Added the ``-Xmx512M`` option to the batch files extending the max. memory heap size to 512 MB. +* Added the ``-Dsun.io.useCanonCaches=false`` which fixes some ``SecurityException`` issues on robots that read from files, and also fixed the installing and compiling problem under Mac 10.3.9. + +## Version 1.1 (14-Jun-2006) The "Continuation" release + +### Bug Fixes +* [Bug-1][] and [Req-1][]: Multiple or hyperthreading CPUs (most P4s) hangs Robocode. +* [Bug-5][]: Robot compile error under jdk1.5. + * The Jikes compiler has been updated to version 1.22. +* [Bug-7][]: Window won't repaint itself, window flickers in battle mode. +* [Bug-9][]: Screen flickers using Sun JDK1.5.0 in Linux. +* [Bug-8][]: Opening of the Robocode API help. + * Help menu updated. +* [Bug-9][]: Screen flickers using Sun JDK1.5.0 in Linux. +* [Bug-10][]: Eclipse compile problem (Java 1.5) in ``RobocodeClassLoader``. +* Links in Help menu fixed, so you are able to browse the API etc. + * Updated with links for "RoboWiki", "Yahoo Group: Robocode", and "Robocode Repository". +* [Req-5][]: Keyboard Navigation. + * Hotkeys have been added to every button, menu, and menu option. + +### Changes +* Added feature for Debug Painting. +* By implementing the ``Robot.onPaint(Graphics2D g)`` method of your robot(s), graphics of your choice will be rendered when enabling "Debug Paint" on the console window for that robot. +* [Req-6][]: Editor Improvements. + * New "Edit" menu containing: "Undo", "Redo", "Cut", "Copy", "Paste", "Delete", "Find...", "Find next", "Replace", "Select All". + * New "Window" menu containing "Close" and "Close All" options, entries for each open window (up to 9), "More Windows" option where you can get all open windows. + * Added undo/redo stack. + * Added linenumbers. +* New rendering engine based on Java2D: + * Graphics is drawn faster as Java2D make use of hardware acceleration. + * Robot colors are now painting using the HSB color model. + * Graphics is resized when the battle window is resized. + * Added "Visible ground" option in "View Options" which will paint background tiles and explosion debrises. +* The battlefield is always centered in the battle window. + +## Robocode was release as Open Source on SourceForge + +## Development was taken over by Flemming N. Larsen + +## Version 1.0.7 (18-Feb-2005) +* Released as Open Source under Common Public License. +* New explosion graphics. +* Fixed a few bugs. + * No longer possible to teleport when hitting walls ([Bug-3][]). + * Docs fixed and regenerated ([Bug-4][]). + * Fire assistance removed from ``AdvancedRobot`` ([Bug-2][]). +* Now requires Java 1.4. +* New system for calculating CPU speed. + +## Version 1.0.6 (17-Jul-2002) +* Robots that perform file I/O will be allowed 240 skipped turns in a row before being stopped. + * Other robots will still be allowed 30 in a row. +* Fixed issue with Linux where window frames were outside screen. +* Fixed reset compiler option in editor (broken in 1.0.5). + +## Version 1.0.5 (15-Jul-2002) +* Updated dialogs for: Packager, Extractor, Team Creator, Compile Options. + * So they don't hide behind main window. +* Fixed bug where New Battle dialog would hang on some systems. + +## Version 1.0.4 (15-Jul-2002) +* Raised max ``setXX`` calls before disable to 10,000. +* Moved ``setXX`` and ``getXX`` warnings to only print when max is hit. + * Previously at 300 and 3000, respectively. +* Fixed bug in ``clearAllEvents``. +* Updated Jikes compiler to version 1.16. + +## Version 1.0.3 (28-Jun-2002) +* Added ``setFire(double)`` and ``setFireBullet(double)`` methods to ``AdvancedRobot``. +* Added ``getDataQuotaAvailable()`` call to ``AdvancedRobot``. +* Fixed bug: Robots taking action in ``Condition.test()``. +* Implemented better method for stopping misbehaving robots. + * Basically, to help fix mistakes such as: + + bad: while (getGunHeat() != 0) {} + good: while (getGunHeat() != 0) { doNothing(); } + + * Robots will be disabled after 10000 calls to ``getXX`` methods with no action. + * Robots will be disabled after 1000 calls to ``setXX`` methods with no action. + * Only ``getXX`` and ``setXX`` in the robot itself counts (``event.getXX`` does not). + +## Version 1.0.2 (21-Jun-2002) +* Increased default filesystem quota to 200000 bytes. +* Droid leaders now start with 220 energy. +* Fixed bug that allowed robots to read other robots' data directories. +* Fixed bug that allowed invalid robot version strings. +* Fixed two bugs that allowed robots to exceed filesystem quota. + +## Version 1.0.1 (23-Apr-2002) +* Team robots will always show in the robot selection dialog. +* Robots in .jar files without a .properties file will not show. +* The extension ".jar.zip" is now supported for cases where the browser renames .jar files. + +## Version 1.0 (05-Apr-2002) +* New online help integrated. + * http://robocode.alphaworks.ibm.com/help/index.html. + * includes instructions for using Eclipse to build a Robot. +* ``onWin()`` is now called the moment you are the last surviving robot. + * You can now do victory dances in ``onWin``. + * Tracker and TrackFire updated to reflect this. +* Context assist will now work inside Eclipse. +* Fixed bug: ``getTeammates()`` returning ``null`` for last teammate. +* Fixed a few other small bugs. + +## Version 0.99.4 (24-Mar-2002) +* Fixed scanning bug (missing scan events with small scanarcs). +* Added "Import downloaded robot" tool. +* Renamed "Packager" to "Package robot for upload". +* Added "Extract downloaded robot for editing" to Robot Editor +* Added "Press F5 to refresh" label to robot selection dialog. +* Added small battle demo when new version detected. + +## Version 0.99.3 (21-Mar-2002) +* Fixed velocity bug. + * Movement is now more optimized. + * No more '1 2 0 -1 0 1 2 0' velocities. +* Fixed ``maxVelocity`` bug. + * ``setMaxVelocity`` can no longer be used to instantly stop. +* Fixed first turn bug (``getTime`` returing 0 twice). +* New, more accurate CPU benchmark. (Updated Linpack benchmark). + * Should fix '1ms per turn' bug on Win9X systems. + +## Version 0.99.2 (13-Mar-2002) +* Added a development path to support external IDEs such as [Eclipse](http://eclipse.org). + * Found in Options->Preferences. + * Simply add the path to your robot project. + * As usual, robots will be loaded from disk at the start of each battle. +* Improved support for RoboLeague. +* Documented ``robocode.control`` package (http://robocode.alphaworks.ibm.com/docs/control). +* Fixed bug: ``sendMessage`` causing ``StringIndexOutOfBounds``. + +## Version 0.99.1 (11-Mar-2002) +* Fixed bug: Some messages were delayed. +* Fixed bug: Broken RoboLeague interoperability. +* Fixed bug: ``getSender()`` did not show version or duplicates. +* Fixed bug: RobotPackager not packaging teams correctly under Java2 1.3. + +## Version 0.99 (05-Mar-2002) The "TEAMS" release +* Introducing: Teams! + * See ``sampleteam.MyFirstTeam`` for an example. + * Teams may consist of 2 to 10 robots. + * To use teams, first create one or more TeamRobots, then create a Team. + * TeamRobots will not show up in the New Battle dialog by default. You can change this behavior in Options->Preferences. + * To create a team, select Robot->Team->Create Team. + * You can add regular robots to a team, but they will not be able to communicate. + * The *first* robot you add to a team becomes the "team leader". Team leaders start with 200 energy. (They are superheroes) When team leaders die, all other members of the team lose 30 energy. Protect your leader! + * Team scoring is cumulative, but similar to normal scoring: Teams receive 50 points for each surviving team member every time an enemy dies. Teams receive ``10 * numEnemies`` points for each surviving teammate upon winning. Damage bonuses are for all damage dealt by that team Firsts, Seconds, Thirds are based on last surviving team member. + * Teammates can damage each other. + * Teams can be packaged like regular robots. + * Teammates without a version will receive the team version [enclosed in square brackets]. + * Team messages are limited to 32K per message. +* Introducing: Droids. + * Droids are robots without radar or scanning ability. + * simply add "implements Droid" to a TeamRobot to create a droid. + * Droids start with 120 energy (due to weight savings on the radar). + * Droids do not show up in the New Battle dialog by default. You can change this behavior in Options->Preferences. + * The API is unchanged, but scanning will not work. + * See ``sampleteam.MyFirstDroid`` for an example. +* Added new class: TeamRobot. + * See Javadocs for details. + * Adds messaging capability to robots. +* Added new class: ``MessageEvent`` +* Added new interface: ``Droid`` +* Fixed bug: Duplicate robots sometimes showed up in robot selection dialog. +* Fixed bug: Default Window Size not working for some battles. + +## Version 0.98.3: (08-Feb-2002) The "Everything but teams and it took too long" release +* ``setColors()`` now accepts any color (previously it had to be a default color). + * Only works in the first round. + * Only the first 16 robots in a battle will get their Reqed colors. +* Robots may now extend or use classes that are not in their package. + * This allows for utility classes, when they are in the robots tree. + * If you do not wish others to extend your robot, declare your robot class final. + * If you do not with others to use classes from your package, do not declare them public. + * All referenced classes will be packaged with the robot packager. +* Robots in the robotcache directory that do not have a .properties file will not show up in the robot selection dialog (done in order to support extended robots, above). +* You may now delete files in your data directory. +* Robocode will now always run at full speed when minimized. +* New Battle Dialog "Finish" button renamed to "Start Battle". +* New Battle Dialog "Start Battle" button Reqs focus when enabled. +* Robocode FAQ linked from help menu. +* Robocode now supports RoboLeague by Christian Schnell. + * http://user.cs.tu-berlin.de/~lulli/roboleague/. +* Fixed bug: Default thread priority was low. +* Fixed bug: Robots had access to peer. +* Fixed bug: Survival seconds reported as Survival firsts. +* Fixed bug: Robots did not always receive all ``onRobotDeath`` events. +* Fixed bug: ``getTime`` returning last round's end time at start of rounds. +* Editor 'Open File' now defaults to the last opened directory (per session). +* Fixed minor editor bug when parsing for classname. +* Fixed bug: Robocode will no longer try to save the size/position of a maximized window. +* Fixed bug: Bullets hitting each other immediately with fast gun cooling rate. +* Fixed bug: Incorrect number of rounds reported when stop pressed. +* Fixed bug: Incorrect number of "seconds" and "thirds" displayed. + +## Version 0.98.2 (28-Nov-2001) The "Screaming FPS" release +* Speed up performance when minimized. +* New license includes academic use. +* Fixed bug: disappearing energy/name strings. + +## Version 0.98.1 (27-Nov-2001) The "Ok, NOW it's starting to feel real" release +* Fixed bug clearing scaled battles. +* Robot consoles changed back to white on dark gray. +* Fixed bug with case sensitivity in editor's suggested filename. +* Other minor tweaks and bug fixes. +* Updated Tracker and RamFire (no ``setInterruptible``). +* Added commentary and dates to this file. +* Added link to this file from help menu. + +## Version 0.98 (27-Nov-2001) The "It's starting to feel real" release +* Added ``setColors(Color robotColor, Color gunColor, Color radarColor)`` to Robot. + * By default, robots are the default blue. + * Call this in your run method (no more than once per round) to set your robot's colors. + * Accepts any ``System`` default colors, i.e. ``Color.red``. +* Robots are now instantiated each round. + * You no longer need to re-initialize all your variables at the beginning of ``run()``. + * ** Only static variables are persistent across rounds **. +* Graphics optimizations. + * No more rotating images at the start of each battle. + * Far more memory efficient. +* New model for CPU time. + * Robocode now uses the [Linpack benchmark](http://www.netlib.org/benchmark/linpackjava/). + * Used to determine how much time each robot is allowed for processing. +* Threading changes. + * Robocode is now threadsafe (as far as I know, anyway). + * Robot threads execute sequentially. + * No more "busy wait" enhances performance, especially on large battles. +* Minimized optimizations. + * When minimized, Robocode will not do any drawing. + * FPS can really crank up (when set in options-preferences). +* Minor graphic changes (The gun is slightly further forward). +* New class hierarchy, in order to clean up the javadocs. + * added ``_Robot`` and ``_AdvancedRobot``. + * These hold deprecated methods and system-related things. + * added ``_AdvancedRadiansRobot`` to clean up the ``AdvancedRobot`` docs. + * You should still extend either ``Robot`` or ``AdvancedRobot``. +* Battles may now consist of 1-256 robots. + * A warning confirmation will appear for > 24 robots. + * A confirmation will appear for 1 robot. +* Robots will now appear as they are loaded. +* So large battles won't appear "hung". +* Consoles persist between battles (although they are cleared). +* Console threading is more efficient. +* Console scrolling is crisper (bug fixed). +* Console now has an unlimited size, once opened. + * There is an 8K circular buffer before it is opened. +* ``setInterruptible()`` moved to ``AdvancedRobot``. + * Deprecated version in ``Robot`` does nothing. + * Note: Balancing of the ``Robot`` class still needs work. +* Skipping turns may happen more often, but is not as big a deal as it used to be. + * with the exception of your first turn. + * You will only lose events if you skip 2 in a row. + * You will not be stopped unless you skip 60 turns in a row. + * Skipped turns can be caused by loading classes from disk, writing files, etc. If this becomes a problem, I will preload all classes. +* Fixed bug with compiler when filename has a space. +* Fixed bug with getting ``BulletMissed`` and ``BulletHit`` events for same bullet. +* Fixed bug with editor locking up reading some files. +* Another round of major code organization. +* Again, probably more minor items that I already forgot about. :) +* (Later additions... such as:) + * Invalid insert bug in editor + * Copy/Paste from console. + +## Version 0.97.4 (18-Nov-2001) The "finally, a single installer!" release +* Completely reworked install process. +* There is no longer a setup.exe installer. +* Jikes is now packaged with Robocode as the default compiler. + * you may use javac if you prefer, and you have it. +* API docs now link to the Java API. +* Fixed bug: Editor did not close files after saving. +* Fixed bug: Unable to deselect "display robot names". +* Fixed bug: Shared static vars between instances of the same robot. +* Fixed a few graphics glitches. +* Minor doc updates. + +## Version 0.97.3 (05-Nov-2001) The "hourly release" release :) +* Fixed ``NullPointerException`` when loading robots with no package. +* Added ``robocode.robot.filesystem.quota`` property to robocode.properties. + * This is a temporary solution, which sets the default filesystem quota for robots. + * Example: ``robocode.robot.filesystem.quota=200000`` for 200k. +* Fixed bug in editor that caused it to suggest an unreasonable filename. + +## Version 0.97.2 (04-Nov-2001) +* Fixed bug that caused some robots to be stopped by the game. +* Battles/Rounds start faster (back to 0.96.2 speed). +* More lenient on CPU use. + * You have roughly 4 whole seconds before your first move. + * You have roughly ``50 + (1000 / fps)`` milliseconds to process each frame. + * This is more than twice what the entire game itself gets. :) + * Failure to take action in that amount of time results in a SkippedTurnEvent. + * You will be removed from the round if you skip 30 turns in a round. + * Un-deprecated ``onSkippedTurn`` and ``SkippedTurnEvent``. + * No reasonable robot should ever receive a ``SkippedTurnEvent``... but now it's there just in case. + +## Version 0.97.1 (03-Nov-2001) +* Abstract classes now work properly in the selection dialog and robot database. +* Fixed a few Javadoc bugs. +* Fixed pause/resume bug. +* Javadocs have deprecated calls again. + +## Version 0.97 (02-Nov-2001) The "painful but worth it" release +* I probably missed a few things in this list. :) +* Introducing the Robot Packager. + * Select your robot, type in a few details, and let it figure out the rest. + * Saves details in a .properties file (see details below). + * Builds a .jar for you. + * Save this .jar in your robots directory (not a subdirectory, for now). + * You may distribute this jar as a standalone robot. +* .properties files. + * Not required unless you are packaging your robot. + * Built automatically by the packager. + * Includes: + * Robot version + * Short description + * Optional author name + * Optional webpage + * Robocode version + * Flag for source included +* .jar files, and the robotcache. + * Simply put a robot .jar file in your robots directory. + * It will be extracted to the "robotcache". + * Jar filename is the unique key for the robotcache. + * Do not edit files in the robotcache, they may be overwritten. Copy them to your robots directory if you like. This will be a feature in a future version of Robocode. +* Robot Database. + * Built and maintained for you. + * Allows Robocode to remember which .class files are robots, and which not. + * Press F5 in the robot selection dialog to refresh the database. +* Robot Selection dialog. + * Divided up into packages. + * Shows robot details (from .properties) if they exist. +* .html files. + * Create a .html file if you like... see ``sample.SittingDuck``. + * Linked from robot selection dialog. +* Major scoring changes. + * 50 points every time an enemy dies while you are alive. + * (10 * numOthers) points if you are the sole survivor + * 1 point for each point of damage you do with bullets. + * 2 points for each point of damage you do by ramming (see Ramming changes, below). + * ``bonus .2 * damage`` done to a specific enemy, if you kill that robot, or + * ``bonus .3 * damage`` done to a specific enemy, if you kill by ramming. +* Ramming changes. + * Damage increased (from .4 to .6). + * Only generates score if you are moving toward the enemy. + * If you are ramming, and run out of energy, you will now be disabled instead of killed. +* "Life" replaced with "Energy". + * A more sensible name. + * All ``getLife()`` calls deprecated and replaced with ``getEnergy()``. +* Added ``getEnergy()`` to ``HitRobotEvent`` (I can't believe it wasn't there before!). +* Only ``Robots`` and ``AdvancedRobots`` will show in the New Battle dialog. + * Fixes known bug listed below at the end of 0.96 changes. +* Custom events are now be cleared at the start of each round. + * However, since many robots rely on them still existing, Robocode will currently re-add any custom events that were created at the beginning of the first round, for all remaining rounds. This is a temporary solution for backwards compatibility, and will cause a warning message in your console. +* You may now print to ``System.out``. + * Will automatically redirect output to your console. +* Robot Editor now supports creating normal Java files. +* Added line number display to Robot Editor +* ``MoveCompleteCondition`` bug fixed. +* ``getTurnRemaining()``, ``getGunTurnRemaining()``, ``getRadarTurnRemaining()`` now return degrees. +* ``getTurnRemainingRadians()``, ``getGunTurnRemainingRadians()``, ``getRadarTurnRemainingRadians()`` added. +* Added ``setAdjustRadarForRobotTurn(boolean)``. + * By default, set to the value of ``setAdjustRadarForGunTurn`` for backwards compatibility. +* Windows now remember their last position. + * This is based on the preferred size of the window, so that different battlefield sizes may have different window position and sizes. + * This is stored in the file "window.properties" which you can safely delete to reset. +* Added "Default Window Size" to Options menu. + * Resizes the window to optimal (even better than before). +* Command-line parameters to run a battle. + * ``robocode -battle battles\sample.battle -results out.txt -fps 250 -minimize``. + * Results will go to ``System.out`` if you do not specify a results file. + * All other Robocode output goes to ``System.err``. +* "Activity" is now defined as loss of 10 energy in the battle. + * Inactivity Time is now the number of frames in which 10 energy must be lost. + * This does not include loss due to inactivity itself, or hitting walls. + * Prevents robots stopping the inactivity timer by calling ``fire(.1)`` every 15 seconds. +* Compiler uses ``-g`` option for debugging. + * This *may* help those users trying to use advanced debuggers. +* Much improved "waiting for robots to start". +* More lenient on "robot has not performed any actions". +* Various javadoc fixes. +* Minor updates to template files. + +## Version 0.96.2 (09-Oct-2001) +* Fixed bug in movement that allowed robots to exceed ``maxVelocity``. + +## Version 0.96.1 +* Added automatic version checking. +* Added ``getVelocity()`` to ``Robot``. +* Fixed minor bug in editor (caused the "do" in "doNothing" to highlight). +* ``WinException`` and ``DeathException`` now extend ``Error`` instead of ``RuntimeException``. + * So you won't catch them by mistake with: ``catch (Exception e)``. + * You still don't want to catch them, or you'll get no score. +* Fixed minor API doc bugs. +* Added a warning when you are calling the ``setXX`` methods too many times (300). + * has no effect on whether the game stops you or not, it simply helps to explain why. before taking an action. +* Replaced BrowserControl with BrowserLauncher, from http://www.stanford.edu/~ejalbert/software/BrowserLauncher. + * Should work on more systems. +* Synchronized ``tick()``. + * Two threads cannot take action at the same time. + * This entire area needs work. +* FPS no longer displayed when Swing doublebuffering is on. +* Added ``getHeadingRadians()`` to ``Bullet``. +* Fixed ``getHeading()`` in ``Bullet`` to return degrees. + +## Version 0.96 (05-Oct-2001) The "Robocode is now my life" release +* Renamed "Battles" to "Rounds" -- a single battle consists of multiple rounds. +* Commented and updated all sample robots. +* All sample robots are now in package "sample". +* If the old samples exist, Robocode will ask you if it may delete them, when you first run it. +* Only Target, Crazy, Spinbot are still AdvancedRobots. + * Target must be for the custom event. + * Crazy and Spinbot call setTurn methods. +* SittingDuck is now an AdvancedRobot. + * SittingDuck writes to the filesystem. +* Help system now uses system browser. Hopefully. Let me know of any issues. +* API Help menu item copied to RobocodeEditor, and uses the local copy. +* Robots may now use,extend,or inherit external classes, as long as they are in the same root package. + * You must be in a package to use this feature. +* Added call: ``getDataDirectory()`` to ``AdvancedRobot`` -- returns ``java.io.File`` representing your data directory. +* Added call: ``getDataFile(String filename)`` to ``AdvancedRobot`` -- returns ``java.io.File`` representing a file in your data directory. +* AdvancedRobots may now read files that are in the same directory (or subdirectory) as their root package. + * It is recommended that you only read from your data directory. + * You may not read another robot's data directory. + * If you extend another robot, and it calls ``getDataDirectory``, it will get YOUR data directory. + * If you extend another robot, and manually try to read it's data directory, it will fail. +* Added classes: ``RobocodeFileOutputStream`` and ``RobocodeFileWriter``. +* AdvancedRobots may now write files to their data directory. + * You must use ``RobocodeFileOutputStream`` or ``RobocodeFileWriter``. + * Any other output stream will fail. + * You may wrapper them with other output streams. + * Example: ``PrintStream out1 = new PrintStream(new RobocodeFileOutputStream(getDataFile("my.dat")));`` + * There is a quota of 100K. +* Fixed scoring bug (as exhibited by ``rk.Rotator``). +* Fixed threads stuck in wait condition when new battle selected. +* Fixed threads stuck in ``onWin`` or ``onDeath`` events. +* Fixed threads not taking action. +* Fixed leftover threads. +* Fixed a half dozen other thread issues. +* Limited \# of worker threads a robot may have to 5. +* Limited ``print``/``println`` calls to ``out``, to 100 per turn. +* Robots now run in their own ``ThreadGroup``. (You can no longer can see other robot's threads). +* Robots now have their own ``Classloader``. (static variable ``messages`` will no longer work). +* Fixed ``NullPointerException`` in ``RobocodeOutputStream``. +* ``WinEvents`` or ``DeathEvents`` will now be the only thing in the event queue. +* Reworked event handler system, should be more robust. +* Tweaked event priorities. New default priorities are: + * ``BulletHitBulletEvent``: 50. +* Valid priorities are 0 to 99 (100 is reserved). +* Added new method ``setInterruptible(boolean)`` to ``Robot``. + * Can only be used while handling an event. + * Always resets to false when the event ends. + * Causes event handler to restart from the top, if the same event (or another event of the same priority) is generated while in the event handler following this call. + * This will only happen if you take an action inside an event handler, that causes the same event handler to be called. + * This makes it possible for Robots to turn and move like AdvancedRobots... + * This has no effect on events of higher priority. +* Calling ``scan()`` inside of ``onScannedRobot()`` can now restart ``onScannedRobot``. + * internally calls ``setInterruptible(true)`` for itself. + * See ``sample.Corners`` for example. +* Robots of class ``Robot`` no longer take damage from hitting a wall. +* Robots of class ``AdvancedRobot`` take more damage from hitting a wall. +* Added ``isMyFault()`` to ``HitRobotEvent``. + * Returns ``true`` if you caused the event by moving toward the other robot. +* Revamped robot to robot collisions. + * Your movement will be marked complete if you are moving toward the other robot. + * You will not be stopped if you are moving away from the other robot. + * Collisions now cause more damage, but are easier to escape from. + * This means robots without ``onHitRobot`` handlers still have a chance... + * An event is generated every time one robot hits another. + * If you are moving toward the other robot, you will get ``onHitRobotEvent`` with ``isMyFault() = true``. + * If another robot is moving toward you, you will get an ``onHitRobotEvent`` with ``isMyFault() = false``. + * If you are moving toward each other, you will get two events, with the ``isMyFault() = true``, first. +* Damage from robot to robot collisions is now a constant 0.4. +* Added ``getBearing()`` to ``onHitByBullet``. +* Added a ``Bullet`` object. + * encapsulates owner, victim, power, velocity, X, and Y. +* Bullet hitting bullet generates ``BulletHitBulletEvent`` - methods include ``getBullet()`` and ``getHitBullet()``. + * added ``getBullet()`` to ``HitByBulletEvent``, ``BulletHitEvent``, ``BulletMissedEvent``. +* Added ``fireBullet()``, which is exactly like ``fire()``, but returns a ``Bullet`` object. + * I could not simply add a bullet return to fire, because it broke *all* existing robot .class files. +* You can now select from the results dialog. +* Fixed path for open/save battles on non-Windows systems. +* Fixed slashscreen for some systems. +* Fixed minor API doc bugs. +* Updated many API docs. +* Renamed and reorganized many internal classes. +* Fixed bug with allowed package names (now allows digits). +* Windows installer now defaults to c:\. +* Added ``getGunHeat()`` to ``Robot``. + * When gunHeat is 0, you can fire. + * ``gunHeat`` goes up by ``(1 + firePower / 5)`` when you fire. + * This is unchanged from the v0.95. +* Added ``getGunCoolingRate()`` to ``Robot``. +* Deprecated ``getGunCharge()``. + * Use ``getGunHeat()`` instead. +* Deprecated ``endTurn()``. + * It will still work for now, but you should replace calls to to it with ``execute()``. +* Removed ``onSkippedTurn``. + * Your robot will simply be stopped instead. + * The results dialog will report "not deterministic". + * Not deterministic means that a battle started with the exact same conditions and starting positions, may not end up with the same results. (Ok, so far, you can't test that...) :) + * Added ``getWaitCount()`` and ``getMaxWaitCount()`` to ``AdvancedRobot``. +* Deprecated ``SkippedTurnEvent``. + * Well, it's no longer used. +* Deprecated all ``getRobotXX`` methods. + * Replaced with ``getXX`` methods. +* Deprecated all ``getXXDegrees`` and ``setXXDegrees`` methods. + * Just use the ``getXX`` and ``setXX`` methods. +* Compiler will always show output, and uses the ``-deprecation`` flag. + * so you can see that you're using a deprecated call. + * I would like to remove all deprecated calls in the next version. +* Known bug: New battle dialog not smart enough to differentiate between Robots classes and other classes. + * You will be able to put other classes into a battle. + * They will sit there and do nothing. + +## Version 0.95 (09-Sep-2001) "The /. release" +* Completely rewrote all windows and dialogs to use LayoutManagers. +* Linux support vastly improved (although fps still not great). +* Improved framerate calculation (should be smoother on most systems). +* Robot exceptions now all go to robot's console. +* Fixed bug in initialization - radar turn. +* Hitting a wall no longer resets inactivity counter. +* Better pause functionality (fixed bugs). +* Known bug: Help system still not using external browser. +* Smarter dialog locations. + +## Version 0.94 (09-Aug-2001) +* Fixed a few bugs so Linux version would run. +* Known bug: Linux version does not run well. + +## Version 0.93 (23-Apr-2001) +* Completely redone graphics for tanks, guns, radar. +* Firepower adjusted. Higher-power bullets now move slightly slower and fire slightly slower. +* Gun must 'charge up' before firing. This avoids the "lucky shot" syndrome at the beginning of a battle. +* Added ``execute()`` method for ``AdvancedRobots``. Better name for 'endTurn'. +* Optimized drawing of explosion graphics. +* Added buttons for selecting battle size. +* Bullets can now hit each other (not perfect yet). +* Updated security manager to work with jdk1.4. +* Revised bounding box for new graphics. The graphics should no longer have a 5-pixel blank area. +* Optimized scanning code. +* Added 'color mask' to determine which parts of image should be recolored. +* Replaced splashscreen and icons. +* Java-based help, API, check new version. +* Robot menu (disabled). +* Changed ``fireDelay`` mechanism to be ``gunCharge``. Still in progress. +* Renamed to Robocode. +* Added Buttons for framerate. +* Added Buttons for battle size. + +## Version 0.92 (Mar-2001) +* Added ``getTime()`` method to ``Robots``. +* Added ``getFireDelay()`` method to ``Robots``. +* Added explosions. + +## Version 0.91 (Mar-2001) +* Fixed bug in ``waitFor()`` so that automatic scanning will not repeatedly generate events when the condition is ``true``. +* Fixed bugs in Tracker sample robot. +* Fixed display issues with view scan arc option. + +## Version 0.9 (Mar-2001) +* Completely reworked ``scan()`` to use a sweep as the radar moves. If the radar is not moving, the scan will be a straight line. +* Added fire assistance to regular ``Robot`` classes (not ``AdvancedRobots``). + * If you fire at a robot you see during ``scan()``, and gun/radar are together, and you ``fire()`` before doing anything else, you will fire at its center. + +## Version 0.8 (Feb-2001) +* Initial release. + * Robocode brought to IBM. + +## Version 0.1 (Sep-2000) +* Development started as late-night project. + + + + +[RoboRumble]: http://robowiki.net/wiki/RoboRumble (RoboWiki - RoboRumble) +[Markdown]: http://daringfireball.net/projects/markdown/syntax (Markdown syntax) + +[IRobotSnapshot.getContestantIndex()]: http://robocode.sourceforge.net/docs/robocode/robocode/control/snapshot/IRobotSnapshot.html#getContestantIndex() (robocode.control.snapshot.IRobotSnapshot.getContestantIndex()) +[IRobotSnapshot.getRobotIndex()]: http://robocode.sourceforge.net/docs/robocode/robocode/control/snapshot/IRobotSnapshot.html#getRobotIndex() (robocode.control.snapshot.IRobotSnapshot.getRobotIndex()) +[IRobotSnapshot.getTeamIndex()]: http://robocode.sourceforge.net/docs/robocode/robocode/control/snapshot/IRobotSnapshot.html#getTeamIndex() (robocode.control.snapshot.IRobotSnapshot.getTeamIndex()) + +[Patch-1]: http://sourceforge.net/p/robocode/patches/1/ (#1 Improved priority battle handling) + +[Bug-1]: http://sourceforge.net/p/robocode/bugs/1/ (Multiple or hyperthreading CPUs (most P4s) hangs Robocode) +[Bug-2]: http://sourceforge.net/p/robocode/bugs/2/ (Remove firing assistance for AdvancedRobo) +[Bug-3]: http://sourceforge.net/p/robocode/bugs/3/ (Teleportation of robot can happen (rare)) +[Bug-4]: http://sourceforge.net/p/robocode/bugs/4/ (#4 API Doc incorrect) +[Bug-5]: http://sourceforge.net/p/robocode/bugs/5/ (Robot compile error under jdk1.5) +[Bug-6]: http://sourceforge.net/p/robocode/bugs/6/ (Text-Output Errors) +[Bug-7]: http://sourceforge.net/p/robocode/bugs/7/ (Window won't repaint itself, window flickers in battle mode) +[Bug-8]: http://sourceforge.net/p/robocode/bugs/8/ (Opening of the Robocode API help) +[Bug-9]: http://sourceforge.net/p/robocode/bugs/9/ (Screen flickers using Sun JDK1.5.0 in Linux) +[Bug-10]: http://sourceforge.net/p/robocode/bugs/10/ (Eclipse compile problem (Java 1.5) in RobocodeClassLoader) +[Bug-11]: http://sourceforge.net/p/robocode/bugs/11/ (A bug at updateMovement() in RobotPeer.jav) +[Bug-12]: http://sourceforge.net/p/robocode/bugs/12/ (Autoextract hangs on Mac 10.3.9) +[Bug-13]: http://sourceforge.net/p/robocode/bugs/13/ (Compiling may fail - Mac 10.3.9) +[Bug-14]: http://sourceforge.net/p/robocode/bugs/14/ (Radar color is wrong) +[Bug-15]: http://sourceforge.net/p/robocode/bugs/15/ ("Visible ground" option is not saved) +[Bug-16]: http://sourceforge.net/p/robocode/bugs/16/ (Too many skipped turn because of CPU speed detection) +[Bug-17]: http://sourceforge.net/p/robocode/bugs/17/ (Robot editor's window list retains old windows) +[Bug-18]: http://sourceforge.net/p/robocode/bugs/18/ (Blank console in battles between two bots) +[Bug-19]: http://sourceforge.net/p/robocode/bugs/19/ (Confused updater) +[Bug-21]: http://sourceforge.net/p/robocode/bugs/21/ (Replace function generates extra tab) +[Bug-22]: http://sourceforge.net/p/robocode/bugs/22/ (Bad buildJikes.sh in 1.1.) +[Bug-24]: http://sourceforge.net/p/robocode/bugs/24/ (Robots hangs when running looong battles (and pausing)) +[Bug-25]: http://sourceforge.net/p/robocode/bugs/25/ (Wrong score for 1st place results in some battles) +[Bug-26]: http://sourceforge.net/p/robocode/bugs/26/ (Battlefield graphics is not always updated) +[Bug-28]: http://sourceforge.net/p/robocode/bugs/28/ (Enabling sound makes Robocode crash) +[Bug-29]: http://sourceforge.net/p/robocode/bugs/29/ (Runtime exception when opening new battle) +[Bug-30]: http://sourceforge.net/p/robocode/bugs/30/ (ad.Quest robot causes ConcurrentModificationException) +[Bug-31]: http://sourceforge.net/p/robocode/bugs/31/ (Ranking Panel does not save its size and position) +[Bug-33]: http://sourceforge.net/p/robocode/bugs/33/ (Sound is cut off after a round or two) +[Bug-34]: http://sourceforge.net/p/robocode/bugs/34/ (Getting null on getName()) +[Bug-35]: http://sourceforge.net/p/robocode/bugs/35/ (robocode.sh contains invalid ^M character) +[Bug-36]: http://sourceforge.net/p/robocode/bugs/36/ (License text in installer has wierd image at the buttom) +[Bug-37]: http://sourceforge.net/p/robocode/bugs/37/ (Bad bullet collision detection) +[Bug-39]: http://sourceforge.net/p/robocode/bugs/39/ (Final results not always ranked correctly) +[Bug-40]: http://sourceforge.net/p/robocode/bugs/40/ (Half of BulletHitBulletEvents are created improperly) +[Bug-41]: http://sourceforge.net/p/robocode/bugs/41/ (More bad bullet collision detections) +[Bug-42]: http://sourceforge.net/p/robocode/bugs/42/ ("Number of rounds" box is not tall enough on Gnome/Linux) +[Bug-43]: http://sourceforge.net/p/robocode/bugs/43/ (Layout is bad for Gnome/Linux) +[Bug-46]: http://sourceforge.net/p/robocode/bugs/46/ (Gun Method returns too soon) +[Bug-47]: http://sourceforge.net/p/robocode/bugs/47/ (Teleportation in version 1.2) +[Bug-48]: http://sourceforge.net/p/robocode/bugs/48/ (isMyFault() returns false despite moving toward the robot) +[Bug-49]: http://sourceforge.net/p/robocode/bugs/49/ (Robot gets stuck off-screen) +[Bug-50]: http://sourceforge.net/p/robocode/bugs/50/ (Bottom-left corner anomaly) +[Bug-51]: http://sourceforge.net/p/robocode/bugs/51/ (Hit wall problems) +[Bug-52]: http://sourceforge.net/p/robocode/bugs/52/ (Extra hit wall events) +[Bug-53]: http://sourceforge.net/p/robocode/bugs/53/ (Teams not always ranked correctly) +[Bug-54]: http://sourceforge.net/p/robocode/bugs/54/ (Flickering when constantly changing colors) +[Bug-55]: http://sourceforge.net/p/robocode/bugs/55/ (Incorrect score after replay) +[Bug-57]: http://sourceforge.net/p/robocode/bugs/57/ (ConcurrentModificationException) +[Bug-58]: http://sourceforge.net/p/robocode/bugs/58/ (NullPointerException during replay) +[Bug-59]: http://sourceforge.net/p/robocode/bugs/59/ (Issue when setting the priority of a BulletHitBulletEvent) +[Bug-60]: http://sourceforge.net/p/robocode/bugs/60/ (ConcurrentModificationException when extracting robots) +[Bug-61]: http://sourceforge.net/p/robocode/bugs/61/ (Hang when checking for new version with no Internet access) +[Bug-62]: http://sourceforge.net/p/robocode/bugs/62/ (Memory "Leak") +[Bug-63]: http://sourceforge.net/p/robocode/bugs/63/ (BulletHitBullet only destroys one bullet) +[Bug-64]: http://sourceforge.net/p/robocode/bugs/64/ (Exception when referencing length of an array of String) +[Bug-65]: http://sourceforge.net/p/robocode/bugs/65/ (Cannot run robocode after installation) +[Bug-66]: http://sourceforge.net/p/robocode/bugs/66/ (Crash: starting a new round while et.Predator 1.8 is playing) +[Bug-67]: http://sourceforge.net/p/robocode/bugs/67/ (Some issues with MessageEvent + priority) +[Bug-68]: http://sourceforge.net/p/robocode/bugs/68/ (Preferences not saved) +[Bug-69]: http://sourceforge.net/p/robocode/bugs/69/ (Robot causes Null Pointer Exception) +[Bug-70]: http://sourceforge.net/p/robocode/bugs/70/ (Version 1.2.6A incompatible with Roboleague) +[Bug-71]: http://sourceforge.net/p/robocode/bugs/71/ (RobocodeEngine becomes slower the more battles that are run) +[Bug-72]: http://sourceforge.net/p/robocode/bugs/72/ (The game won't play sounds on 2nd launch) +[Bug-73]: http://sourceforge.net/p/robocode/bugs/73/ (Sound don't work) +[Bug-74]: http://sourceforge.net/p/robocode/bugs/74/ (Java FilePermission error during startup) +[Bug-75]: http://sourceforge.net/p/robocode/bugs/75/ (getTeammates() problem) +[Bug-76]: http://sourceforge.net/p/robocode/bugs/76/ (Unique error) +[Bug-78]: http://sourceforge.net/p/robocode/bugs/78/ (Robots are disabled with no timer or countdown) +[Bug-79]: http://sourceforge.net/p/robocode/bugs/79/ (Output displayed in bursts) +[Bug-80]: http://sourceforge.net/p/robocode/bugs/80/ (Results file is empty with the command line) +[Bug-81]: http://sourceforge.net/p/robocode/bugs/80/ (Replay recording does not record paintings) +[Bug-82]: http://sourceforge.net/p/robocode/bugs/82/ (Undo comment does not change font color of code) +[Bug-83]: http://sourceforge.net/p/robocode/bugs/83/ (Ranking Panel Does not update number of competitors) +[Bug-84]: http://sourceforge.net/p/robocode/bugs/84/ (Preferences page problem on machine w/out sound card) +[Bug-85]: http://sourceforge.net/p/robocode/bugs/85/ (No window position in-bounding) +[Bug-86]: http://sourceforge.net/p/robocode/bugs/86/ (Using UI removes focus from interactive bots) +[Bug-87]: http://sourceforge.net/p/robocode/bugs/87/ (Round indicator incorrect) +[Bug-88]: http://sourceforge.net/p/robocode/bugs/88/ (Scorch layer) +[Bug-90]: http://sourceforge.net/p/robocode/bugs/90/ (Limit per round, not turn) +[Bug-91]: http://sourceforge.net/p/robocode/bugs/91/ (ConcurrentModificationException) +[Bug-92]: http://sourceforge.net/p/robocode/bugs/92/ (RoboRumble tries to connect with GUI) +[Bug-93]: http://sourceforge.net/p/robocode/bugs/93/ (onPaint(Graphics2D g) called prematurely) +[Bug-94]: http://sourceforge.net/p/robocode/bugs/94/ (Inconsistent Behavoir of RobocodeEngine.setVisible()) +[Bug-95]: http://sourceforge.net/p/robocode/bugs/95/ (OutOfMemory: Robots are Being Left on the Stack) +[Bug-96]: http://sourceforge.net/p/robocode/bugs/96/ (Initializing Label even when no display) +[Bug-97]: http://sourceforge.net/p/robocode/bugs/97/ (Exception when packaging robots) +[Bug-98]: http://sourceforge.net/p/robocode/bugs/98/ (When minimized doesn't show actual tps) +[Bug-99]: http://sourceforge.net/p/robocode/bugs/99/ (Clicking on a bottom area results in ClassCastException) +[Bug-100]: http://sourceforge.net/p/robocode/bugs/100/ (Double-clicking "restart") +[Bug-101]: http://sourceforge.net/p/robocode/bugs/101/ ("Keyboard lockup" with interactive robots) +[Bug-102]: http://sourceforge.net/p/robocode/bugs/102/ (Bots can hold memory after being destroyed) +[Bug-103]: http://sourceforge.net/p/robocode/bugs/103/ (ConcurrentModificationException) +[Bug-104]: http://sourceforge.net/p/robocode/bugs/104/ (Reproducable scoring bug) +[Bug-105]: http://sourceforge.net/p/robocode/bugs/105/ (testingCondition flag not reset) +[Bug-106]: http://sourceforge.net/p/robocode/bugs/106/ (Incorrect repaint of paused battlefield) +[Bug-107]: http://sourceforge.net/p/robocode/bugs/107/ (Bullet hit locations reported inaccurately) +[Bug-108]: http://sourceforge.net/p/robocode/bugs/108/ (It is possible to restart a battle without any robots) +[Bug-110]: http://sourceforge.net/p/robocode/bugs/110/ (Partial match recording replay) +[Bug-111]: http://sourceforge.net/p/robocode/bugs/111/ (Wasted time at end of each round) +[Bug-112]: http://sourceforge.net/p/robocode/bugs/112/ (Forcing stop: no score will be generated) +[Bug-113]: http://sourceforge.net/p/robocode/bugs/113/ (-battle option runs at full speed) +[Bug-114]: http://sourceforge.net/p/robocode/bugs/114/ (Wait Interrupted Message) +[Bug-115]: http://sourceforge.net/p/robocode/bugs/115/ (AWTException with RoboRumble on OS X) +[Bug-116]: http://sourceforge.net/p/robocode/bugs/116/ (Exclude filter removes bots from the RoboRumble) +[Bug-117]: http://sourceforge.net/p/robocode/bugs/117/ (Sound card is being dodgey/not detected by OS causes error) +[Bug-118]: http://sourceforge.net/p/robocode/bugs/118/ (Battles fail when executing with Eclipse debugger) +[Bug-120]: http://sourceforge.net/p/robocode/bugs/120/ (The renderering is slower on Vista than XP) +[Bug-122]: http://sourceforge.net/p/robocode/bugs/122/ (Not all shortcut keys work on MacOS) +[Bug-123]: http://sourceforge.net/p/robocode/bugs/123/ (Compiler fails to build due to CR/LF in scripts) +[Bug-125]: http://sourceforge.net/p/robocode/bugs/125/ (TimeoutExceptions occur when debugging in Eclipse) +[Bug-130]: http://sourceforge.net/p/robocode/bugs/130/ (Various usability issues) +[Bug-131]: http://sourceforge.net/p/robocode/bugs/131/ (Sometimes the compiler window hangs) +[Bug-134]: http://sourceforge.net/p/robocode/bugs/134/ (Robot problem after Options->Clean robot cache) +[Bug-135]: http://sourceforge.net/p/robocode/bugs/135/ (-battle broken) +[Bug-137]: http://sourceforge.net/p/robocode/bugs/137/ (Roborumble "ITERATE" broken) +[Bug-139]: http://sourceforge.net/p/robocode/bugs/139/ (Bug in RobotPeer.updateMovement?) +[Bug-141]: http://sourceforge.net/p/robocode/bugs/141/ (The -DROBOTPATH= option does not work) +[Bug-142]: http://sourceforge.net/p/robocode/bugs/142/ (Broken .sh files) +[Bug-143]: http://sourceforge.net/p/robocode/bugs/143/ (Blank console window when compiling) +[Bug-144]: http://sourceforge.net/p/robocode/bugs/144/ (drawArc does not work as expected) +[Bug-146]: http://sourceforge.net/p/robocode/bugs/146/ (Spammy output when running roborumble) +[Bug-147]: http://sourceforge.net/p/robocode/bugs/147/ (gunHeat is negative) +[Bug-148]: http://sourceforge.net/p/robocode/bugs/148/ (Wrong bullet power) +[Bug-149]: http://sourceforge.net/p/robocode/bugs/149/ (Replay exception) +[Bug-151]: http://sourceforge.net/p/robocode/bugs/151/ (Exception when changing between Robot to AdvancedRobot) +[Bug-153]: http://sourceforge.net/p/robocode/bugs/153/ (Junior Robot turnAheadRight bug) +[Bug-154]: http://sourceforge.net/p/robocode/bugs/154/ (Robot name missing when replaying XML record) +[Bug-156]: http://sourceforge.net/p/robocode/bugs/156/ (Spammy output on robot console windows) +[Bug-158]: http://sourceforge.net/p/robocode/bugs/158/ (Ubuntu throws NullPointerException in main) +[Bug-159]: http://sourceforge.net/p/robocode/bugs/159/ (Installation fail on windows if directory contain space) +[Bug-160]: http://sourceforge.net/p/robocode/bugs/160/ (Battle Results screen displaying old results) +[Bug-161]: http://sourceforge.net/p/robocode/bugs/161/ (Robot disabled by any other than losing energy can recover) +[Bug-162]: http://sourceforge.net/p/robocode/bugs/162/ (Team battle) +[Bug-163]: http://sourceforge.net/p/robocode/bugs/163/ (Spaces or native names in name of robocode directory) +[Bug-164]: http://sourceforge.net/p/robocode/bugs/164/ (Compiler Classpath Suggestion) +[Bug-165]: http://sourceforge.net/p/robocode/bugs/165/ (NullPointerException when using -battle option from cmd-line) +[Bug-166]: http://sourceforge.net/p/robocode/bugs/166/ (Bots referencing robocode.robocodeGL broken) +[Bug-168]: http://sourceforge.net/p/robocode/bugs/168/ (Bots inconviently stop working if they go over time limit) +[Bug-169]: http://sourceforge.net/p/robocode/bugs/169/ (pe.SandboxDT_3.02 stopped working in 1.6.2 and later version) +[Bug-170]: http://sourceforge.net/p/robocode/bugs/170/ (Robot Colors don't stick between rounds) +[Bug-171]: http://sourceforge.net/p/robocode/bugs/171/ (A battleview size exceed 800x600 filled with black) +[Bug-172]: http://sourceforge.net/p/robocode/bugs/172/ (Robot console fails to display some deaths/wins) +[Bug-173]: http://sourceforge.net/p/robocode/bugs/173/ (Robot packager can be activated once per running) +[Bug-174]: http://sourceforge.net/p/robocode/bugs/174/ (Robot console is sometimes empty) +[Bug-175]: http://sourceforge.net/p/robocode/bugs/175/ (Development robots cause problems with data files) +[Bug-177]: http://sourceforge.net/p/robocode/bugs/177/ (Open battle menu dialog is not loading robots) +[Bug-178]: http://sourceforge.net/p/robocode/bugs/178/ (Typing to find bot no longer works) +[Bug-179]: http://sourceforge.net/p/robocode/bugs/179/ (Event.setTime() method should not be hidden) +[Bug-181]: http://sourceforge.net/p/robocode/bugs/181/ (API: Typo in Documentation onBulletMissed(BulletMissedEvent)) +[Bug-176]: http://sourceforge.net/p/robocode/bugs/176/ (Editor UNDO does delete the line when no undo left) +[Bug-180]: http://sourceforge.net/p/robocode/bugs/180/ (Editor: Find (set cursor position)) +[Bug-182]: http://sourceforge.net/p/robocode/bugs/182/ (roborumble.sh and teamrumble.sh are broken) +[Bug-183]: http://sourceforge.net/p/robocode/bugs/183/ (NullPointerException in BattlesRunner.runBattlesImpl) +[Bug-184]: http://sourceforge.net/p/robocode/bugs/184/ (Custom event priority broken) +[Bug-185]: http://sourceforge.net/p/robocode/bugs/185/ (Webpage button lay over robot description) +[Bug-186]: http://sourceforge.net/p/robocode/bugs/186/ (Rounds number do not saved between run) +[Bug-187]: http://sourceforge.net/p/robocode/bugs/187/ (Not enough java memory allocated in launch scripts) +[Bug-188]: http://sourceforge.net/p/robocode/bugs/188/ (Meleerumble using 2 bots instead of 10) +[Bug-189]: http://sourceforge.net/p/robocode/bugs/189/ (API - cannot subclass Event in 1.7.1) +[Bug-190]: http://sourceforge.net/p/robocode/bugs/190/ (Errors with some robot classes when rebuilding database) +[Bug-191]: http://sourceforge.net/p/robocode/bugs/191/ (EOFException during repository rebuild) +[Bug-192]: http://sourceforge.net/p/robocode/bugs/192/ (Fair Play!) +[Bug-193]: http://sourceforge.net/p/robocode/bugs/193/ (TeamRumble uploading result for Robot instead of team) +[Bug-194]: http://sourceforge.net/p/robocode/bugs/194/ (JarJar multi-registration) +[Bug-195]: http://sourceforge.net/p/robocode/bugs/195/ (Client tries to remove all participants) +[Bug-196]: http://sourceforge.net/p/robocode/bugs/196/ (Wrong file path used for development bots) +[Bug-197]: http://sourceforge.net/p/robocode/bugs/197/ (Melee rumble doesn't use "smart battles") +[Bug-199]: http://sourceforge.net/p/robocode/bugs/199/ (FontMetrics StackOverflowError) +[Bug-200]: http://sourceforge.net/p/robocode/bugs/200/ (Graphics2D.setFont() has no effect) +[Bug-201]: http://sourceforge.net/p/robocode/bugs/201/ (setMaxVelocity(lower than current) + reverse direction bug) +[Bug-202]: http://sourceforge.net/p/robocode/bugs/202/ (Installer says to run robocode.jar) +[Bug-204]: http://sourceforge.net/p/robocode/bugs/204/ (Nanobot rumble not sending melee or team parameters) +[Bug-205]: http://sourceforge.net/p/robocode/bugs/205/ (Wrong survival scores sent by rumble client) +[Bug-206]: http://sourceforge.net/p/robocode/bugs/206/ (Funny behaviors with robot graphics/painting) +[Bug-207]: http://sourceforge.net/p/robocode/bugs/207/ (Access denied javax.swing -DNOSECURITY=true) +[Bug-208]: http://sourceforge.net/p/robocode/bugs/208/ (Does not extract .properties files into bot data dirs) +[Bug-209]: http://sourceforge.net/p/robocode/bugs/209/ ([Codesize] Invalid entry point in codesize-1.1.jar) +[Bug-210]: http://sourceforge.net/p/robocode/bugs/210/ (Bullet and Ram Damage Bonuses are wrong) +[Bug-212]: http://sourceforge.net/p/robocode/bugs/212/ (Team jar files reported as corrupted) +[Bug-213]: http://sourceforge.net/p/robocode/bugs/213/ (NullPointerException when setting classpath directory) +[Bug-214]: http://sourceforge.net/p/robocode/bugs/214/ (Accel/decel rules introduced in 1.7.1.3 causes trouble) +[Bug-215]: http://sourceforge.net/p/robocode/bugs/215/ (Missed onRobotDeath events) +[Bug-216]: http://sourceforge.net/p/robocode/bugs/216/ (Sometimes too few results for robots are displayed) +[Bug-218]: http://sourceforge.net/p/robocode/bugs/218/ (Robocode enters infinite loop with the Restart button) +[Bug-222]: http://sourceforge.net/p/robocode/bugs/222/ (Some of sound not working) +[Bug-226]: http://sourceforge.net/p/robocode/bugs/226/ (java.io.FileNotFoundException in RobotFileSystemManager.init) +[Bug-227]: http://sourceforge.net/p/robocode/bugs/227/ (Can't load Katana 1.0 or DrussGT 1.3.1wilo) +[Bug-228]: http://sourceforge.net/p/robocode/bugs/228/ (Krabb.sliNk.GarmTeam 0.9v locks up in new beta) +[Bug-229]: http://sourceforge.net/p/robocode/bugs/229/ (IllegalArgumentException on painting in some robots?) +[Bug-230]: http://sourceforge.net/p/robocode/bugs/230/ (Lockup on start if too many bots in robots dir) +[Bug-231]: http://sourceforge.net/p/robocode/bugs/231/ (Lockup on start if too many bots in robots dir (cont'd)) +[Bug-232]: http://sourceforge.net/p/robocode/bugs/232/ (Graphics2D.getTransform() throws NPE) +[Bug-233]: http://sourceforge.net/p/robocode/bugs/233/ ("Teleport") +[Bug-234]: http://sourceforge.net/p/robocode/bugs/234/ (Source is not included) +[Bug-236]: http://sourceforge.net/p/robocode/bugs/236/ (Robot Editor doesn't accept packagename with dot (.) in it) +[Bug-237]: http://sourceforge.net/p/robocode/bugs/237/ (OS X 10.6: Cannot run Robocode from robocode.sh) +[Bug-238]: http://sourceforge.net/p/robocode/bugs/238/ (OS X 10.6: The editor cannot see the JD) +[Bug-240]: http://sourceforge.net/p/robocode/bugs/240/ (morbid.MorbidPriest_1.0 fails to load) +[Bug-243]: http://sourceforge.net/p/robocode/bugs/243/ (Robot console text sometimes disappears) +[Bug-244]: http://sourceforge.net/p/robocode/bugs/244/ (Robot static data isn't being GCed after battle) +[Bug-245]: http://sourceforge.net/p/robocode/bugs/245/ (Removing directories from "development options" doesn't work) +[Bug-247]: http://sourceforge.net/p/robocode/bugs/247/ (Version ordering is somewhat strange with letters) +[Bug-250]: http://sourceforge.net/p/robocode/bugs/250/ (Installer installs AutoExtract$1.class) +[Bug-252]: http://sourceforge.net/p/robocode/bugs/252/ (yk.JahRoslav 1.1 throws WinException) +[Bug-254]: http://sourceforge.net/p/robocode/bugs/254/ (Roborumble doesn't upload with EXECUTE=NOT) +[Bug-255]: http://sourceforge.net/p/robocode/bugs/255/ (java.lang.Error: Interrupted attempt to aquire read lock) +[Bug-257]: http://sourceforge.net/p/robocode/bugs/257/ (Team RoboRumble uploading is broken) +[Bug-258]: http://sourceforge.net/p/robocode/bugs/258/ (isTeammate() called on null gives NullPointerException) +[Bug-259]: http://sourceforge.net/p/robocode/bugs/259/ (jlm.javaDisturbance loses substantial score in 1.7.2 Beta) +[Bug-260]: http://sourceforge.net/p/robocode/bugs/260/ (ArrayIndexOutOfBoundsException when starting team battle) +[Bug-261]: http://sourceforge.net/p/robocode/bugs/261/ ((.NET) condition tested on concurrently modified collection) +[Bug-262]: http://sourceforge.net/p/robocode/bugs/262/ (TeamRumble: Cannot find robot in nested .jar files) +[Bug-263]: http://sourceforge.net/p/robocode/bugs/263/ (Cannot extract downloaded robot for editing in Robot Editor) +[Bug-265]: http://sourceforge.net/p/robocode/bugs/265/ (Occasionally losing the bit of text in the robot console) +[Bug-267]: http://sourceforge.net/p/robocode/bugs/267/ (Strange issue first time running roborumble in 1.7.2.0 Beta2) +[Bug-269]: http://sourceforge.net/p/robocode/bugs/269/ (Minor visual bug - Currently selected robot gets covered) +[Bug-270]: http://sourceforge.net/p/robocode/bugs/270/ (Strange thread exceptions with kid.DeltaSquad in 1.7) +[Bug-271]: http://sourceforge.net/p/robocode/bugs/271/ (Battle engine consumes more CPU power over time) +[Bug-272]: http://sourceforge.net/p/robocode/bugs/272/ (isTeammate() sometimes returns false with teammates) +[Bug-274]: http://sourceforge.net/p/robocode/bugs/274/ ("Ignoring" messages in rumble are duplicated) +[Bug-275]: http://sourceforge.net/p/robocode/bugs/275/ (Duplicate version numbers prevents uploading) +[Bug-276]: http://sourceforge.net/p/robocode/bugs/276/ (tzu.TheArtOfWar 1.2 gets NullPointerExceptions) +[Bug-277]: http://sourceforge.net/p/robocode/bugs/277/ (Problems with Graphics2D.fill/draw(Shape)) +[Bug-278]: http://sourceforge.net/p/robocode/bugs/278/ (Attempting to install robocode over an existing install NPEs) +[Bug-280]: http://sourceforge.net/p/robocode/bugs/280/ (NPE when uploading results) +[Bug-281]: http://sourceforge.net/p/robocode/bugs/281/ (The robocode.command is missing the execute permissions bit) +[Bug-282]: http://sourceforge.net/p/robocode/bugs/282/ (Cannot see robot with no package in New Battle dialog) +[Bug-283]: http://sourceforge.net/p/robocode/bugs/283/ (Possible for robot to kill other robot threads) +[Bug-284]: http://sourceforge.net/p/robocode/bugs/284/ (Robot Packager doesn't package source file in Eclipse proj) +[Bug-285]: http://sourceforge.net/p/robocode/bugs/285/ (Robot Packaging Wizard doesn't save value for Next & Back) +[Bug-286]: http://sourceforge.net/p/robocode/bugs/286/ (ClassNotFoundException at RobotClassLoader.java:271) +[Bug-287]: http://sourceforge.net/p/robocode/bugs/287/ (Zipped robots data files are not extracted) +[Bug-288]: http://sourceforge.net/p/robocode/bugs/288/ ("skipped" turns at start with -Ddebug=true) +[Bug-289]: http://sourceforge.net/p/robocode/bugs/289/ (Exclude filters not working) +[Bug-290]: http://sourceforge.net/p/robocode/bugs/290/ (Development Options remove wrong item) +[Bug-291]: http://sourceforge.net/p/robocode/bugs/291/ (JavaDoc missing _Robot and similar) +[Bug-292]: http://sourceforge.net/p/robocode/bugs/292/ (Robot PrintStream doesn't handle write in a portable fashion) +[Bug-293]: http://sourceforge.net/p/robocode/bugs/293/ (Wrong headings with the JuniorRobot) +[Bug-297]: http://sourceforge.net/p/robocode/bugs/297/ (x,y coords between BulletHitEvent & HitByBulletEvent differ) +[Bug-299]: http://sourceforge.net/p/robocode/bugs/299/ (Custom events no longer firing after clearing event queue) +[Bug-301]: http://sourceforge.net/p/robocode/bugs/301/ (getTurnRateRadians incorrect for negative velocity) +[Bug-302]: http://sourceforge.net/p/robocode/bugs/302/ (Hide enemy name implementation bug) +[Bug-303]: http://sourceforge.net/p/robocode/bugs/303/ (bullet.equals semantic has been change in 1.7.3.0 version) +[Bug-304]: http://sourceforge.net/p/robocode/bugs/304/ (setColor(null) causes NPE) +[Bug-305]: http://sourceforge.net/p/robocode/bugs/305/ (TeamRumble priority battles bug) +[Bug-306]: http://sourceforge.net/p/robocode/bugs/306/ (Rumble sh scripts for launching do not handle spaces in path) +[Bug-307]: http://sourceforge.net/p/robocode/bugs/306/ (Console output cannot handle non-ascii names) +[Bug-308]: http://sourceforge.net/p/robocode/bugs/308/ (ConcurrentModificationException in URLJarCollector) +[Bug-309]: http://sourceforge.net/p/robocode/bugs/309/ (robot in development generates * into filename) +[Bug-310]: http://sourceforge.net/p/robocode/bugs/310/ (Interface Robot skips turns at end of round) +[Bug-311]: http://sourceforge.net/p/robocode/bugs/311/ (out.write(int) uses up allocated printing quickly) +[Bug-312]: http://sourceforge.net/p/robocode/bugs/312/ (Enabling Paint Freezes Robocode) +[Bug-313]: http://sourceforge.net/p/robocode/bugs/313/ (Robocode .NET does not work on Java 7) +[Bug-315]: http://sourceforge.net/p/robocode/bugs/315/ (Unable to change drawing color in .NET (C#)) +[Bug-318]: http://sourceforge.net/p/robocode/bugs/318/ (Installer throws NumberFormatException on Linux 3.0) +[Bug-319]: http://sourceforge.net/p/robocode/bugs/319/ (Package name allows bad chars) +[Bug-320]: http://sourceforge.net/p/robocode/bugs/320/ ("About" window colors are awful) +[Bug-323]: http://sourceforge.net/p/robocode/bugs/323/ (Robocode can't find the ECJ (Eclipse Compiler for Java)) +[Bug-326]: http://sourceforge.net/p/robocode/bugs/326/ (Package of team fails to load in team battles) +[Bug-328]: http://sourceforge.net/p/robocode/bugs/328/ (Issue with the robocode.dll + # chars in the path for a dll) +[Bug-331]: http://sourceforge.net/p/robocode/bugs/331/ (RoboRumble client has infinite timeout) +[Bug-332]: http://sourceforge.net/p/robocode/bugs/332/ (Use OpenGL backend under linux) +[Bug-333]: http://sourceforge.net/p/robocode/bugs/333/ (.NET runs release dll not debug dll so can't debug) +[Bug-334]: http://sourceforge.net/p/robocode/bugs/334/ (Snapshot API never shows bullets in "HIT_WALL" status) +[Bug-335]: http://sourceforge.net/p/robocode/bugs/335/ (Skipped turns ... issues) +[Bug-336]: http://sourceforge.net/p/robocode/bugs/336/ (Skipped turns ... issues) +[Bug-337]: http://sourceforge.net/p/robocode/bugs/337/ (Hangups with New Editor in 1.7.4.0) +[Bug-338]: http://sourceforge.net/p/robocode/bugs/338/ ("Accept-Encoding: gzip" not in Roborumble HTTP Headers) +[Bug-339]: http://sourceforge.net/p/robocode/bugs/339/ (All Text Missing) +[Bug-340]: http://sourceforge.net/p/robocode/bugs/340/ (Robocode crash on window resize (linux-opengl)) +[Bug-341]: http://sourceforge.net/p/robocode/bugs/341/ (InteractiveRobots gets error "After the event was added...") +[Bug-342]: http://sourceforge.net/p/robocode/bugs/342/ (New bots not given priority) +[Bug-344]: http://sourceforge.net/p/robocode/bugs/344/ (BattleAdaptor missing in robocode.control.events) +[Bug-345]: http://sourceforge.net/p/robocode/bugs/345/ (Graphics still being rendered when minimized) +[Bug-346]: http://sourceforge.net/p/robocode/bugs/346/ (Cannot extract sources from robot packages) +[Bug-347]: http://sourceforge.net/p/robocode/bugs/347/ (/bin/sh^M bad interpreter) +[Bug-348]: http://sourceforge.net/p/robocode/bugs/348/ (.NET: UnauthorizedAccessException in AppDomainShell.Dispose()) +[Bug-349]: http://sourceforge.net/p/robocode/bugs/349/ (Instances of RobocodeEngine don't seem to be independant - memory leak and performance decrease) +[Bug-350]: http://sourceforge.net/p/robocode/bugs/350/ (Bullet id from battle record XML file is sometimes -1 causing a NumberFormatException) +[Bug-351]: http://sourceforge.net/p/robocode/bugs/351/ (Robot.onBattleEnded(BattleEndedEvent) provides wrong scores) +[Bug-352]: http://sourceforge.net/p/robocode/bugs/352/ (Results from BattleCompletedEvent.getIndexedResults() are always sorted) +[Bug-353]: http://sourceforge.net/p/robocode/bugs/353/ (RobocodeEngine.setVisible() can cause a NullPointerException) +[Bug-354]: http://sourceforge.net/p/robocode/bugs/354/ (Replaying an XML record can cause an ArrayIndexOutOfBoundsException) +[Bug-355]: http://sourceforge.net/p/robocode/bugs/355/ (Priority battles not accepted for mini/micro/nano rumbles) +[Bug-356]: http://sourceforge.net/p/robocode/bugs/356/ (Update Roborumble URLs from Darkcanuck to LiteRumble) +[Bug-357]: http://sourceforge.net/p/robocode/bugs/357/ (Tab characters are inserted in the last line of a robot source file when opening it) +[Bug-358]: http://sourceforge.net/p/robocode/bugs/358/ (Robot in default package cannot write to files. Should at least get a warning) +[Bug-361]: http://sourceforge.net/p/robocode/bugs/361/ (Problem in the text editor related with the .java file modification) +[Bug-362]: http://sourceforge.net/p/robocode/bugs/362/ (Rumble client does not remove participants in wrong codesize group) +[Bug-363]: http://sourceforge.net/p/robocode/bugs/363/ (No Last Survivor Bonus being given) +[Bug-364]: http://sourceforge.net/p/robocode/bugs/364/ (Robot Packager does not include the robot data dir in the .jar file) +[Bug-366]: http://sourceforge.net/p/robocode/bugs/366/ (Receiving enemy's real name on HitByBulletEvent) +[Bug-368]: http://sourceforge.net/p/robocode/bugs/368/ (Issues with sentries) +[Bug-369]: http://sourceforge.net/p/robocode/bugs/369/ (RoboRumble: NoClassDefFoundError for CodeSizeCalculator) +[Bug-370]: http://sourceforge.net/p/robocode/bugs/370/ (Robot Packager cannot find robot .properties file in development path) +[Bug-371]: http://sourceforge.net/p/robocode/bugs/371/ (High cpu usage on editor) +[Bug-372]: http://sourceforge.net/p/robocode/bugs/372/ (Cannot load battle file when -DNOSECURITY=true is enabled - java.lang.IllegalAccessError) +[Bug-373]: http://sourceforge.net/p/robocode/bugs/373/ (Wrong robot size calculation in version 1.9.0 - 1.9.2) +[Bug-374]: http://sourceforge.net/p/robocode/bugs/374/ (Wrong size report for minirumble in v1.9.2.2) +[Bug-375]: http://sourceforge.net/p/robocode/bugs/375/ (Wrong width and height returned for .NET robots) +[Bug-378]: http://sourceforge.net/p/robocode/bugs/378/ (robocode.robocodeGL.system.GLRenderer ClassNotFoundException) +[Bug-380]: http://sourceforge.net/p/robocode/bugs/380/ (Yet another historical bot related bug) + +[Req-1]: http://sourceforge.net/p/robocode/feature-requests/1/ (Multiple or hyperthreading CPUs (most P4s) hangs Robocode) +[Req-2]: http://sourceforge.net/p/robocode/feature-requests/2/ (Keep window size of "New battle" window) +[Req-3]: http://sourceforge.net/p/robocode/feature-requests/3/ (More precise battlefieldsize configuration) +[Req-4]: http://sourceforge.net/p/robocode/feature-requests/4/ (Prevent API from loading unused features) +[Req-5]: http://sourceforge.net/p/robocode/feature-requests/5/ (Keyboard Navigation) +[Req-6]: http://sourceforge.net/p/robocode/feature-requests/6/ (Editor Improvements) +[Req-7]: http://sourceforge.net/p/robocode/feature-requests/7/ (Graphical "debug" facilities like with RobocodeGL) +[Req-8]: http://sourceforge.net/p/robocode/feature-requests/8/ (Debug Graphics - SG Option) +[Req-10]: http://sourceforge.net/p/robocode/feature-requests/10/ (Coloring of bullets and scan arcs) +[Req-11]: http://sourceforge.net/p/robocode/feature-requests/11/ (Explosion on robots dependent on bullet energy) +[Req-12]: http://sourceforge.net/p/robocode/feature-requests/12/ (Faster framerates / Turns per second) +[Req-13]: http://sourceforge.net/p/robocode/feature-requests/13/ (Bullets are sometimes too small) +[Req-14]: http://sourceforge.net/p/robocode/feature-requests/14/ (Restart Button) +[Req-15]: http://sourceforge.net/p/robocode/feature-requests/15/ (Optional sound effects) +[Req-16]: http://sourceforge.net/p/robocode/feature-requests/16/ (Browse button in Development Options) +[Req-17]: http://sourceforge.net/p/robocode/feature-requests/17/ (New splashscreen picture) +[Req-18]: http://sourceforge.net/p/robocode/feature-requests/18/ (Better notification about new Robocode versions) +[Req-19]: http://sourceforge.net/p/robocode/feature-requests/19/ (Possible to install Robocode on Windows Vista) +[Req-20]: http://sourceforge.net/p/robocode/feature-requests/20/ (Robot templates must be updated regarding deprecated methods) +[Req-21]: http://sourceforge.net/p/robocode/feature-requests/21/ (Option for accessing external .jars) +[Req-23]: http://sourceforge.net/p/robocode/feature-requests/23/ (Preference to allow disabling of the scorecard pop-up) +[Req-24]: http://sourceforge.net/p/robocode/feature-requests/24/ (Recording of battles) +[Req-25]: http://sourceforge.net/p/robocode/feature-requests/25/ (Save battle results to file) +[Req-26]: http://sourceforge.net/p/robocode/feature-requests/26/ (Invoke default browser from Help) +[Req-30]: http://sourceforge.net/p/robocode/feature-requests/30/ (UI Control for adjusting the TPS quickly) +[Req-31]: http://sourceforge.net/p/robocode/feature-requests/31/ (Redirecting Robot output, running without GUI) +[Req-32]: http://sourceforge.net/p/robocode/feature-requests/32/ (Bullet size) +[Req-33]: http://sourceforge.net/p/robocode/feature-requests/33/ (Making robots die quicker (graphically)) +[Req-34]: http://sourceforge.net/p/robocode/feature-requests/34/ (Provide javadoc for robocode.util.Utils and robocode.control) +[Req-35]: http://sourceforge.net/p/robocode/feature-requests/35/ (Pause Button) +[Req-36]: http://sourceforge.net/p/robocode/feature-requests/36/ (Initial Placement) +[Req-37]: http://sourceforge.net/p/robocode/feature-requests/37/ (Running Score Window) +[Req-38]: http://sourceforge.net/p/robocode/feature-requests/38/ (Codesize) +[Req-39]: http://sourceforge.net/p/robocode/feature-requests/39/ (Support for RR@Hom) +[Req-44]: http://sourceforge.net/p/robocode/feature-requests/44/ (Restart tweak) +[Req-45]: http://sourceforge.net/p/robocode/feature-requests/45/ (Reset compiler cancel button) +[Req-49]: http://sourceforge.net/p/robocode/feature-requests/49/ (Speedup time required for rebuilding robot database) +[Req-50]: http://sourceforge.net/p/robocode/feature-requests/50/ (Recalculate CPU Constant) +[Req-52]: http://sourceforge.net/p/robocode/feature-requests/52/ (The 'New Battle' window sometimes is spamed with .robotcache) +[Req-53]: http://sourceforge.net/p/robocode/feature-requests/53/ (More control over the event queue) +[Req-54]: http://sourceforge.net/p/robocode/feature-requests/54/ (All input received from events) +[Req-55]: http://sourceforge.net/p/robocode/feature-requests/55/ (Exclude Filter for RoboRumble) +[Req-56]: http://sourceforge.net/p/robocode/feature-requests/56/ (Robots Cache Cleaner) +[Req-57]: http://sourceforge.net/p/robocode/feature-requests/57/ (Events processed in chronological order) +[Req-58]: http://sourceforge.net/p/robocode/feature-requests/58/ (HitRobotEvent - damage) +[Req-60]: http://sourceforge.net/p/robocode/feature-requests/60/ (Enhanced CPU constant calculation) +[Req-62]: http://sourceforge.net/p/robocode/feature-requests/62/ (Fix for massive turn skipping when cpu constant < granularity) +[Req-63]: http://sourceforge.net/p/robocode/feature-requests/63/ (Replay should store debug graphics) +[Req-64]: http://sourceforge.net/p/robocode/feature-requests/64/ (Change default battle settings like e.g. "Number of Rounds") +[Req-65]: http://sourceforge.net/p/robocode/feature-requests/65/ (Score % display) +[Req-66]: http://sourceforge.net/p/robocode/feature-requests/66/ ("onBattleIEnd(*)" Event) +[Req-70]: http://sourceforge.net/p/robocode/feature-requests/70/ (Longer package name allowed) +[Req-74]: http://sourceforge.net/p/robocode/feature-requests/74/ (Option for enabling/disabling robot timeouts) +[Req-75]: http://sourceforge.net/p/robocode/feature-requests/75/ (Add client version to POST data sent to server) +[Req-77]: http://sourceforge.net/p/robocode/feature-requests/77/ (Better "lifebar" display) +[Req-78]: http://sourceforge.net/p/robocode/feature-requests/78/ (Visual debugging without cpu penalty) +[Req-80]: http://sourceforge.net/p/robocode/feature-requests/80/ (Screenshot of battleview) +[Req-82]: http://sourceforge.net/p/robocode/feature-requests/82/ (Launch upload result in separate thread) +[Req-84]: http://sourceforge.net/p/robocode/feature-requests/84/ (Added append option in copy method (FileTransfer class)) +[Req-86]: http://sourceforge.net/p/robocode/feature-requests/86/ (Rankings should be visible when Robocode is minimized) +[Req-88]: http://sourceforge.net/p/robocode/feature-requests/88/ (Command Line option for saving a battle record file) +[Req-89]: http://sourceforge.net/p/robocode/feature-requests/89/ (Launch Robocode from .br (battle record) files) +[Req-90]: http://sourceforge.net/p/robocode/feature-requests/90/ (Prevent JuniorRobot to be unresponsive) +[Req-92]: http://sourceforge.net/p/robocode/feature-requests/92/ (Scrollable properties) +[Req-93]: http://sourceforge.net/p/robocode/feature-requests/93/ (Rename /robots/.robotcache to /robots/.data) +[Req-99]: http://sourceforge.net/p/robocode/feature-requests/99/ (Move away from Jikes towards ECJ) +[Req-101]: http://sourceforge.net/p/robocode/feature-requests/101/ (onRoundEnded()) +[Req-113]: http://sourceforge.net/p/robocode/feature-requests/113/ (Skipped turn events) +[Req-114]: http://sourceforge.net/p/robocode/feature-requests/114/ (RateControlRobot vs. TeamRobot) +[Req-115]: http://sourceforge.net/p/robocode/feature-requests/115/ (Installed package should contain readme file) +[Req-118]: http://sourceforge.net/p/robocode/feature-requests/118/ (Enable/disable development paths) +[Req-121]: http://sourceforge.net/p/robocode/feature-requests/121/ (Issues with editor font) +[Req-124]: http://sourceforge.net/p/robocode/feature-requests/124/ (Ability to save the properties file for robots in dev. path) +[Req-128]: http://sourceforge.net/p/robocode/feature-requests/128/ (In battle name hiding) +[Req-129]: http://sourceforge.net/p/robocode/feature-requests/129/ (Rules.getBulletSpeed) +[Req-134]: http://sourceforge.net/p/robocode/feature-requests/134/ (Calculate codesize after compile in editor) +[Req-135]: http://sourceforge.net/p/robocode/feature-requests/135/ (Twin Duel configuration files) +[Req-144]: http://sourceforge.net/p/robocode/feature-requests/144/ (Mac ... start with icon and name) +[Req-156]: http://sourceforge.net/p/robocode/feature-requests/156/ (Codesize added to properties file) +[Req-159]: http://sourceforge.net/p/robocode/feature-requests/159/ (Fix overkilled garbage collection on static fields) +[Req-160]: http://sourceforge.net/p/robocode/feature-requests/160/ (Fixed width font in console)

+ * If you have not already, you should create a {@link Robot} first. + * + * @see + * robocode.sourceforge.net + * @see + * Building your first robot + * + * @see JuniorRobot + * @see Robot + * @see TeamRobot + * @see RateControlRobot + * @see Droid + * @see BorderSentry + * + * @author Mathew A. Nelson (original) + * @author Flemming N. Larsen (contributor) + * @author Robert D. Maupin (contributor) + * @author Pavel Savara (contributor) + */ +public class AdvancedRobot extends _AdvancedRadiansRobot implements IAdvancedRobot, IAdvancedEvents { + + /** + * Returns the distance remaining in the robot's current move measured in + * pixels. + *

Y#GTF}} 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�@i&Q8jg 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