HuntEngine.java 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package fr.pavnay.rabbits.engine;
  2. import java.awt.Point;
  3. import java.util.List;
  4. import java.util.Random;
  5. import org.apache.log4j.Logger;
  6. import fr.pavnay.rabbits.model.Burrow;
  7. import fr.pavnay.rabbits.model.Character;
  8. import fr.pavnay.rabbits.model.Forest;
  9. import fr.pavnay.rabbits.model.Hunter;
  10. import fr.pavnay.rabbits.model.Rabbit;
  11. import fr.pavnay.rabbits.model.enums.Speed;
  12. import fr.pavnay.rabbits.model.enums.Status;
  13. /**
  14. *
  15. * This class provides the hunt mechanisms like moving, shooting, etc...
  16. *
  17. */
  18. public class HuntEngine {
  19. private static final Logger logger = Logger.getLogger(HuntEngine.class);
  20. private Forest forest;
  21. private Hunter hunter;
  22. private int stepCount = 0;
  23. private int lastShotStep = -4;
  24. private Status status = Status.RUNNING;
  25. public HuntEngine(Forest forest, Hunter hunter) {
  26. this.forest = forest;
  27. this.hunter = hunter;
  28. }
  29. public Forest getForest() {
  30. return forest;
  31. }
  32. public Hunter getHunter() {
  33. return hunter;
  34. }
  35. public Status getStatus() {
  36. return status;
  37. }
  38. /**
  39. * The core engine method. To have a full hunt cycle, call this method in a loop still the HuntEngine.getStatus() returns a value different than RUNNING.
  40. *
  41. * @return
  42. */
  43. public Status step() {
  44. logger.debug("Step " + stepCount);
  45. boolean hunterHasShot = false; // Only one shot per step
  46. int stepSinceLastShot = stepCount - lastShotStep;
  47. move(hunter);
  48. Random rand = new Random();
  49. for (Rabbit rabbit : forest.getRabbits() ) {
  50. if( stepSinceLastShot > 3 && !rabbit.isScared() ) {
  51. if( rabbit.getSpeed() > Speed.MEDIUM.getSpeed() ) {
  52. rabbit.slowDown();
  53. } else {
  54. rabbit.setSpeed(rand.nextInt(Speed.RUNNING.getSpeed()));
  55. }
  56. } else if( stepSinceLastShot > 5 && rabbit.isScared() ) {
  57. rabbit.setScared(false);
  58. }
  59. move(rabbit);
  60. boolean canShoot = !hunterHasShot && stepSinceLastShot > 5; // One shot per step and only 5 steps after the last shot.
  61. if( canShoot && forest.canView( hunter, rabbit ) && hunter.isInRange(rabbit) ) {
  62. hunterHasShot = true;
  63. lastShotStep = stepCount;
  64. if( hunter.shoot(rabbit) ) {
  65. forest.killedRabbit(rabbit);
  66. } else {
  67. logger.info(String.format("Hunter missed a shot. %d ammos remaining", hunter.getAmmos()));
  68. hunter.purchase(rabbit);
  69. }
  70. }
  71. }
  72. // A shot occurs, so rabbits must escape
  73. if( hunterHasShot ) {
  74. logger.debug("Escape from the hunter");
  75. forest.escape(hunter);
  76. }
  77. stepCount++;
  78. return updateStatus();
  79. }
  80. /**
  81. * The rabbit must choose a destination - Random, the last one or a burrow
  82. *
  83. * @param rabbit The rabbit to move
  84. */
  85. protected void move( Rabbit rabbit ) {
  86. Point location = rabbit.getLocation();
  87. Point destination = rabbit.getDestination();
  88. if( location.distance(destination) <= rabbit.getSpeed() ) {
  89. List<Burrow> refuges = rabbit.getRefuges();
  90. if( refuges.size() > 0 ) { // Purchased rabbit
  91. Burrow refuge = refuges.get( refuges.size() -1 );
  92. if( refuge.isFree() ) { // Only one rabbit per burrow
  93. refuge.setFree(false);
  94. forest.savedRabbit( rabbit );
  95. } else {
  96. Burrow burrow = forest.getNearestBurrow(hunter, rabbit); // Find another burrow
  97. rabbit.setRefuge(burrow); // Keep in mind this burrow is full
  98. rabbit.setDestination(burrow.getLocation());
  99. }
  100. } else {
  101. setRandomDestination(rabbit);
  102. }
  103. }
  104. if( rabbit.getDestination() != null ) {
  105. go(rabbit);
  106. }
  107. }
  108. /**
  109. * The hunter must choose a destination : the last one or a new randomized destination.
  110. *
  111. * @param hunter
  112. */
  113. protected void move( Hunter hunter ) {
  114. Point location = hunter.getLocation();
  115. Point destination = hunter.getDestination();
  116. if( location.distance(destination) < hunter.getSpeed() ) {
  117. destination = setRandomDestination(hunter);
  118. }
  119. go(hunter);
  120. }
  121. /**
  122. * Move the given character (Hunter or Rabbit)
  123. *
  124. * @param character
  125. */
  126. protected void go(Character character) {
  127. Point location = character.getLocation();
  128. Point destination = character.getDestination();
  129. double x = destination.getX() - location.getX();
  130. double y = destination.getY() - location.getY();
  131. double rate = character.getSpeed() / location.distance(destination);
  132. double newX = Math.max(0, location.getX() + x * rate);
  133. double newY = Math.max(0, location.getY() + y * rate);
  134. Point newLocation = new Point((int) Math.min(newX, forest.getEdgeArea()), (int) Math.min(newY, forest.getEdgeArea()));
  135. character.increaseDistance((int) location.distance(newLocation));
  136. location.setLocation( newLocation );
  137. }
  138. /**
  139. * "Choose" a random destination for the given character (Hunter or Rabbit)
  140. *
  141. * @param character The character to move
  142. * @return The new destination
  143. */
  144. protected Point setRandomDestination(Character character) {
  145. Random rand = new Random();
  146. Point destination = new Point(rand.nextInt(forest.getEdgeArea()), rand.nextInt(forest.getEdgeArea()));
  147. character.setDestination(destination);
  148. return destination;
  149. }
  150. /**
  151. * Update the hunt status
  152. *
  153. * @return The new Status
  154. */
  155. protected Status updateStatus() {
  156. if( forest.getRabbits().size() == 0 ) { // No more running rabbits, so the hunt ends
  157. if( (forest.getRabbits().size() + forest.getSavedRabbits().size()) < forest.getDeadRabbits().size() ) { // Too many dead rabbit, the hunter wins
  158. status = Status.HUNTER_WINS;
  159. } else {
  160. status = Status.RABBITS_WIN; // else, rabbits win
  161. }
  162. logger.info("Hunt ended : " + status);
  163. } else if( hunter.getAmmos() == 0 ) { // No more ammos, rabbits win
  164. status = Status.RABBITS_WIN;
  165. logger.info("Hunt ended : " + status);
  166. } else { // Hunt still running
  167. status = Status.RUNNING;
  168. }
  169. return status;
  170. }
  171. }