RoboSim.java
Go to the documentation of this file.
1 
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.Random;
7 import java.lang.reflect.Constructor;
8 public class RoboSim
9 {
11  public static class RoboSimExecutionException extends Exception
12  {
13  public String player;
14 
15  public RoboSimExecutionException(String message, String player)
16  {
17  this(message,player,-1,-1,-1,-1);
18  }
19 
20  public RoboSimExecutionException(String message, String player, Robot.GridCell cell)
21  {
22  this(message,player,cell.x_coord,cell.y_coord,-1,-1);
23  }
24 
25  public RoboSimExecutionException(String message, String player, Robot.GridCell cell, Robot.GridCell cell2)
26  {
27  this(message,player,cell.x_coord,cell.y_coord,cell2.x_coord,cell2.y_coord);
28  }
29 
30  public RoboSimExecutionException(String message, String player_, int x1, int y1, int x2, int y2)
31  {
32  super("Player "+player_+" "+message+(x1!=-1 ? " with robot at coordinates ["+x1+"]["+y1+"]" : "")+(x2!=-1 ? ", coordinates of invalid cell are ["+x2+"]["+y2+"]" : ""));
33  player = player_;
34  }
35  }
36 
38  public static class SimGridAllyDeterminant extends Robot.RobotUtility.FSPPredicate
40  public SimGridAllyDeterminant(Robot.GridCell origin_) { origin = origin_; }
41 
42  public boolean validCell(Robot.GridCell potential_ally)
43  {
44  if(potential_ally==origin)
45  return false;
46 
47  switch(potential_ally.contents)
48  {
49  case ALLY:
50  return true;
51  case SELF:
52  if(!(potential_ally instanceof SimGridCell) || !(origin instanceof SimGridCell))
53  return false;
54  SimGridCell origin_downcast = (SimGridCell)(origin);
55  SimGridCell potential_ally_downcast = (SimGridCell)(potential_ally);
56  if(potential_ally_downcast.occupant_data!=null &&
57  potential_ally_downcast.occupant_data.player.equals(origin_downcast.occupant_data.player))
58  return true;
59  default:
60  return false;
61  }
62  }
63  }
64 
65  private static class RobotData
66  {
70  public Robot robot;
71  public String player;
72 
73  //Build information
75  public int investedPower;
77 
78  //Buffered radio messages
79  public List<byte[]> buffered_radio;
80  }
81 
82  private static class SimGridCell extends Robot.GridCell
83  {
85  public int wallforthealth;
86  }
87 
88  //RoboSim environmental constants
89  private final int WALL_HEALTH = 10;
90  private final int WALL_DEFENSE = 10;
91 
92  //RoboSim execution data (world grid, turn order, GUI reference, etc.)
93  private SimGridCell[][] worldGrid;
94  private ArrayList<RobotData> turnOrder;
95  private int turnOrder_pos;
96  private SimulatorGUI gui;
97 
99  public Robot.GridCell[][] getWorldGrid() { return worldGrid; }
100 
104  public String getOccupantPlayer(Robot.GridCell to_convert)
105  {
106  return ((SimGridCell)(to_convert)).occupant_data.player;
107  }
108 
109  //Always good to have an RNG handy
110  Random generator;
111 
119  private SimGridCell[][] getSubGrid(int x_left, int y_up, int x_right, int y_down)
120  {
121  final int x_length = x_right - x_left + 1;
122  final int y_height = y_down - y_up + 1;
123 
124  SimGridCell[][] to_return = new SimGridCell[x_length][y_height];
125  for(int i=x_left; i<=x_right; i++)
126  for(int j=y_up; j<=y_down; j++)
127  to_return[i-x_left][j-y_up] = worldGrid[i][j];
128 
129  return to_return;
130  }
131 
139  private static Robot.GridCell[][] sanitizeGrid(SimGridCell[][] simgrid, String player)
140  {
141  Robot.GridCell[][] to_return = new Robot.GridCell[simgrid.length][simgrid[0].length];
142  for(int i=0; i<simgrid.length; i++)
143  for(int j=0; j<simgrid[0].length; j++)
144  {
145  SimGridCell sanitized;
146  try
147  {
148  sanitized = (SimGridCell)(simgrid[i][j].clone());
149  }
150  catch(CloneNotSupportedException e)
151  {
152  throw new RuntimeException("Problem in sanitizeGrid() clone attempt. This is not the student's fault.");
153  }
154  if(sanitized.contents==Robot.GridObject.SELF)
155  if(sanitized.occupant_data.player.equals(player))
156  sanitized.contents=Robot.GridObject.ALLY;
157  else
158  sanitized.contents=Robot.GridObject.ENEMY;
159  sanitized.occupant_data=null;
160  sanitized.wallforthealth=0;
161  to_return[i][j] = sanitized;
162  }
163 
164  return to_return;
165  }
166 
167  private static Robot.Robot_Specs checkSpecsValid(Robot.Robot_Specs proposed, String player, int skill_points) throws RoboSimExecutionException
168  {
169  if(proposed.attack + proposed.defense + proposed.power + proposed.charge != skill_points)
170  throw new RoboSimExecutionException("attempted to create invalid robot!",player);
171  return proposed;
172  }
173 
185  public RoboSim(String[] combatants, int initial_robots_per_combatant, int skill_points, int length, int width, int obstacles) throws RoboSimExecutionException
186  {
187  //Create grid
188  worldGrid = new SimGridCell[length][];
189  for(int i=0; i<length; i++)
190  {
191  worldGrid[i] = new SimGridCell[width];
192  for(int j=0; j<width; j++)
193  {
194  worldGrid[i][j] = new SimGridCell();
195  worldGrid[i][j].x_coord = i;
196  worldGrid[i][j].y_coord = j;
197  worldGrid[i][j].contents = Robot.GridObject.EMPTY;
198  }
199  }
200 
201  //Random number generator
202  generator = new Random();
203 
204  //Initialize array to hold turn order
205  turnOrder = new ArrayList<RobotData>(combatants.length*initial_robots_per_combatant);
206 
207  //Position in turnOrder
208  turnOrder_pos = 0;
209 
210  //Add robots for each combatant
211  for(String player : combatants)
212  {
213  Constructor gen_robot;
214  try
215  {
216  gen_robot = Class.forName(player).getConstructor();
217  }
218  catch(ClassNotFoundException e)
219  {
220  throw new RoboSimExecutionException("robot not found", player);
221  }
222  catch(NoSuchMethodException e)
223  {
224  throw new RoboSimExecutionException("Student's robot doesn't have a default constructor", player);
225  }
226  for(int i=0; i<initial_robots_per_combatant; i++)
227  {
228  int x_pos,y_pos;
229  do
230  {
231  x_pos = generator.nextInt(length);
232  y_pos = generator.nextInt(width);
233  } while(worldGrid[x_pos][y_pos].contents!=Robot.GridObject.EMPTY);
234 
235  worldGrid[x_pos][y_pos].contents = Robot.GridObject.SELF;
236  RobotData data = worldGrid[x_pos][y_pos].occupant_data = new RobotData();
237  data.assoc_cell = worldGrid[x_pos][y_pos];
238  try
239  {
240  data.robot = (Robot)(gen_robot.newInstance());
241  }
242  catch(Exception e)
243  {
244  throw new RoboSimExecutionException("something went wrong invoking studen'ts constructor", player);
245  }
246  data.player = player;
247  byte[] creation_message = new byte[64];
248  creation_message[1] = (byte)(turnOrder_pos % 256);
249  creation_message[0] = (byte)(turnOrder_pos / 256);
250  data.specs = checkSpecsValid(data.robot.createRobot(null, skill_points, creation_message), player, skill_points);
251  data.status = new Robot.Robot_Status();
252  data.status.charge = data.status.health = data.specs.power*10;
253  data.buffered_radio = new ArrayList<byte[]>();
254  turnOrder.add(data);
255  }
256  }
257 
258  //Add obstacles to battlefield
259  for(int i=0; i<obstacles; i++)
260  {
261  int x_pos, y_pos;
262  do
263  {
264  x_pos = generator.nextInt(length);
265  y_pos = generator.nextInt(width);
266  } while(worldGrid[x_pos][y_pos].contents!=Robot.GridObject.EMPTY);
267  worldGrid[x_pos][y_pos].contents = Robot.GridObject.WALL;
268  worldGrid[x_pos][y_pos].wallforthealth = WALL_HEALTH;
269  }
270  }
271 
282  private class RoboAPIImplementor implements WorldAPI
283  {
285 
290  private RoboAPIImplementor(RobotData actingRobot_) { actingRobot = actingRobot_; }
291 
297  private boolean isAdjacent(Robot.GridCell adjacent_cell)
298  {
299  return (Math.abs(actingRobot.assoc_cell.x_coord-adjacent_cell.x_coord)==1 &&
300  actingRobot.assoc_cell.y_coord == adjacent_cell.y_coord ||
301  Math.abs(actingRobot.assoc_cell.y_coord-adjacent_cell.y_coord)==1 &&
302  actingRobot.assoc_cell.x_coord == adjacent_cell.x_coord);
303  }
304 
311  private boolean calculateHit(int attack, int defense)
312  {
313  int luckOfAttacker = generator.nextInt(10);
314  return luckOfAttacker+attack-defense>=5;
315  }
316 
323  private Robot.AttackResult processAttack(int attack, SimGridCell cell_to_attack, int power) throws RoboSimExecutionException
324  {
325  //Holds result of attack
326  Robot.AttackResult to_return = Robot.AttackResult.MISSED;
327 
328  //Calculate defense skill of opponent
329  int defense = 0;
330  switch(cell_to_attack.contents)
331  {
332  case SELF:
333  defense = cell_to_attack.occupant_data.specs.defense + cell_to_attack.occupant_data.status.defense_boost;
334  break;
335 
336  case FORT:
337  case WALL:
338  defense = 10;
339  break;
340  }
341 
342 
343  //If we hit, damage the opponent
344  if(calculateHit(attack,defense))
345  {
346  //We hit
347  to_return = Robot.AttackResult.HIT;
348 
349  if(cell_to_attack.occupant_data!=null)
350  {
351  //we're a robot
352  for(int i=0; true; i++)
353  if(turnOrder.get(i)==cell_to_attack.occupant_data)
354  {
355  if((cell_to_attack.occupant_data.status.health-=power)<=0)
356  {
357  //We destroyed the opponent!
358  to_return = Robot.AttackResult.DESTROYED_TARGET;
359 
360  //Handle in-progress build, reusing setBuildTarget() to handle interruption of build due to death
361  (new RoboAPIImplementor(cell_to_attack.occupant_data)).setBuildTarget(null,null);
362 
363  //Handle cell
364  cell_to_attack.occupant_data = null;
365  cell_to_attack.contents = cell_to_attack.wallforthealth>0 ? Robot.GridObject.FORT : Robot.GridObject.EMPTY;
366 
367  //Handle turnOrder position
368  turnOrder.remove(i);
369  if(i<turnOrder_pos)
370  turnOrder_pos--;
371  }
372  break;
373  }
374  }
375  else
376  if((cell_to_attack.wallforthealth-=power)<=0)
377  {
378  //We destroyed the target!
379  to_return = Robot.AttackResult.DESTROYED_TARGET;
380 
381  cell_to_attack.wallforthealth = 0;
382  cell_to_attack.contents = Robot.GridObject.EMPTY;
383  }
384  }
385 
386  return to_return;
387  }
388 
389  public Robot.AttackResult meleeAttack(int power, Robot.GridCell adjacent_cell) throws RoboSimExecutionException
390  {
391  //Lots of error checking here (as everywhere...)
392  if(adjacent_cell==null)
393  throw new RoboSimExecutionException("passed null as argument to meleeAttack()",actingRobot.player);
394 
395  //Check that we're using a valid amount of power
396  if(power > actingRobot.status.power || power > actingRobot.specs.attack || power < 1)
397  throw new RoboSimExecutionException("attempted melee attack with illegal power level",actingRobot.player,actingRobot.assoc_cell);
398 
399  //Are cells adjacent?
400  if(!isAdjacent(adjacent_cell))
401  throw new RoboSimExecutionException("attempted to melee attack nonadjacent cell",actingRobot.player,actingRobot.assoc_cell);
402 
403  //Does cell exist in grid?
404  //(could put this in isAdjacent() method but want to give students more useful error messages)
405  if(adjacent_cell.x_coord > worldGrid.length || adjacent_cell.y_coord > worldGrid[0].length ||
406  adjacent_cell.x_coord < 0 || adjacent_cell.y_coord < 0)
407  throw new RoboSimExecutionException("passed invalid cell coordinates to meleeAttack()",actingRobot.player,actingRobot.assoc_cell,adjacent_cell);
408 
409  //Safe to use this now, checked for oob condition from student
410  SimGridCell cell_to_attack = worldGrid[adjacent_cell.x_coord][adjacent_cell.y_coord];
411 
412  //Is there an enemy, fort, or wall at the cell's location?
413  switch(cell_to_attack.contents)
414  {
415  case EMPTY:
416  throw new RoboSimExecutionException("attempted to attack empty cell",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
417  case BLOCKED:
418  throw new RoboSimExecutionException("attempted to attack blocked tile",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
419  case SELF:
420  if(cell_to_attack.occupant_data.player.equals(actingRobot.player))
421  throw new RoboSimExecutionException("attempted to attack ally",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
422  break;
423  case CAPSULE:
424  throw new RoboSimExecutionException("attempted to attack energy capsule",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
425  case ALLY:
426  throw new RuntimeException("ERROR in RoboSim.RoboAPIImplementor.meleeAttack(). This is probably not the student's fault. Contact Patrick Simmons about this message. (Not the Doobie Brother...)");
427  }
428 
429  //Okay, if we haven't thrown an exception, the cell is valid to attack. Perform the attack.
430  //Update this robot's charge status and power status.
431  actingRobot.status.charge-=power;
432  actingRobot.status.power-=power;
433 
434  //Begin calculation of our attack power
435  int raw_attack = actingRobot.specs.attack;
436 
437  //If we're outside a fort attacking someone in the fort, range penalty applies
438  if(cell_to_attack.wallforthealth > 0 && cell_to_attack.occupant_data!=null)
439  raw_attack/=2;
440 
441  //Attack adds power of attack to raw skill
442  int attack = raw_attack + power;
443 
444  //Process attack
445  return processAttack(attack,cell_to_attack,power);
446  }
447 
448  public Robot.AttackResult rangedAttack(int power, Robot.GridCell nonadjacent_cell) throws RoboSimExecutionException
449  {
450  //Lots of error checking here (as everywhere...)
451  if(nonadjacent_cell==null)
452  throw new RoboSimExecutionException("passed null as argument to rangedAttack()",actingRobot.player,actingRobot.assoc_cell);
453 
454 
455  //Check that we're using a valid amount of power
456  if(power > actingRobot.status.power || power > actingRobot.specs.attack || power < 1)
457  throw new RoboSimExecutionException("attempted ranged attack with illegal power level",actingRobot.player,actingRobot.assoc_cell);
458 
459  //Does cell exist in grid?
460  //(could put this in isAdjacent() method but want to give students more useful error messages)
461  if(nonadjacent_cell.x_coord > worldGrid.length || nonadjacent_cell.y_coord > worldGrid[0].length ||
462  nonadjacent_cell.x_coord < 0 || nonadjacent_cell.y_coord < 0)
463  throw new RoboSimExecutionException("passed invalid cell coordinates to rangedAttack()",actingRobot.player,actingRobot.assoc_cell,nonadjacent_cell);
464 
465  //Are cells nonadjacent?
466  if(isAdjacent(nonadjacent_cell))
467  throw new RoboSimExecutionException("attempted to range attack adjacent cell",actingRobot.player,actingRobot.assoc_cell);
468 
469  //Safe to use this now, checked for oob condition from student
470  SimGridCell cell_to_attack = worldGrid[nonadjacent_cell.x_coord][nonadjacent_cell.y_coord];
471 
472  //Do we have a "clear shot"?
473  Robot.GridCell[] shortest_path = Robot.RobotUtility.findShortestPath(actingRobot.assoc_cell,cell_to_attack,worldGrid);
474  if(shortest_path==null) //we don't have a clear shot
475  throw new RoboSimExecutionException("attempted to range attack cell with no clear path",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
476  else if(shortest_path.length>actingRobot.specs.defense) //out of range
477  throw new RoboSimExecutionException("attempted to range attack cell more than (defense) tiles away",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
478 
479  //Is there an enemy, fort, or wall at the cell's location?
480  switch(cell_to_attack.contents)
481  {
482  case EMPTY:
483  throw new RoboSimExecutionException("attempted to attack empty cell",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
484  case BLOCKED:
485  throw new RoboSimExecutionException("attempted to attack blocked tile",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
486  case SELF:
487  if(cell_to_attack.occupant_data.player.equals(actingRobot.player))
488  throw new RoboSimExecutionException("attempted to attack ally",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
489  break;
490  case CAPSULE:
491  throw new RoboSimExecutionException("attempted to attack energy capsule",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
492  case ALLY:
493  throw new RuntimeException("ERROR in RoboSim.RoboAPIImplementor.rangedAttack(). This is probably not the student's fault. Contact Patrick Simmons about this message. (Not the Doobie Brother...)");
494  }
495 
496  //Okay, if we haven't thrown an exception, the cell is valid to attack. Perform the attack.
497  //Update this robot's charge status.
498  actingRobot.status.charge-=power;
499  actingRobot.status.power-=power;
500 
501  //Begin calculation of our attack power
502  int raw_attack = actingRobot.specs.attack/2;
503 
504  //Attack adds power of attack to raw skill
505  int attack = raw_attack + power;
506 
507  //Process attack
508  return processAttack(attack,cell_to_attack,power);
509  }
510 
511  public Robot.AttackResult capsuleAttack(int power_of_capsule, Robot.GridCell cell) throws RoboSimExecutionException
512  {
513  //Error checking, *sigh*...
514  if(cell==null)
515  throw new RoboSimExecutionException("passed null to capsuleAttack()",actingRobot.player,actingRobot.assoc_cell);
516 
517  //Does cell exist in grid?
518  if(cell.x_coord > worldGrid.length || cell.y_coord > worldGrid[0].length || cell.x_coord < 0 || cell.y_coord < 0)
519  throw new RoboSimExecutionException("passed invalid cell coordinates to capsuleAttack()",actingRobot.player,actingRobot.assoc_cell,cell);
520 
521  //Cell to attack
522  SimGridCell cell_to_attack = worldGrid[cell.x_coord][cell.y_coord];
523 
524  //Do we have a capsule of this power rating?
525  int capsule_index = ArrayUtility.linearSearch(actingRobot.status.capsules,power_of_capsule);
526 
527  if(capsule_index==-1)
528  throw new RoboSimExecutionException("passed invalid power to capsuleAttack(): doesn't have capsule of power "+power_of_capsule,actingRobot.player,actingRobot.assoc_cell);
529 
530  //Can we use this capsule? (attack + defense >= power)
531  if(actingRobot.specs.attack + actingRobot.specs.defense < power_of_capsule)
532  throw new RoboSimExecutionException("attempted to use capsule of greater power than attack+defense",actingRobot.player,actingRobot.assoc_cell);
533 
534  //Can we hit the target? Range is power of capsule + defense.
535  Robot.GridCell[] shortest_path = Robot.RobotUtility.findShortestPath(actingRobot.assoc_cell,cell_to_attack,worldGrid);
536 
537  if(shortest_path==null)
538  throw new RoboSimExecutionException("no clear shot to target",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
539 
540  if(shortest_path.length > power_of_capsule + actingRobot.specs.defense)
541  throw new RoboSimExecutionException("target not in range",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
542 
543  //Is there an enemy, fort, or wall at the cell's location?
544  switch(cell_to_attack.contents)
545  {
546  case EMPTY:
547  throw new RoboSimExecutionException("attempted to attack empty cell",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
548  case BLOCKED:
549  throw new RoboSimExecutionException("attempted to attack blocked tile",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
550  case SELF:
551  if(cell_to_attack.occupant_data.player.equals(actingRobot.player))
552  throw new RoboSimExecutionException("attempted to attack ally",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
553  break;
554  case CAPSULE:
555  throw new RoboSimExecutionException("attempted to attack energy capsule",actingRobot.player,actingRobot.assoc_cell,cell_to_attack);
556  case ALLY:
557  throw new RuntimeException("ERROR in RoboSim.RoboAPIImplementor.capsuleAttack(). This is probably not the student's fault. Contact Patrick Simmons about this message. (Not the Doobie Brother...)");
558  }
559 
560  /*Okay, if we're still here, we can use the capsule.
561  Need to delete capsule from robot status structure.
562  */
563  actingRobot.status.capsules = ArrayUtility.deleteElement(actingRobot.status.capsules,capsule_index);
564 
565  int[] newCapsules = new int[actingRobot.status.capsules.length-1];
566  boolean deleted_capsule = false;
567  for(int i=0,j=0; i<actingRobot.status.capsules.length; i++,j++)
568  {
569  if(!deleted_capsule && actingRobot.status.capsules[i]==power_of_capsule)
570  {
571  deleted_capsule=true;
572  j--;
573  continue;
574  }
575  newCapsules[j]=actingRobot.status.capsules[i];
576  }
577 
578  //Process attack
579  return processAttack(actingRobot.specs.attack + power_of_capsule,cell_to_attack,(int)(Math.ceil(0.1 * power_of_capsule * actingRobot.specs.attack)));
580  }
581 
582  public void defend(int power) throws RoboSimExecutionException
583  {
584  //Error checking
585  if(power < 0 || power > actingRobot.specs.defense || power > actingRobot.specs.power || power > actingRobot.status.charge)
586  throw new RoboSimExecutionException("attemped to defend with negative power",actingRobot.player, actingRobot.assoc_cell);
587 
588  //This one's easy
589  actingRobot.status.charge-=power;
590  actingRobot.status.defense_boost+=power;
591  }
592 
593  public void move(int steps, Robot.Direction way) throws RoboSimExecutionException
594  {
595  if(steps<1)
596  return;
597 
598  int x_coord = actingRobot.assoc_cell.x_coord;
599  final int actor_x = x_coord;
600  int y_coord = actingRobot.assoc_cell.y_coord;
601  final int actor_y = y_coord;
602  switch(way)
603  {
604  case UP:
605  y_coord-=steps;
606  break;
607  case DOWN:
608  y_coord+=steps;
609  break;
610  case LEFT:
611  x_coord-=steps;
612  break;
613  case RIGHT:
614  x_coord+=steps;
615  break;
616  }
617 
618  //Is our destination in the map?
619  if(x_coord < 0 || x_coord > worldGrid.length || y_coord < 0 || y_coord > worldGrid[0].length)
620  throw new RoboSimExecutionException("attempted to move out of bounds",actingRobot.player,actingRobot.assoc_cell);
621 
622  //Is our destination empty?
623  if(worldGrid[x_coord][y_coord].contents!=Robot.GridObject.EMPTY && worldGrid[x_coord][y_coord].contents!=Robot.GridObject.FORT)
624  throw new RoboSimExecutionException("attempted to move onto illegal cell",actingRobot.player,actingRobot.assoc_cell,worldGrid[x_coord][y_coord]);
625 
626  //Are we approaching the fort from the right angle?
627  if(worldGrid[x_coord][y_coord].contents==Robot.GridObject.FORT && worldGrid[x_coord][y_coord].fort_orientation!=way)
628  throw new RoboSimExecutionException("attempted to move onto a fort from an illegal direction",actingRobot.player,actingRobot.assoc_cell,worldGrid[x_coord][y_coord]);
629 
630  //Okay, now we have to make sure each step is empty
631  final boolean x_left = x_coord<actor_x;
632  final boolean y_left = y_coord<actor_y;
633  if(x_coord!=actor_x)
634  {
635  for(int i=(x_left ? actor_x-1 : actor_x+1); i!=x_coord; i=(x_left ? i-1 : i+1))
636  if(worldGrid[i][y_coord].contents!=Robot.GridObject.EMPTY)
637  throw new RoboSimExecutionException("attempted to cross illegal cell",actingRobot.player,actingRobot.assoc_cell,worldGrid[i][y_coord]);
638  }
639  else
640  {
641  for(int i=(y_left ? actor_y-1 : actor_y+1); i!=y_coord; i=(y_left ? i-1 : i+1))
642  if(worldGrid[x_coord][i].contents!=Robot.GridObject.EMPTY)
643  throw new RoboSimExecutionException("attempted to cross illegal cell",actingRobot.player,actingRobot.assoc_cell,worldGrid[x_coord][i]);
644  }
645 
646  //Okay, now: do we have enough power/charge?
647  if(steps > actingRobot.status.power)
648  throw new RoboSimExecutionException("attempted to move too far (not enough power)",actingRobot.player,actingRobot.assoc_cell,worldGrid[x_coord][y_coord]);
649 
650  //Account for power cost
651  actingRobot.status.power-=steps;
652  actingRobot.status.charge-=steps;
653 
654  //Change position of robot.
655  actingRobot.assoc_cell.contents = Robot.GridObject.EMPTY;
656  actingRobot.assoc_cell.occupant_data = null;
657  actingRobot.assoc_cell = worldGrid[x_coord][y_coord];
658  actingRobot.assoc_cell.contents = Robot.GridObject.SELF;
659  actingRobot.assoc_cell.occupant_data = actingRobot;
660  }
661 
662  public void pick_up_capsule(Robot.GridCell adjacent_cell) throws RoboSimExecutionException
663  {
664  //Error checking, *sigh*...
665  //Can't pass us null
666  if(adjacent_cell==null)
667  throw new RoboSimExecutionException("passed null to pick_up_capsule()",actingRobot.player,actingRobot.assoc_cell);
668 
669  //Does cell exist in grid?
670  if(adjacent_cell.x_coord > worldGrid.length || adjacent_cell.y_coord > worldGrid[0].length || adjacent_cell.x_coord < 0 || adjacent_cell.y_coord < 0)
671  throw new RoboSimExecutionException("passed invalid cell coordinates to pick_up_capsule()",actingRobot.player,actingRobot.assoc_cell,adjacent_cell);
672 
673  //Cell in question
674  SimGridCell gridCell = worldGrid[adjacent_cell.x_coord][adjacent_cell.y_coord];
675 
676  //Cell must be adjacent
677  if(!isAdjacent(adjacent_cell))
678  throw new RoboSimExecutionException("attempted to pick up capsule in nonadjacent cell",actingRobot.player,actingRobot.assoc_cell,gridCell);
679 
680  //We need at least one power.
681  if(actingRobot.status.power==0)
682  throw new RoboSimExecutionException("attempted to pick up capsule with no power",actingRobot.player,actingRobot.assoc_cell,gridCell);
683 
684  //Is there actually a capsule there?
685  if(gridCell.contents!=Robot.GridObject.CAPSULE)
686  throw new RoboSimExecutionException("attempted to pick up capsule from cell with no capsule",actingRobot.player,actingRobot.assoc_cell,gridCell);
687 
688  //Do we have "room" for this capsule?
689  if(actingRobot.status.capsules.length+1>actingRobot.specs.attack+actingRobot.specs.defense)
690  throw new RoboSimExecutionException("attempted to pick up too many capsules",actingRobot.player,actingRobot.assoc_cell,gridCell);
691 
692  //If still here, yes.
693 
694  //Decrement our power
695  actingRobot.status.power--;
696 
697  //Put capsule in our inventory, delete it from world
698  actingRobot.status.capsules = ArrayUtility.addElement(actingRobot.status.capsules,gridCell.capsule_power);
699  gridCell.contents = Robot.GridObject.EMPTY;
700  gridCell.capsule_power = 0;
701  }
702 
703  public void drop_capsule(Robot.GridCell adjacent_cell, int power_of_capsule) throws RoboSimExecutionException
704  {
705  //Error checking, *sigh*...
706  //Can't pass us null
707  if(adjacent_cell==null)
708  throw new RoboSimExecutionException("passed null to pick_up_capsule()",actingRobot.player,actingRobot.assoc_cell);
709 
710  //Does cell exist in grid?
711  if(adjacent_cell.x_coord > worldGrid.length || adjacent_cell.y_coord > worldGrid[0].length || adjacent_cell.x_coord < 0 || adjacent_cell.y_coord < 0)
712  throw new RoboSimExecutionException("passed invalid cell coordinates to pick_up_capsule()",actingRobot.player,actingRobot.assoc_cell,adjacent_cell);
713 
714  //Cell in question
715  SimGridCell gridCell = worldGrid[adjacent_cell.x_coord][adjacent_cell.y_coord];
716 
717  //Cell must be adjacent
718  if(!isAdjacent(adjacent_cell))
719  throw new RoboSimExecutionException("attempted to pick up capsule in nonadjacent cell",actingRobot.player,actingRobot.assoc_cell,gridCell);
720 
721  //Is the cell empty?
722  if(gridCell.contents!=Robot.GridObject.EMPTY)
723  throw new RoboSimExecutionException("attempted to place capsule in nonempty cell",actingRobot.player,actingRobot.assoc_cell,gridCell);
724 
725  //Do we have such a capsule?
726  int index = ArrayUtility.linearSearch(actingRobot.status.capsules,power_of_capsule);
727  if(index==-1)
728  throw new RoboSimExecutionException("attempted to drop capsule with power "+power_of_capsule+", having no such capsule",actingRobot.player,actingRobot.assoc_cell,gridCell);
729 
730  //Okay. We're good. Drop the capsule
731  gridCell.contents = Robot.GridObject.CAPSULE;
732  gridCell.capsule_power = power_of_capsule;
733 
734  //Delete it from our inventory
735  ArrayUtility.deleteElement(actingRobot.status.capsules,index);
736  }
737 
739  {
740  return actingRobot.whatBuilding;
741  }
742 
744  {
745  return actingRobot.invested_assoc_cell;
746  }
747 
749  {
750  return actingRobot.investedPower;
751  }
752 
753  private void finalizeBuilding(byte[] creation_message) throws RoboSimExecutionException
754  {
755  //Nothing to finalize if not building anything
756  if(actingRobot.whatBuilding==null)
757  return;
758 
759  //What do we have to finalize?
760  switch(actingRobot.whatBuilding)
761  {
762  case WALL:
763  if(actingRobot.investedPower >= 50)
764  {
765  actingRobot.invested_assoc_cell.contents = Robot.GridObject.WALL;
766  actingRobot.invested_assoc_cell.wallforthealth = WALL_HEALTH;
767  }
768  else
769  actingRobot.invested_assoc_cell.contents = Robot.GridObject.EMPTY;
770  break;
771 
772  case FORT:
773  if(actingRobot.investedPower >= 75)
774  {
775  actingRobot.invested_assoc_cell.contents = Robot.GridObject.FORT;
776  actingRobot.invested_assoc_cell.wallforthealth = WALL_HEALTH;
777  }
778  else
779  actingRobot.invested_assoc_cell.contents = Robot.GridObject.EMPTY;
780  break;
781 
782  case CAPSULE:
783  int capsule_power = actingRobot.investedPower/10;
784  if(capsule_power!=0)
785  {
786  if(actingRobot.status.capsules.length+1>actingRobot.specs.attack+actingRobot.specs.defense)
787  throw new RoboSimExecutionException("attempted to finish building capsule when already at max capsule capacity",actingRobot.player,actingRobot.assoc_cell);
788  actingRobot.status.capsules = ArrayUtility.addElement(actingRobot.status.capsules,capsule_power);
789  }
790  break;
791 
792  case ROBOT:
793  int skill_points = actingRobot.investedPower/20;
794  if(skill_points!=0)
795  {
796  //Check creation message correct size
797  if(creation_message!=null && creation_message.length!=64)
798  throw new RoboSimExecutionException("passed incorrect sized creation message to setBuildTarget()",actingRobot.player,actingRobot.assoc_cell,actingRobot.invested_assoc_cell);
799 
800  //Set default creation message if we don't have one
801  if(creation_message==null)
802  {
803  creation_message = new byte[64];
804  creation_message[1] = (byte)(turnOrder.size() % 256);
805  creation_message[0] = (byte)(turnOrder.size() / 256);
806  }
807 
808  //Create the robot
809  actingRobot.invested_assoc_cell.contents = Robot.GridObject.SELF;
810  RobotData data = actingRobot.invested_assoc_cell.occupant_data = new RobotData();
811  data.assoc_cell = actingRobot.invested_assoc_cell;
812  try
813  {
814  data.robot = (Robot)(Class.forName(actingRobot.player).getConstructor().newInstance());
815  }
816  catch(Exception e)
817  {
818  throw new RoboSimExecutionException("something went wrong calling student's constructor", actingRobot.player,actingRobot.assoc_cell, actingRobot.invested_assoc_cell);
819  }
820  data.player = actingRobot.player;
821  data.specs = checkSpecsValid(data.robot.createRobot(null, skill_points, creation_message), actingRobot.player, skill_points);
822  data.status = new Robot.Robot_Status();
823  data.status.charge = data.status.health = data.specs.power*10;
824  data.buffered_radio = new ArrayList<byte[]>();
825  turnOrder.add(data);
826  }
827  else
828  actingRobot.invested_assoc_cell.contents = Robot.GridObject.EMPTY;
829  break;
830  }
831  }
832 
833  public void setBuildTarget(Robot.BuildStatus status, Robot.GridCell location) throws RoboSimExecutionException
834  {
835  setBuildTarget(status,location,null);
836  }
837 
838  public void setBuildTarget(Robot.BuildStatus status, Robot.GridCell location, byte[] message) throws RoboSimExecutionException
839  {
840  //If we're in the middle of building something, finalize it.
841  if(actingRobot.whatBuilding!=null)
842  finalizeBuilding(message);
843 
844  //Error checking, *sigh*...
845 
846  //Does cell exist in grid?
847  if(location!=null && (location.x_coord > worldGrid.length || location.y_coord > worldGrid[0].length || location.x_coord < 0 || location.y_coord < 0))
848  throw new RoboSimExecutionException("passed invalid cell coordinates to setBuildTarget()",actingRobot.player,actingRobot.assoc_cell,location);
849 
850  //Cell in question
851  SimGridCell gridCell = (location!=null ? worldGrid[location.x_coord][location.y_coord] : null);
852 
853  //Update status
854  actingRobot.whatBuilding = status;
855  actingRobot.investedPower = 0;
856  actingRobot.invested_assoc_cell = gridCell;
857 
858  //CAN pass us null, so special-case it
859  if(location==null)
860  {
861  //We must be building capsule, then.
862  if(actingRobot.whatBuilding!=null && actingRobot.whatBuilding!=Robot.BuildStatus.CAPSULE)
863  throw new RoboSimExecutionException("passed null to setBuildTarget() location with non-null and non-capsule build target",actingRobot.player,actingRobot.assoc_cell);
864  return;
865  }
866 
867  //If location NOT null, must not be building capsule
868  if(status == null || status == Robot.BuildStatus.CAPSULE)
869  throw new RoboSimExecutionException("attempted to target capsule or null building on non-null adjacent cell",actingRobot.player,actingRobot.assoc_cell,location);
870 
871  //Cell must be adjacent
872  if(!isAdjacent(location))
873  throw new RoboSimExecutionException("attempted to set build target to nonadjacent cell",actingRobot.player,actingRobot.assoc_cell,gridCell);
874 
875  //Is the cell empty?
876  if(gridCell.contents!=Robot.GridObject.EMPTY)
877  throw new RoboSimExecutionException("attempted to set build target to nonempty cell",actingRobot.player,actingRobot.assoc_cell,gridCell);
878 
879  //Okay, block off cell since we're building there now.
880  gridCell.contents = Robot.GridObject.BLOCKED;
881  }
882 
883  public void build(int power) throws RoboSimExecutionException
884  {
885  if(power > actingRobot.status.power || power < 0)
886  throw new RoboSimExecutionException("attempted to apply invalid power to build task",actingRobot.player,actingRobot.assoc_cell);
887  actingRobot.status.charge-=power;
888  actingRobot.status.power-=power;
889  actingRobot.investedPower+=power;
890  }
891 
892  public void repair(int power) throws RoboSimExecutionException
893  {
894  if(power > actingRobot.status.power || power < 0)
895  throw new RoboSimExecutionException("attempted to apply invalid power to repair task",actingRobot.player,actingRobot.assoc_cell);
896  actingRobot.status.charge-=power;
897  actingRobot.status.power-=power;
898  actingRobot.status.health+=power/2;
899 
900  //Can't have more health than charge skill*10
901  if(actingRobot.status.health > actingRobot.specs.charge*10)
902  actingRobot.status.health = actingRobot.specs.charge*10;
903  }
904 
905  public void charge(int power, Robot.GridCell ally) throws RoboSimExecutionException
906  {
907  //Lots of error checking here (as everywhere...)
908  if(ally==null)
909  throw new RoboSimExecutionException("passed null as argument to charge()",actingRobot.player);
910 
911  //Check that we're using a valid amount of power
912  if(power > actingRobot.status.power || power < 1)
913  throw new RoboSimExecutionException("attempted charge with illegal power level",actingRobot.player,actingRobot.assoc_cell);
914 
915  //Are cells adjacent?
916  if(!isAdjacent(ally))
917  throw new RoboSimExecutionException("attempted to charge nonadjacent cell",actingRobot.player,actingRobot.assoc_cell);
918 
919  //Does cell exist in grid?
920  //(could put this in isAdjacent() method but want to give students more useful error messages)
921  if(ally.x_coord > worldGrid.length || ally.y_coord > worldGrid[0].length || ally.x_coord < 0 || ally.y_coord < 0)
922  throw new RoboSimExecutionException("passed invalid cell coordinates to charge()",actingRobot.player,actingRobot.assoc_cell,ally);
923 
924  //Safe to use this now, checked for oob condition from student
925  SimGridCell allied_cell = worldGrid[ally.x_coord][ally.y_coord];
926 
927  //Is there an ally in that cell?
928  if(allied_cell.contents!=Robot.GridObject.SELF || !allied_cell.occupant_data.player.equals(actingRobot.player))
929  throw new RoboSimExecutionException("attempted to charge non-ally, or cell with no robot in it",actingRobot.player,actingRobot.assoc_cell,allied_cell);
930 
931  //Perform the charge
932  actingRobot.status.power-=power;
933  actingRobot.status.charge-=power;
934  allied_cell.occupant_data.status.charge+=power;
935  }
936 
937  public void sendMessage(byte[] message, int power) throws RoboSimExecutionException
938  {
939  if(power < 1 || power > 2)
940  throw new RoboSimExecutionException("attempted to send message with invalid power", actingRobot.player,actingRobot.assoc_cell);
941 
942  if(message.length!=64)
943  throw new RoboSimExecutionException("attempted to send message byte array of incorrect length", actingRobot.player,actingRobot.assoc_cell);
944 
945  Robot.GridCell target = null;
946  if(power==1)
947  {
948  target = Robot.RobotUtility.findNearestAlly(actingRobot.assoc_cell,worldGrid);
949  if(target!=null)
950  {
951  /*There's a way to "cheat" here and set up a power-free comm channel
952  *between two allied robots. If you can find it ... let me know, and
953  *you'll get extra credit :). Additional credit for a bugfix.*/
954  ((SimGridCell)(target)).occupant_data.buffered_radio.add(message);
955  }
956  return;
957  }
958  else //power==2
959  for(RobotData x : turnOrder)
960  if(x!=actingRobot && x.player.equals(actingRobot.player))
961  x.buffered_radio.add(message);
962  }
963 
964  //It's a wonderful day in the neighborhood...
966  {
967  //YAY! No parameters means NO ERROR CHECKING! YAY!
968  final int range = actingRobot.specs.defense;
969  final int xloc = actingRobot.assoc_cell.x_coord;
970  final int yloc = actingRobot.assoc_cell.y_coord;
971  final int x_left = (xloc - range < 0) ? 0 : (xloc - range);
972  final int x_right = (xloc + range > worldGrid.length-1) ? (worldGrid.length-1) : (xloc + range);
973  final int y_up = (yloc - range < 0) ? 0 : (yloc - range);
974  final int y_down = (yloc + range > worldGrid[0].length - 1) ? (worldGrid[0].length-1) : (yloc + range);
975  Robot.GridCell[][] to_return = sanitizeGrid(getSubGrid(x_left,y_up,x_right,y_down),actingRobot.player);
976 
977  //Set associated cell to SELF instead of ALLY
978  to_return[xloc - x_left][yloc - y_up].contents=Robot.GridObject.SELF;
979  return to_return;
980  }
981 
982  public Robot.GridCell[][] getWorld(int power) throws RoboSimExecutionException
983  {
984  if(power!=3)
985  throw new RoboSimExecutionException("tried to get world with invalid power (not equal to 3)",actingRobot.player,actingRobot.assoc_cell);
986 
987  Robot.GridCell[][] to_return = sanitizeGrid(getSubGrid(0,0,worldGrid.length-1,worldGrid[0].length-1),actingRobot.player);
988 
989  //Set self to self instead of ally
990  to_return[actingRobot.assoc_cell.x_coord][actingRobot.assoc_cell.y_coord].contents=Robot.GridObject.SELF;
991  return to_return;
992  }
993 
994  public void scanEnemy(Robot.Robot_Specs enemySpecs, Robot.Robot_Status enemyStatus, Robot.GridCell toScan) throws RoboSimExecutionException
995  {
996  if(enemySpecs==null || enemyStatus==null || toScan==null
997  || toScan.x_coord < 0 || toScan.x_coord >= worldGrid.length || toScan.y_coord < 0 || toScan.y_coord >= worldGrid[0].length || actingRobot.status.power==0)
998  throw new RoboSimExecutionException("Invalid parameters passed to scanEnemy()",actingRobot.player,actingRobot.assoc_cell);
999 
1000  SimGridCell cell = worldGrid[toScan.x_coord][toScan.y_coord];
1001 
1002  //Are we within range?
1003  if(Math.abs(actingRobot.assoc_cell.x_coord - cell.x_coord) > actingRobot.specs.defense || Math.abs(actingRobot.assoc_cell.y_coord - cell.y_coord) > actingRobot.specs.defense)
1004  throw new RoboSimExecutionException("attempted to scan farther than range", actingRobot.player, actingRobot.assoc_cell);
1005 
1006  //Is there a robot in this cell?
1007  if(cell.contents != Robot.GridObject.SELF)
1008  throw new RoboSimExecutionException("attempted to scan invalid cell (no robot in cell)", actingRobot.player, actingRobot.assoc_cell, cell);
1009 
1010  //Register cost
1011  actingRobot.status.power--;
1012  actingRobot.status.charge--;
1013 
1014  //Okay, we're good. Fill in the data.
1015  enemySpecs.attack = cell.occupant_data.specs.attack;
1016  enemySpecs.defense = cell.occupant_data.specs.defense;
1017  enemySpecs.power = cell.occupant_data.specs.power;
1018  enemySpecs.charge = cell.occupant_data.specs.charge;
1019  enemyStatus.power = cell.occupant_data.status.power;
1020  enemyStatus.charge = cell.occupant_data.status.charge;
1021  enemyStatus.health = cell.occupant_data.status.health;
1022  enemyStatus.defense_boost = cell.occupant_data.status.defense_boost;
1023  enemyStatus.capsules = cell.occupant_data.status.capsules.clone();
1024  }
1025  }
1026 
1032  {
1033  for(turnOrder_pos=0; turnOrder_pos<turnOrder.size(); turnOrder_pos++)
1034  {
1035  //References to robot's data
1036  RobotData data = turnOrder.get(turnOrder_pos);
1037  WorldAPI student_api = new RoboAPIImplementor(data);
1038 
1039  //Charge robot an amount of charge equal to charge skill
1040  data.status.charge = Math.min(data.status.charge + data.specs.charge, data.specs.charge*10);
1041 
1042  /*We can spend up to status.power power this turn, but
1043  *no more than our current charge level*/
1044  data.status.power = Math.min(data.specs.power, data.status.charge);
1045 
1046  //Defense boost reset to zero at beginning of turn
1047  data.status.defense_boost = 0;
1048 
1049  //Clone status for student
1050  Robot.Robot_Status clonedStatus;
1051  try
1052  {
1053  clonedStatus = (Robot.Robot_Status)(data.status.clone());
1054  }
1055  catch(CloneNotSupportedException e)
1056  {
1057  throw new RuntimeException("error cloning in executeSingleTimeStep. This is not the student's fault.");
1058  }
1059 
1060  //Run student code
1061  data.robot.act(student_api,clonedStatus,data.buffered_radio.toArray(new byte[0][]));
1062  }
1063 
1064  String player = turnOrder.get(0).player;
1065  for(int i=1; i<turnOrder.size(); i++)
1066  if(!turnOrder.get(i).player.equals(player))
1067  return null;
1068  return player;
1069  }
1070 }
RoboSimExecutionException(String message, String player, Robot.GridCell cell)
Definition: RoboSim.java:20
Robot.GridCell getBuildTarget()
Definition: RoboSim.java:743
void setBuildTarget(Robot.BuildStatus status, Robot.GridCell location, byte[] message)
Definition: RoboSim.java:838
void finalizeBuilding(byte[] creation_message)
Definition: RoboSim.java:753
void setBuildTarget(Robot.BuildStatus status, Robot.GridCell location)
Definition: RoboSim.java:833
Robot.AttackResult processAttack(int attack, SimGridCell cell_to_attack, int power)
Definition: RoboSim.java:323
void pick_up_capsule(Robot.GridCell adjacent_cell)
Definition: RoboSim.java:662
String getOccupantPlayer(Robot.GridCell to_convert)
Definition: RoboSim.java:104
ArrayList< RobotData > turnOrder
Definition: RoboSim.java:94
SimGridCell[][] getSubGrid(int x_left, int y_up, int x_right, int y_down)
Definition: RoboSim.java:119
SimGridCell[][] worldGrid
Definition: RoboSim.java:93
Robot.GridCell[][] getVisibleNeighborhood()
Definition: RoboSim.java:965
Definition: Robot.java:11
List< byte[]> buffered_radio
Definition: RoboSim.java:79
void sendMessage(byte[] message, int power)
Definition: RoboSim.java:937
RoboAPIImplementor(RobotData actingRobot_)
Definition: RoboSim.java:290
boolean validCell(Robot.GridCell potential_ally)
Definition: RoboSim.java:42
static Robot.Robot_Specs checkSpecsValid(Robot.Robot_Specs proposed, String player, int skill_points)
Definition: RoboSim.java:167
SimGridCell invested_assoc_cell
Definition: RoboSim.java:76
Robot.AttackResult meleeAttack(int power, Robot.GridCell adjacent_cell)
Definition: RoboSim.java:389
void repair(int power)
Definition: RoboSim.java:892
RobotData occupant_data
Definition: RoboSim.java:84
Robot.BuildStatus getBuildStatus()
Definition: RoboSim.java:738
Robot.AttackResult rangedAttack(int power, Robot.GridCell nonadjacent_cell)
Definition: RoboSim.java:448
final int WALL_HEALTH
Definition: RoboSim.java:89
Robot.AttackResult capsuleAttack(int power_of_capsule, Robot.GridCell cell)
Definition: RoboSim.java:511
void build(int power)
Definition: RoboSim.java:883
Robot.GridCell[][] getWorldGrid()
Definition: RoboSim.java:99
void charge(int power, Robot.GridCell ally)
Definition: RoboSim.java:905
void defend(int power)
Definition: RoboSim.java:582
void scanEnemy(Robot.Robot_Specs enemySpecs, Robot.Robot_Status enemyStatus, Robot.GridCell toScan)
Definition: RoboSim.java:994
boolean calculateHit(int attack, int defense)
Definition: RoboSim.java:311
Robot.Robot_Status status
Definition: RoboSim.java:69
SimGridCell assoc_cell
Definition: RoboSim.java:67
RoboSimExecutionException(String message, String player)
Definition: RoboSim.java:15
void move(int steps, Robot.Direction way)
Definition: RoboSim.java:593
boolean isAdjacent(Robot.GridCell adjacent_cell)
Definition: RoboSim.java:297
void drop_capsule(Robot.GridCell adjacent_cell, int power_of_capsule)
Definition: RoboSim.java:703
RoboSim(String[] combatants, int initial_robots_per_combatant, int skill_points, int length, int width, int obstacles)
Definition: RoboSim.java:185
SimGridAllyDeterminant(Robot.GridCell origin_)
Definition: RoboSim.java:40
int turnOrder_pos
Definition: RoboSim.java:95
static Robot.GridCell[][] sanitizeGrid(SimGridCell[][] simgrid, String player)
Definition: RoboSim.java:139
GridObject contents
Definition: Robot.java:89
final int WALL_DEFENSE
Definition: RoboSim.java:90
RoboSimExecutionException(String message, String player_, int x1, int y1, int x2, int y2)
Definition: RoboSim.java:30
Robot.GridCell[][] getWorld(int power)
Definition: RoboSim.java:982
Robot.BuildStatus whatBuilding
Definition: RoboSim.java:74
SimulatorGUI gui
Definition: RoboSim.java:96
Robot.Robot_Specs specs
Definition: RoboSim.java:68
String executeSingleTimeStep()
Definition: RoboSim.java:1031
RoboSimExecutionException(String message, String player, Robot.GridCell cell, Robot.GridCell cell2)
Definition: RoboSim.java:25
Robot_Specs createRobot(WorldAPI api, int skill_points, byte[] message)