/*
 * $Id$
 *
 * Copyright © 2003 Keith Packard
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Keith Packard not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Keith Packard makes no
 * representations about the suitability of this software for any purpose.  It
 * is provided "as is" without express or implied warranty.
 *
 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

namespace RR {
    public typedef enum { Red, Yellow, Green, Blue, Whirl } Color;
    public typedef enum { Triangle, Square, Octagon, Circle, Whirl } Shape;
    public typedef enum { North, East, South, West } Direction;

    public const int	Width = 16;
    public const int	Height = 16;
    public const int	Port = 5252;

    public typedef struct {
        Color   color;
        bool    active;
    } Robot;
    
    public typedef union {
	void	none;
	Robot	robot;
    } RobotOrNone;

    public typedef struct {
	Color   color;
	Shape   shape;
	bool    active;
    } Target;
    
    public typedef union {
	void	none;
	Target	target;
    } TargetOrNone;
	
    public typedef struct {
        bool    left, right, below, above;
    } Walls;

    public typedef struct {
	RobotOrNone	robot;
	TargetOrNone	target;
	Walls		walls;
    } Object;

    public typedef enum {
	NEW,	    /* no bids yet */
	BID,	    /* some bids, timer running */
	SHOW,	    /* timer expired, waiting for solution */
	DONE	    /* turn done (solved, or bailed) */
    } GameState;
    
    public typedef Object[Width,Height]	Board;

    public TargetOrNone active_target(&Board board) {
	    for (int y = 0; y < Height; y++)
		    for (int x = 0; x < Width; x++)
			    union switch (board[x,y].target) {
			    case target t:
				    if (t.active)
					    return (TargetOrNone.target) t;
				    break;
			    case none:
				    break;
			    }
	    return TargetOrNone.none;
    }

    public void set_target(&Board board, Target target) {
	    for (int y = 0; y < Height; y++)
		    for (int x = 0; x < Width; x++)
			    union switch (board[x,y].target) {
			    case target t:
				    board[x,y].target.target.active = t == target;
				    break;
			    case none:
				    break;
			    }
    }

    public RobotOrNone active_robot(&Board board) {
	    for (int y = 0; y < Height; y++)
		    for (int x = 0; x < Width; x++)
			    union switch (board[x,y].robot) {
			    case robot r:
				    if (r.active)
					    return (RobotOrNone.robot) r;
				    break;
			    case none:
				    break;
			    }
	    return RobotOrNone.none;
    }

    public void set_robot(&Board board, Robot robot) {
	    for (int y = 0; y < Height; y++)
		    for (int x = 0; x < Width; x++)
			    union switch (board[x,y].robot) {
			    case robot r:
				    board[x,y].robot.robot.active = r == robot;
				    break;
			    case none:
				    break;
			    }
    }

    public typedef enum {
	NOGAME,
	NOUSER,
	NOTINGAME,
	NOTPLAYING,
	NOTBIDDING,
	NOTLOWER,
	NOBID,
	NOTACTIVE,
	NOTDONE,
	NOTNUMBER,
	BLOCKED,
	NOTEMPTY,
	COMMAND,
	SYNTAX,
	NOTCOLOR,
	NOTSHAPE,
	NOTDIRECTION,
	TOOMANYMOVES,
	NONAMESET,
	INVALIDNAME,
	NOTGAMESTATE,
	NOTBOOL
    } Error;

    public exception rr_error (Error e);

    public Color color (string w) {
	switch (w[0]) {
	case 'r': case 'R': return Color.Red;
	case 'y': case 'Y': return Color.Yellow;
	case 'g': case 'G': return Color.Green;
	case 'b': case 'B': return Color.Blue;
	case 'w': case 'W': return Color.Whirl;
	default: raise rr_error (Error.NOTCOLOR);
	}
    }
    
    public bool boolean (string w) {
	switch (w[0]) {
	case 't': case 'T': case 'y': case 'Y': case '1':
	    return true;
	case 'f': case 'F': case 'n': case 'N': case '0':
	    return false;
	default:
	    raise rr_error(Error.NOTBOOL);
	}
    }

    public Shape shape (string w) {
	switch (w[0]) {
	case 't': case 'T': return Shape.Triangle;
	case 's': case 'S': return Shape.Square;
	case 'o': case 'O': return Shape.Octagon;
	case 'c': case 'C': return Shape.Circle;
	case 'w': case 'W': return Shape.Whirl;
	    default: raise rr_error (Error.NOTSHAPE);
	}
    }

    public Direction direction (string w) {
	switch (w[0]) {
	case 'n': case 'N': return Direction.North;
	case 'e': case 'E': return Direction.East;
	case 's': case 'S': return Direction.South;
	case 'w': case 'W': return Direction.West;
	default: raise rr_error (Error.NOTDIRECTION);
	}
    }

    public GameState game_state(string w) {
	switch (w[0]) {
	case 'n': case 'N': return GameState.NEW;
	case 'b': case 'B': return GameState.BID;
	case 's': case 'S': return GameState.SHOW;
	case 'd': case 'D': return GameState.DONE;
	default: raise rr_error (Error.NOTGAMESTATE);
	}
    }
}
