001    package model.fish;
002    
003    import model.fish.display.RoundFishDisplay;
004    import model.RandNumGenerator;
005    import model.ILambda;
006    import sysModel.fish.AFish;
007    import sysModel.env.IBlockedCommand;
008    import sysModel.env.IOpenCommand;
009    
010    import java.awt.*;
011    
012    import lrs.LRStruct;
013    import lrs.visitor.GetLength;
014    import lrs.visitor.GetNth;
015    
016    /**
017     * Class for a generic fish.
018     *
019     * @author Mathias G. Ricken
020     */
021    public class GenericFish extends AFish {
022        /**
023         * Create a new generic fish.
024         *
025         * @param fishColor color of the fish
026         */
027        public GenericFish(Color fishColor) {
028            super(fishColor, RoundFishDisplay.Singleton);
029        }
030    
031        /**
032         * Carry out movement behavior for the fish.
033         */
034        protected void move() {
035            final LRStruct moveLambdas = new LRStruct();
036    
037            // turn PI/2 radians to the left and attempt to move forward
038            turnLeft();
039    
040            final IBlockedCommand blocked3 = new IBlockedCommand() {
041                public Object apply(Object param) {
042                    int size = ((Integer)moveLambdas.execute(GetLength.Singleton, null)).intValue();
043    
044                    if (0 != size) {
045                        // pick random move command
046                        Integer randnum = new Integer(RandNumGenerator.instance().nextInt(size));
047                        ILambda cmd = (ILambda)moveLambdas.execute(GetNth.Singleton, randnum);
048    
049                        // apply that command
050                        cmd.apply(null);
051                    }
052                    else {
053                        // turn back PI/2 radians to the left
054                        turnLeft();
055                    }
056                    return null;
057                }
058            };
059    
060            final IBlockedCommand blocked2 = new IBlockedCommand() {
061                public Object apply(Object param) {
062                    // turn PI/2 radians to the right and attempt to move forward
063                    turnRight();
064                    return tryMoveFwd(blocked3,
065                        new IOpenCommand() {
066                            public Object apply(Object param) {
067                                // the field to the right is open
068                                moveLambdas.insertFront(param);
069                                return blocked3.apply(null);
070                            }
071                        });
072                }
073            };
074    
075            final IBlockedCommand blocked1 = new IBlockedCommand() {
076                public Object apply(Object param) {
077                    // turn PI/2 radians to the right and attempt to move forward
078                    turnRight();
079                    return tryMoveFwd(blocked2,
080                        new IOpenCommand() {
081                            public Object apply(Object param) {
082                                // the field straight ahead is open
083                                moveLambdas.insertFront(param);
084                                return blocked2.apply(null);
085                            }
086                        });
087                }
088            };
089    
090    
091            tryMoveFwd(blocked1,
092                new IOpenCommand() {
093                    public Object apply(Object param) {
094                        // the field to the left is open
095                        moveLambdas.insertFront(param);
096                        return blocked1.apply(null);
097                    }
098                });
099        }
100    }