//game: WOLF-GOAT-CABBAGE

module game_wgc(
input wire reset,
input wire clk,
input wire [3:0]key,
output reg [3:0]state_out,
output reg fail,
output reg win
);

parameter GOAT = 0;
parameter CABBAGE = 1;
parameter WOLF = 2;
parameter MEN = 3;

//fix new key states
reg [3:0]key_fixed;
always @(posedge clk or posedge reset)
begin
if(reset)
key_fixed <= 4'b0000;
else
key_fixed <= key;
end

//detect key press event with simple filter with shift register
reg [3:0]key_was_pressed_sr;
always @(posedge clk or posedge reset)
begin
if(reset)
key_was_pressed_sr <= 4'b0000;
else
key_was_pressed_sr <= { key_was_pressed_sr[2:0], (key_fixed != 4'b0000) };
end

wire key_was_pressed;
assign key_was_pressed = (key_was_pressed_sr==4'b0001);

//each bit for goat/cabbage/wolf/men
//0 mean initial river side
//1 mean target river side
reg [3:0]state;
always @(posedge clk or posedge reset)
begin
if(reset)
state <= 4'b0000;
else
begin
if(key_was_pressed)
begin
case(state)
4'b0000: //state0
begin
if(key_fixed[GOAT])
state <= 4'b1001; //move to 1
else
if(key_fixed[CABBAGE])
state <= 4'b1010; //fail
else
if(key_fixed[WOLF])
state <= 4'b1100; //fail
else
if(key_fixed[MEN])
state <= 4'b1000; //fail
end
4'b1001: //state1
begin
if(key_fixed[GOAT])
state <= 4'b0000; //move back to 0
else
if(key_fixed[CABBAGE])
state <= 4'b1001; //stay
else
if(key_fixed[WOLF])
state <= 4'd1001; //stay
else
if(key_fixed[MEN])
state <= 4'b0001; //move to 2
end
4'b0001: //state2
begin
if(key_fixed[GOAT])
state <= 4'b0001; //stay
else
if(key_fixed[CABBAGE])
state <= 4'b1011; //move to 3
else
if(key_fixed[WOLF])
state <= 4'b1101; //move to 4
else
if(key_fixed[MEN])
state <= 4'b1001; //back to 1
end
4'b1011: //state3
begin
if(key_fixed[GOAT])
state <= 4'b0010; //move to 5
else
if(key_fixed[CABBAGE])
state <= 4'b0001; //back to 2
else
if(key_fixed[WOLF])
state <= 4'b1011; //stay
else
if(key_fixed[MEN])
state <= 4'b0011; //fail
end
4'b1101: //state4
begin
if(key_fixed[GOAT])
state <= 4'b0100; //move to 8
else
if(key_fixed[CABBAGE])
state <= 4'b1101; //stay
else
if(key_fixed[WOLF])
state <= 4'b0001; //back to 2
else
if(key_fixed[MEN])
state <= 4'b0101; //fail
end
4'b0010: //state5
begin
if(key_fixed[GOAT])
state <= 4'b1011; //back to 3
else
if(key_fixed[CABBAGE])
state <= 4'b0010; //stay
else
if(key_fixed[WOLF])
state <= 4'b1110; //move to 6
else
if(key_fixed[MEN])
state <= 4'b1010; //fail
end
4'b1110: //state6
begin
if(key_fixed[GOAT])
state <= 4'b1110; //stay
else
if(key_fixed[CABBAGE])
state <= 4'b0100; //move to 8
else
if(key_fixed[WOLF])
state <= 4'b0010; //back to 5
else
if(key_fixed[MEN])
state <= 4'b0110; //move to 7
end
4'b0110: //state7
begin
if(key_fixed[GOAT])
state <= 4'b1111; //win
else
if(key_fixed[CABBAGE])
state <= 4'b0110; //stay
else
if(key_fixed[WOLF])
state <= 4'b0110; //stay
else
if(key_fixed[MEN])
state <= 4'b1110; //back to 6
end
4'b0100: //state8
begin
if(key_fixed[GOAT])
state <= 4'b1101; //move to 4
else
if(key_fixed[CABBAGE])
state <= 4'b1110; //back to 6
else
if(key_fixed[WOLF])
state <= 4'b0100; //stay
else
if(key_fixed[MEN])
state <= 4'b1100; //fail
end
4'b1111: //win
begin
state <= 4'd0;
end
default: //fail
state <= 4'd0;
endcase
end
end
end

always @(state)
begin
state_out = state;
win = (state==4'b1111);
fail = (state==4'b0111) || (state==4'b1000) || (state==4'b0011) || (state==4'b1100) || (state==4'b0101) || (state==4'b1010);
end

endmodule