2-APL UPC project.
1 package blockworld;
2
3/*
4 3APL Blockworld program by Jelle Herold, copyright 2003.
5 Written for the Intelligent Systems group at Utrecht University.
6 This is LGPL software.
7
8 $Id: Env.java,v 1.7 2004/12/27 02:22:41 cvs-3apl Exp $
9 */
10
11// 2APL imports
12import apapl.Environment;
13import apapl.ExternalActionFailedException;
14import apapl.data.*;
15
16// Standard java imports
17import java.awt.Point;
18import java.util.Collection;
19import java.util.Iterator;
20import java.util.List;
21import java.util.Vector;
22import java.util.LinkedList;
23import javax.swing.SwingUtilities;
24import java.awt.Dimension;
25import java.util.ArrayList;
26import java.util.HashMap;
27
28import java.io.IOException;
29import java.io.InputStream;
30import java.io.ObjectInputStream;
31import java.io.ObjectOutputStream;
32import java.io.OutputStream;
33
34import blockworld.lib.ObsVectListener;
35import blockworld.lib.Signal;
36import blockworld.lib.ObsVect;
37
38public class Env extends Environment implements ObsVectListener
39{
40 // To hold our reference to the window
41 final protected Window m_window;
42
43 // max distance of cells visible to each agent
44 protected int _senserange = 5;
45
46 // size of environment
47 protected Dimension m_size = new Dimension( 16, 16 );
48
49 private HashMap<String,Agent> agentmap = new HashMap<String,Agent>();
50
51 /* ---- ALL the stuff in the environment -----*/
52
53 // list of agents (Agent)
54 protected ObsVect _agents = new ObsVect( this );
55 // location of bomb traps
56 protected ObsVect _traps = new ObsVect();
57 // list of coordinates (Point) containing stones
58 protected ObsVect _stones = new ObsVect();
59 // list of coordinates (Point) containing bombs
60 protected ObsVect _bombs = new ObsVect();
61 // id for identifiable objects
62 protected String _objType = "default";
63
64 /* ------------------------------------------*/
65
66
67 /* ---- SIGNALS -------------------------------*/
68 // / emitted on collection of a bomb in the bomb trap
69 public transient Signal signalBombTrapped = new Signal( "env bomb trapped" );
70
71 public transient Signal signalSenseRangeChanged = new Signal(
72 "env sense range changed" );
73
74 // emitted if environment is resized
75 public transient Signal signalSizeChanged = new Signal( "env size changed" );
76
77 // emitted if bomb traps location changed
78 public transient Signal signalTrapChanged = new Signal(
79 "env trap position changed" );
80
81 /* ------------------------------------------*/
82
83
84 // The default constructor
85 public Env()
86 {
87 super();
88 // Create the window
89 m_window = new Window( this );
90 }
91
92 /* Called from 2APL */
93
94 // Enter the agent into the world
95 // Succesful returns true, else the ExternalActionFailedException exception is thrown
96 public Term enter( String sAgent, APLNum xt, APLNum yt, APLIdent colort) throws ExternalActionFailedException
97 {
98 int x = xt.toInt();
99 int y = yt.toInt();
100 String color = colort.toString();
101
102 // Get the agent
103 Agent agent = getAgent(sAgent);
104
105 // Give a signal that we want to move
106 agent.signalMove.emit();
107
108 writeToLog( "Agent entered: " +agent.getName());
109
110 Point position = new Point(x,y);
111 String pos = "("+x+","+y+")";
112
113 // Agent already entered
114 if( agent.isEntered() )
115 {
116 writeToLog( "agent already entered" );
117 throw new ExternalActionFailedException("Agent \""+agent.getName()+"\" has already entered.");
118 }
119
120 // Is this position within the world?
121 if (isOutOfBounds(position))
122 {
123 throw new ExternalActionFailedException("Position "+pos+" out of bounds.");
124 }
125 // Is this position free?
126 if( !isFree( position ) )
127 {
128 throw new ExternalActionFailedException("Position "+pos+" is not free.");
129 }
130
131 // Update the agent his position
132 agent._position = position;
133
134 // Which color does the agent want to be
135 int nColorID = getColorID(color);
136 agent._colorID = nColorID;
137
138 // Redraw so we can see the agent
139 validatewindow();
140 m_window.repaint();
141
142 // We came so far, this means success!
143 agent.signalMoveSucces.emit();
144
145 return wrapBoolean(true);
146 }
147
148 // Move the agent north
149 public Term north(String sAgent) throws ExternalActionFailedException
150 {
151 // Get the correct agent
152 Agent agent = getAgent(sAgent);
153
154 // Get the agent his position
155 Point p = (Point) agent.getPosition().clone();
156 p.y = p.y - 1;
157
158 // Set the position for the agent
159 boolean r = setAgentPosition( agent, p);
160
161 // can't move north
162 if (!r) throw new ExternalActionFailedException("Moving north failed.");
163
164 // Redraw the window
165 validatewindow();
166 m_window.repaint();
167 return wrapBoolean(r);
168 }
169
170 // Move the agent east
171 public Term east(String sAgent) throws ExternalActionFailedException
172 {
173 // Get the correct agent
174 Agent agent = getAgent(sAgent);
175
176 // Get the agent his position
177 Point p = (Point) agent.getPosition().clone();
178 p.x = p.x + 1;
179
180 // Set the position for the agent
181 boolean r = setAgentPosition( agent, p);
182
183 // can't move north
184 if (!r) throw new ExternalActionFailedException("Moving north failed.");
185
186 // Redraw the window
187 validatewindow();
188 m_window.repaint();
189 return wrapBoolean(r);
190 }
191
192 // Move the agent south
193 public Term south(String sAgent) throws ExternalActionFailedException
194 {
195 // Get the correct agent
196 Agent agent = getAgent(sAgent);
197
198 // Get the agent his position
199 Point p = (Point) agent.getPosition().clone();
200 p.y = p.y + 1;
201
202 // Set the position for the agent
203 boolean r = setAgentPosition( agent, p);
204
205 // can't move north
206 if (!r) throw new ExternalActionFailedException("Moving north failed.");
207
208 // Redraw the window
209 validatewindow();
210 m_window.repaint();
211 return wrapBoolean(r);
212 }
213
214 // Move the agent west
215 public Term west(String sAgent) throws ExternalActionFailedException
216 {
217 // Get the correct agent
218 Agent agent = getAgent(sAgent);
219
220 // Get the agent his position
221 Point p = (Point) agent.getPosition().clone();
222 p.x = p.x - 1;
223
224 // Set the position for the agent
225 boolean r = setAgentPosition( agent, p);
226
227 // can't move north
228 if (!r) throw new ExternalActionFailedException("Moving north failed.");
229
230 // Redraw the window
231 validatewindow();
232 m_window.repaint();
233 return wrapBoolean(r);
234 }
235
236 // Pickup a bomb
237 public Term pickup( String sAgent ) throws ExternalActionFailedException
238 {
239 // Get the agent
240 Agent agent = getAgent(sAgent);
241
242 // Let everyone know we are going to pick up a bomb
243 agent.signalPickupBomb.emit();
244
245 // see if we are not already carrying a bomb
246 if( agent.atCapacity() )
247 {
248 writeToLog( "Pickup bomb failed" );
249 throw new ExternalActionFailedException("Pickup bomb failed");
250 }
251
252 // we are not already carying a bomb so get this one
253 TypeObject bomb = removeBomb( agent.getPosition() );
254 if( bomb == null )
255 {
256 writeToLog( "Pickup bomb failed" );
257 throw new ExternalActionFailedException("Pickup bomb failed");
258 }
259
260 // Yes
261 agent.signalPickupBombSucces.emit();
262
263 // there was a bomb at that position, so set token
264 agent.pickBomb(bomb);
265
266 // show what happened
267 validatewindow();
268 m_window.repaint();
269
270 return wrapBoolean(true);
271 }
272
273 // Drop a bomb
274 public Term drop( String sAgent ) throws ExternalActionFailedException
275 {
276 // Get the agent
277 Agent agent = getAgent(sAgent);
278 // we are going to drop a bomb
279 agent.signalDropBomb.emit();
280
281 TypeObject bomb = agent.senseBomb();
282 // see if we are actually carrying a bomb
283 if( bomb == null)
284 {
285 writeToLog( "Drop bomb failed" );
286 throw new ExternalActionFailedException("Drop bomb failed");
287 }
288
289 Point pos = agent.getPosition();
290 // see if we can drop that bomb here
291
292 if( !addBomb(pos) && (isTrap( pos ) == null
293 || agent.senseBomb( isTrap( pos ).getType() ) == null) )
294 {
295 writeToLog( "Drop bomb failed" );
296 throw new ExternalActionFailedException("Drop bomb failed");
297 }
298
299 if(isTrap( pos ) != null
300 && agent.senseBomb( isTrap( pos ).getType() ) != null)
301 {
302 signalBombTrapped.emit();
303 }
304
305 // unset token
306 agent.dropBomb();
307
308 agent.signalDropBombSucces.emit();
309
310 // Show it
311 validatewindow();
312 m_window.repaint();
313
314 // return success
315 return wrapBoolean(true);
316 }
317
318 // What is the agent his Sense Range
319 public Term getSenseRange(String agent)
320 {
321 // the below function is also used by EnvView
322 int r = getSenseRange();
323 return new APLList(new APLNum(r));
324 }
325
326 // Sense all agents. This does not include self.
327 public synchronized Term senseAllAgent(String sAgent) throws ExternalActionFailedException
328 {
329 //Collection c = senseAllAgents(getAgent(agent).getPosition());
330 Point position = getAgent(sAgent).getPosition();
331 // iterate over all agents
332 Vector all = new Vector();
333
334 Iterator j = _agents.iterator();
335 while( j.hasNext() ) {
336 Agent agent = (Agent) j.next();
337 Point p = agent.getPosition();
338
339 // Changed SA: when there are no other agents, this return null, which
340 // causes Java to throw an exception and never return the empty list.
341 if (p == null)
342 continue;
343
344 // skip self
345 if( p.equals( position ) )
346 continue;
347
348 all.add( agent );
349 }
350
351 LinkedList<Term> listpar = new LinkedList<Term>();
352 for(Object i : all) {
353 final Agent a = (Agent) i;
354 APLListVar tmp = new APLList(new APLIdent(a.getName()),new APLNum(a.getPosition().x),new APLNum(a.getPosition().y));
355 listpar.add(tmp);
356 }
357 return new APLList(listpar);
358 }
359
360 // Sense the given agent his position
361 public synchronized Term sensePosition(String sAgent) throws ExternalActionFailedException
362 {
363 Point p = getAgent(sAgent).getPosition();
364 return new APLList(new APLNum(p.x),new APLNum(p.y));
365 }
366
367 // is there a trap in the senserange of the agent?
368 public synchronized Term senseTraps(String agent) throws ExternalActionFailedException
369 {
370 // Get the agent his position
371 Point position = getAgent(agent).getPosition();
372
373 // iterate over all traps and decide according to distance if it is in
374 // vision range
375 Vector visible = new Vector();
376
377 Iterator i = _traps.iterator();
378 while( i.hasNext() ) {
379 TypeObject t = (TypeObject) i.next();
380 if( position.distance( t.getPosition() ) <= _senserange )
381 visible.add( t );
382 }
383
384 return convertCollectionToTerm(visible);
385 }
386
387 // Get all the traps in the env
388 public synchronized Term senseAllTraps(String agent)
389 {
390 // iterate over all traps
391 Vector all = new Vector();
392
393 Iterator i = _traps.iterator();
394 while( i.hasNext() )
395 {
396 all.add( (TypeObject) i.next() );
397 }
398
399 return convertCollectionToTerm(all);
400 }
401
402 // Sends a bom in the senserange of the agent
403 public synchronized Term senseBombs(String agent) throws ExternalActionFailedException
404 {
405 // Get the agent his position
406 Point position = getAgent(agent).getPosition();
407
408 // iterate over all bombs and decide according to distance if it is in
409 // vision range
410 Vector visible = new Vector();
411
412 Iterator i = _bombs.iterator();
413 while( i.hasNext() )
414 {
415 TypeObject b = (TypeObject) i.next();
416 if( position.distance( b.getPosition() ) <= _senserange )
417 visible.add( b );
418 }
419
420 return convertCollectionToTerm(visible);
421 }
422
423 // Find all the bombs in the environment
424 public synchronized Term senseAllBombs (String agent)
425 {
426 // iterate over all bombs
427 Vector all = new Vector();
428
429 Iterator i = _bombs.iterator();
430 while( i.hasNext() )
431 {
432 all.add( (TypeObject) i.next() );
433 }
434
435 return convertCollectionToTerm(all);
436 }
437
438 // Sense the stones in the agent senserange
439 public synchronized Term senseStones(String agent) throws ExternalActionFailedException
440 {
441 // Get the agent his position
442 Point position = getAgent(agent).getPosition();
443
444 // iterate over all stones and decide according to distance if it is in
445 // vision range
446 Vector visible = new Vector();
447
448 Iterator i = _stones.iterator();
449 while( i.hasNext() )
450 {
451 TypeObject t = (TypeObject) i.next();
452 if( position.distance( t.getPosition() ) <= _senserange )
453 visible.add( t );
454 }
455
456 return convertCollectionToTerm(visible);
457 }
458
459 // Sense all stones
460 public synchronized Term senseAllStones (String agent)
461 {
462 // iterate over all traps
463 Vector all = new Vector();
464
465 Iterator i = _stones.iterator();
466 while( i.hasNext() )
467 {
468 all.add( (TypeObject) i.next() );
469 }
470
471 return convertCollectionToTerm(all);
472 }
473
474 // Sense visible area for agents. This does not include self.
475 public synchronized Term senseAgent(String sAgent) throws ExternalActionFailedException
476 {
477 //Collection c = senseAgents(getAgent(agent).getPosition());
478 Point position = getAgent(sAgent).getPosition();
479
480 // iterate over all agents and decide according to distance if it is in
481 // vision range
482 Vector visible = new Vector();
483
484 Iterator j = _agents.iterator();
485
486 while( j.hasNext() )
487 {
488 Agent agent = (Agent) j.next();
489
490 Point p = agent.getPosition();
491
492 // Changed SA: when there are no other agents, this return null, which
493 // causes Java to throw an exception and never return the empty list.
494 if (p == null)
495 continue;
496
497 // skip self
498 if( p.equals( position ) )
499 continue;
500
501 // agent within visible range
502 if( position.distance( p ) <= _senserange )
503 visible.add( agent );
504 }
505
506 LinkedList<Term> listpar = new LinkedList<Term>();
507 for(Object i : visible) {
508 final Agent a = (Agent) i;
509 APLListVar tmp = new APLList(new APLIdent(a.getName()),new APLNum(a.getPosition().x),new APLNum(a.getPosition().y));
510 listpar.add(tmp);
511 }
512 return new APLList(listpar);
513 }
514
515
516
517 /* Standard functions --------------------------------------*/
518
519 private void notifyAgents(APLFunction event, String... receivers) {
520 throwEvent(event, receivers);
521 }
522
523 private void notifyEvent(String parm1, Point ptPosition)
524 {
525 APLNum nX = new APLNum((double)(ptPosition.getX()));
526 APLNum nY = new APLNum((double)(ptPosition.getY()));
527
528 // Send an external event to all agents within the senserange.
529 ArrayList<String> targetAgents = new ArrayList<String>();
530 for (Agent a : agentmap.values())
531 {
532 // Changed SA: I got no idea why there is always 1 agent which does not exists,
533 // but this fixes the exceptions
534 if ((a.getPosition() != null) && (ptPosition.distance(a.getPosition()) <= getSenseRange()))
535 targetAgents.add(a.getName());
536 }
537
538 writeToLog("EVENT: "+parm1+"("+nX+","+nY+")"+" to "+targetAgents);
539
540 if (!targetAgents.isEmpty())
541 {
542 notifyAgents(new APLFunction(parm1,nX,nY),targetAgents.toArray(new String[0]));
543 }
544 }
545
546 // Add an agent to the environment
547 public synchronized void addAgent(String sAgent) {
548 String sAgentMain = getMainModule(sAgent);
549 // Agent not yet in the environment
550 if (agentmap.keySet().contains(sAgentMain)) {
551 agentmap.put(sAgent,agentmap.get(sAgentMain));
552 writeToLog("linking " + sAgent + "");
553 } else{
554 final Agent agent = new Agent(sAgentMain);
555 _agents.add(agent);
556 agentmap.put(sAgent, agent);
557 writeToLog("agent " + agent + " added");
558 }
559 }
560
561 // Remove the agent from the environment
562 public synchronized void removeAgent(String sAgent)
563 {
564 try
565 {
566 //String sAgentMain = getMainModule(sAgent);
567
568 Agent a = getAgent(sAgent);
569 agentmap.remove( sAgent );
570
571 // there can be several agent
572 if (!agentmap.containsValue(a)) {
573 _agents.remove(a);
574 a.reset();
575 }
576
577 writeToLog("Agent removed: " + sAgent);
578
579 synchronized( this )
580 {
581 notifyAll();
582 }
583 }
584 catch (ExternalActionFailedException e) {}
585 }
586
587 /* END Standard functions --------------------------------------*/
588
589
590
591
592 /* Helper functions --------------------------------------*/
593
594 // Get the size of the blockworld
595 public synchronized Term getWorldSize(String agent)
596 {
597 int w = getWidth();
598 int h = getHeight();
599 return new APLList(new APLNum(w),new APLNum(h));
600 }
601
602 // Get the agent from its name
603 private synchronized Agent getAgent(String name) throws ExternalActionFailedException
604 {
605 Agent a = null;
606 //a = agentmap.get(getMainModule(name));
607 a = agentmap.get(name);
608 if (a==null) throw new ExternalActionFailedException("No such agent: "+name);
609 else return a;
610
611 }
612
613 private static String getMainModule(String sAgent)
614 {
615 int dotPos;
616 if ((dotPos = sAgent.indexOf('.')) == -1)
617 return sAgent;
618 else
619 return sAgent.substring(0, dotPos);
620 }
621
622 // Get the environment width
623 public synchronized int getWidth() { return m_size.width; }
624
625 // Get the environment height
626 public synchronized int getHeight() { return m_size.height; }
627
628 // Return the agents
629 public synchronized Collection getBlockWorldAgents()
630 {
631 return new Vector(_agents);
632 }
633
634 // convert a collection to a term
635 private static Term convertCollectionToTerm(Collection c)
636 {
637 LinkedList<Term> listpar = new LinkedList<Term>();
638 for(Object i : c) {
639 final TypeObject o = (TypeObject) i;
640 APLListVar tmp = new APLList(new APLIdent(o.getType()),new APLNum(o.getPosition().x),new APLNum(o.getPosition().y));
641 listpar.add(tmp);
642 }
643 return new APLList(listpar);
644 }
645
646 // Get senserange
647 public int getSenseRange()
648 {
649 return _senserange;
650 }
651
652 // Redrawing the window is a nightmare, this does some redraw stuff
653 private void validatewindow()
654 {
655 Runnable repaint = new Runnable()
656 {
657 public void run()
658 {
659 //try {Thread.sleep(500);} catch(Exception e) {}
660 m_window.doLayout();
661
662 /*if (!m_window.isVisible())
663 {
664 m_window.setVisible( true );
665 }*/
666 }
667 };
668 SwingUtilities.invokeLater(repaint);
669 }
670
671 // Move the agent
672 private synchronized boolean setAgentPosition( Agent agent, Point position)
673 {
674 agent.signalMove.emit();
675
676 if( isOutOfBounds( position ) )
677 return false;
678
679 // suspend thread if some other agent is blocking our entrance
680
681 // Is the position free?
682 if( !isFree( position ) )
683 return false;
684
685 agent.signalMoveSucces.emit();
686
687 // there may be other threads blocked because this agent was in the way,
688 // notify
689 // them of the changed state of environment
690 synchronized( this )
691 {
692 notifyAll();
693 }
694
695 // set the agent position
696 agent._position = position;
697 return true;
698 }
699
700 // check if point is within environment boundaries
701 // return false is p is within bounds
702 protected boolean isOutOfBounds( Point p )
703 {
704 if( (p.x >= m_size.getWidth()) || (p.x < 0) || (p.y >= m_size.getHeight()) || (p.y < 0) )
705 {
706 return true;
707 }
708
709 return false;
710 }
711
712 // Is the position free?
713 public synchronized boolean isFree( final Point position )
714 {
715 return (isStone( position )) == null && (isAgent( position ) == null);
716 }
717
718 // Check for agent at coordinate. \return Null if there is no agent at the
719 // specified coordinate. Otherwise return a reference to the agent there.
720 public synchronized Agent isAgent( final Point p )
721 {
722 synchronized (_agents) {
723 Iterator i = _agents.iterator();
724 while( i.hasNext() ) {
725 final Agent agent = (Agent) i.next();
726 if( p.equals( agent.getPosition() ) )
727 return agent;
728 }
729 return null;
730 }
731 }
732
733 // Is there a stone at this point
734 public synchronized TypeObject isStone( Point p )
735 {
736 synchronized (_agents) {
737 Iterator i = _stones.iterator();
738 while( i.hasNext() ) {
739 TypeObject stones = (TypeObject) i.next();
740 if( p.equals( stones.getPosition() ) )
741 return stones;
742 }
743 return null;
744 }
745 }
746
747 // see if there is a trap at the specified coordinate
748 public synchronized TypeObject isTrap( Point p ) {
749 synchronized (_traps) {
750 Iterator i = _traps.iterator();
751 while( i.hasNext() ) {
752 TypeObject trap = (TypeObject) i.next();
753 if( p.equals( trap.getPosition() ) )
754 return trap;
755 }
756 return null;
757 }
758 }
759
760 public synchronized TypeObject isBomb( Point p )
761 {
762 synchronized (_bombs) {
763 Iterator i = _bombs.iterator();
764 while( i.hasNext() ) {
765 TypeObject bomb = (TypeObject)i.next();
766 if(p.equals(bomb.getPosition()))
767 return bomb;
768 }
769 return null;
770 }
771 }
772
773 // Remove bomb at position TODO Jaap; why is this different then remove stone???
774 public synchronized TypeObject removeBomb( Point position )
775 {
776 // find bomb in bombs list
777 synchronized(this) {
778 Iterator i = _bombs.iterator();
779 while (i.hasNext())
780 {
781 TypeObject bomb = (TypeObject) i.next();
782 if (position.equals(bomb.getPosition()))
783 {
784 i.remove();
785 return bomb;
786 }
787 }
788 }
789
790 notifyEvent("bombRemovedAt", position);
791 return null;
792
793 }
794
795 // remove stone at position
796 public synchronized boolean removeStone( Point position )
797 {
798 synchronized(_stones) {
799 // find stone in stones list
800 Iterator i = _stones.iterator();
801 while (i.hasNext())
802 //if( position.equals( i.next() ) ) {
803 // Changed SA:
804 if (position.equals(((TypeObject)i.next()).getPosition()))
805 {
806 i.remove();
807
808 // there may be other threads blocked because this agent was in
809 // the way, notify
810 // them of the changed state of environment
811 synchronized( this )
812 {
813 notifyAll();
814 }
815
816 return true;
817 }
818 }
819 notifyEvent("wallRemovedAt", position);
820 return false;
821 }
822
823 // remove trap at position
824 public synchronized boolean removeTrap( Point position )
825 {
826 synchronized(_traps) {
827 // find trap in traps list
828 Iterator i = _traps.iterator();
829 while (i.hasNext()) {
830 if (position.equals(((TypeObject)i.next()).getPosition()))
831 {
832 i.remove();
833
834
835 // Sohan: I believe this notification is unnecessary, commented it out:
836 //synchronized( this ) {
837 // notifyAll();
838 //}
839
840 return true;
841 }
842 }
843 }
844
845 notifyEvent("trapRemovedAt", position);
846 return false;
847 }
848
849 // Add a stone at the given position
850 public synchronized boolean addStone( Point position ) throws IndexOutOfBoundsException
851 {
852 // valid coordinate
853 if( isOutOfBounds( position ) )
854 throw new IndexOutOfBoundsException( "setStone out of range: "
855 + position + ", " + m_size );
856
857 // is position clear of other stuff
858 // Changed SA:
859 if( isBomb( position ) != null || isStone( position ) != null || isTrap( position ) != null )
860 return false;
861
862 synchronized (_stones) {
863 _stones.add( new TypeObject(_objType,position) );
864 }
865 notifyEvent("wallAt", position);
866
867 return true;
868 }
869
870 // Add a bomb to the environment
871 public synchronized boolean addBomb( Point position ) throws IndexOutOfBoundsException
872 {
873 if( isOutOfBounds( position ) )
874 throw new IndexOutOfBoundsException( "addBomb outOfBounds: "
875 + position + ", " + m_size );
876
877 // is position clear of other stuff
878 if( isBomb( position ) != null || isStone( position ) != null || isTrap( position ) != null )
879 return false;
880
881 // all clear, accept bomb
882 synchronized (_bombs) {
883 _bombs.add( new TypeObject(_objType,position) );
884 }
885 notifyEvent("bombAt", position);
886
887 return true;
888 }
889
890 // Add a trap at the given position
891 public synchronized boolean addTrap( Point position ) throws IndexOutOfBoundsException {
892 // valid coordinate
893 if( isOutOfBounds( position ) )
894 throw new IndexOutOfBoundsException( "setTrap out of range: "
895 + position + ", " + m_size );
896
897 // is position clear of other stuff
898 // Changed SA:
899 if( isBomb( position ) != null || isStone( position ) != null || isTrap( position ) != null )
900 return false;
901 synchronized(_traps) {
902 _traps.add( new TypeObject(_objType,position) );
903 }
904 notifyEvent("trapAt", position);
905
906 return true;
907 }
908
909 // Print a message to the console
910 static public void writeToLog(String message) {
911 //System.out.println("blockworld: " + message);
912 }
913
914 // helper function to wrap a boolean value inside a ListPar.
915 static public APLListVar wrapBoolean( boolean b )
916 {
917 return new APLList(new APLIdent(b ? "true" : "false"));
918 }
919
920 // Which color does the agent want to be!
921 private int getColorID(String sColor)
922 {
923 if (sColor.equals("army") )
924 {
925 return 0;
926 }
927 else if (sColor.equals("blue") )
928 {
929 return 1;
930 }
931 else if (sColor.equals("gray") )
932 {
933 return 2;
934 }
935 else if (sColor.equals("green") )
936 {
937 return 3;
938 }
939 else if (sColor.equals("orange") )
940 {
941 return 4;
942 }
943 else if (sColor.equals("pink") )
944 {
945 return 5;
946 }
947 else if (sColor.equals("purple") )
948 {
949 return 6;
950 }
951 else if (sColor.equals("red") )
952 {
953 return 7;
954 }
955 else if (sColor.equals("teal") )
956 {
957 return 8;
958 }
959 else if (sColor.equals("yellow") )
960 {
961 return 9;
962 }
963
964 // Red is the default
965 return 7;
966 }
967
968 // Set the senserange
969 public void setSenseRange( int senserange )
970 {
971 _senserange = senserange;
972 signalSenseRangeChanged.emit();
973 }
974
975 // helper function, calls setSize(Dimension)
976 public void setSize( int width, int height )
977 {
978 setSize( new Dimension( width, height ) );
979 }
980
981 // resize world
982 public void setSize( Dimension size )
983 {
984 m_size = size;
985 signalSizeChanged.emit();
986
987 Iterator i = _bombs.iterator();
988 while( i.hasNext() ) {
989 if( isOutOfBounds( ((TypeObject) i.next()).getPosition() ) )
990 i.remove();
991 }
992 i = _stones.iterator();
993 while( i.hasNext() ) {
994 if( isOutOfBounds( (Point) i.next() ) )
995 i.remove();
996 }
997 i = _traps.iterator();
998 while( i.hasNext() ) {
999 if( isOutOfBounds( ((TypeObject) i.next()).getPosition() ) )
1000 i.remove();
1001 }
1002 }
1003
1004 // what kind of object is it, bomb, stone, wall ?
1005 public String getObjType()
1006 {
1007 return _objType;
1008 }
1009
1010 // what kind of object is it, bomb, stone, wall ?
1011 public void setObjType(String objType)
1012 {
1013 _objType = objType;
1014 }
1015
1016 // Remove everything
1017 public void clear()
1018 {
1019 _stones.removeAllElements();
1020 _bombs.removeAllElements();
1021 _traps.removeAllElements();
1022 }
1023
1024 // Save the environment
1025 public void save( OutputStream destination ) throws IOException
1026 {
1027 ObjectOutputStream stream = new ObjectOutputStream( destination );
1028 stream.writeObject( m_size );
1029
1030 stream.writeInt( _senserange );
1031
1032 stream.writeObject( (Vector) _stones );
1033 stream.writeObject( (Vector) _bombs );
1034 stream.writeObject( (Vector) _traps );
1035 stream.flush();
1036 }
1037
1038 // Load the environment
1039 public void load( InputStream source ) throws IOException, ClassNotFoundException
1040 {
1041 ObjectInputStream stream = new ObjectInputStream( source );
1042 Dimension size = (Dimension) stream.readObject();
1043
1044 int senserange = stream.readInt();
1045
1046 Vector stones = (Vector) stream.readObject();
1047 Vector bombs = (Vector) stream.readObject();
1048 Vector traps = (Vector) stream.readObject();
1049
1050 // delay assignments until complete load is succesfull
1051 m_size = size;
1052 _senserange = senserange;
1053
1054 signalSizeChanged.emit();
1055 signalTrapChanged.emit();
1056 signalSenseRangeChanged.emit();
1057
1058 clear();
1059
1060 _stones.addAll( stones );
1061 _bombs.addAll( bombs );
1062 _traps.addAll( traps );
1063 }
1064
1065 /* END Helper functions --------------------------------------*/
1066
1067 /* Listeners ------------------------------------------------*/
1068
1069 // / This listener is notified upon changes regarding the Agent list.
1070 // / Please note that this only involves registering new agents or
1071 // / removing existing agents. To track agent position changes, add
1072 // / a listener to that specific agent.
1073 // / \sa Agent
1074 public void addAgentListener( ObsVectListener o )
1075 {
1076 _agents.addListener( o );
1077 }
1078
1079 // / This listener is notified upon changes regarding the Stones list.
1080 public void addStonesListener( ObsVectListener o )
1081 {
1082 _stones.addListener( o );
1083 }
1084
1085 // / This listener is notified upon changes regarding the Bombs list.
1086 public void addBombsListener( ObsVectListener o )
1087 {
1088 _bombs.addListener( o );
1089 }
1090
1091 // / This listener is notified upon changes regarding the Traps list.
1092 public void addTrapsListener( ObsVectListener o )
1093 {
1094 _traps.addListener( o );
1095 }
1096
1097 /* END Liseteners ------------------------------------------*/
1098
1099
1100 /* Overrides for ObsVector ---------------------------------*/
1101
1102 public void onAdd( int index, Object o ) {}
1103
1104 public void onRemove( int index, Object o )
1105 {
1106 ((Agent) o).deleteObservers();
1107 }
1108
1109 /* END Overrides for ObsVector ---------------------------------*/
1110}