001    package model.fish;
002    
003    import model.fish.display.ImageFishDisplay;
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    /**
013     * A fish that moves like a knight in chess.
014     *
015     * @author Mathias Ricken
016     */
017    public class KnightFish extends AFish {
018        /**
019         * Make a new knight fish.
020         *
021         * @param fishColor color of the fish
022         */
023        public KnightFish(Color fishColor) {
024            super(fishColor, new ImageFishDisplay("knight.gif", 0));
025        }
026    
027        /**
028         * Carry out movement behavior for the fish.
029         */
030        protected void move() {
031            int target = RandNumGenerator.instance().nextInt(8);
032            int turns = target / 2; // number of 90 degree turns
033            turnRight(turns * Math.PI / 2.0);
034            final boolean oneOverToLeft = (0 == (target % 2)); // true if the "one over" step goes to the left, false if to the right
035    
036            // try to make the first step forward
037            tryMoveFwd(new IBlockedCommand() {
038                public Object apply(Object param) {
039                    // if blocked, do nothing
040                    return null;
041                }
042            }, new IOpenCommand() {
043                public Object apply(Object param) {
044                    // if open, move
045                    ((ILambda)param).apply(null);
046    
047                    // try to make the second step forward
048                    return tryMoveFwd(new IBlockedCommand() {
049                        public Object apply(Object param) {
050                            // if blocked, do nothing
051                            return null;
052                        }
053                    }, new IOpenCommand() {
054                        public Object apply(Object param) {
055                            // if open, move
056                            ((ILambda)param).apply(null);
057    
058                            // if over to the left...
059                            if (oneOverToLeft) {
060                                // ...turn left
061                                turnLeft();
062                            }
063                            else {
064                                // ...else turn right
065                                turnRight();
066                            }
067    
068                            // try to make the step over
069                            return tryMoveFwd(new IBlockedCommand() {
070                                public Object apply(Object param) {
071                                    // if blocked, do nothing
072                                    return null;
073                                }
074                            }, new IOpenCommand() {
075                                public Object apply(Object param) {
076                                    // if open, move
077                                    ((ILambda)param).apply(null);
078    
079                                    return null;
080                                }
081                            });
082                        }
083                    });
084                }
085            });
086        }
087    }