---------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- The Marienbad Game -- EE 552 Project -- Group Members: Koziar, Kory -- McDermott, Ashley -- Stangeland, Duane -- -- File : Gd_move.vhd ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- This VHDL code is used in a couple of different ways. The first is in -- the check move process. This process is responcible for math that must -- be done continusly to ensure that when any other module requests information -- there is no timming errors. This module will also calcluate the number of -- pieces that the computer will take. This is also done here, however at this -- present time, there still is a timming violation that occurs on a irregular -- basis. The second process in this file is check_mouse. This process will -- take the values calculated in the other process and will decide if the player -- made a valid move and will update the player and pointer information accordingly -- In the case of the computer, it will update the pointers if no win can be -- made, or set the pointers to a winning position if required. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; use work.my_constants.all; ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- The entity Gd_Move contains five inputs, three buffered signals. -- They are described below. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- entity Gd_Move is port( signal Power_On : in std_logic; -- Reset signal signal MouseL : in std_logic; -- Left mouse button signal MouseX : in std_logic_vector(6 downto 0); -- X mouse position signal MouseY : in std_logic_vector(6 downto 0); -- Y mouse position signal Computer_Play : in std_logic; -- Computer on flag signal Player : buffer std_logic; -- Player turn flag signal PointerX : buffer std_logic_vector(6 downto 0); -- Last pebble X position signal PointerY : buffer std_logic_vector(6 downto 0) -- Last pebble Y position ); end Gd_Move; ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- Architecture Behavior of Gd_Move is ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- signal Error_Check : std_logic; -- Error Flag signal Win_Flag : std_logic; -- Win Flag signal YStep : std_logic_vector(6 downto 0) ; -- Computer Y increment signal LastTaken : integer range -511 to 511; -- Last Number of pieces taken signal PiecesWanted : integer range -511 to 511; -- How many does player want signal Pieces : integer range -1023 to 1023; -- How many does computer want signal MXI, PXI : integer range -511 to 511; -- X column position signal MXI2, PXI2 : integer range -511 to 511; -- Temp to calculate MXI and PXI signal MYI, PYI : integer range -511 to 511; -- Y row position signal MYI2, PYI2 : integer range -511 to 511; -- Temp to calculate MYI and PYI signal YMove : integer range -511 to 511; -- How much to increment Y by signal Remaining : integer range -511 to 511; -- Remaining pieces on next line signal How_Many : integer range -511 to 511; -- How many pieces computer will take Begin ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- Check_Move will preform all the math that is required to check if the -- Move requested by the user, or the computer is valid. Is done in a empty -- sensitivity list so that data is always updated. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- Check_Move : process begin if Power_On = '0' then Win_Flag <= '0'; -- No win YStep <= "0000000"; -- No step PiecesWanted <= 0; -- No move has been made yet MXI <= 0; -- Rest follows this principle: MXI2 <= 0; -- This is to ensure that when reset, system PXI <= 0; -- does not hang on to previous values PXI2 <= 0; MYI <= 0; MYI2 <= 0; PYI <= 0; PYI2 <= 0; YMove <= 0; Remaining <= 0; Pieces <= 0; How_Many <= 0; else ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- The next few lines will take the values of mouse X, Y and pointer X, Y -- and will convert them to row and column of current mouse position and -- previous taken position. This is because mouse is ranged by a offset of -- 1 and must be subtracted so that the first column is column 1 for both mouse -- and pointer. Y however, is incremented by 2 (to allow for a row of pebbles -- and a row of blanks. because of this, the row count must be subtracted by -- 1 and then divided by 2 so that the first row is 1 and the last is 16. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- Error_Check <= '0'; MXI2 <= conv_integer(MouseX); MXI <= MXI2 - 1; MYI2 <= conv_integer(MouseY); MYI <= (MYI2 - 1) / 2; PXI2 <= conv_integer(PointerX); PXI <= PXI2 - 1; PYI2 <= conv_integer(PointerY); PYI <= (PYI2 - 1) / 2; YMove <= MYI - PYI; Pieces <= LastTaken + LastTaken; -- Pieces computer wants How_Many <= PXI + Pieces; -- overflow onto line calculated below. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- if the computer wants to take more then the listed value, the multiple of 36 -- is subtracted by that ammount, and the Ystep is the value of howmany lines the -- y pointer must be incremented to. This was done, as division in a system -- that does not have a math processor is a complicated system, and by doing -- addition and subtraction only, the number of LC's is GREATLY reduced. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- if (LastTaken >168) then Win_Flag <= '1'; elsif (How_Many >324) then Remaining <= How_Many - 324; YStep <= "0010010"; elsif (How_Many >288) then Remaining <= How_Many - 288; YStep <= "0010000"; elsif (How_Many >252) then Remaining <= How_Many - 252; YStep <= "0001110"; elsif (How_Many >216) then Remaining <= How_Many - 216; YStep <= "0001100"; elsif (How_Many >180) then Remaining <= How_Many - 180; YStep <= "0001010"; elsif (How_Many >144) then Remaining <= How_Many - 144; YStep <= "0001000"; elsif (How_Many >108) then Remaining <= How_Many - 108; YStep <= "0000110"; elsif (How_Many >72) then Remaining <= How_Many - 72; YStep <= "0000100"; elsif (How_Many >36) then Remaining <= How_Many - 36; YStep <= "0000010"; else YStep <= "0000000"; end if; if (YMove < 0) then Error_Check <= '1'; elsif(Ymove = 0) then -- Person 'clicked' on same line as previous play PiecesWanted <= ( MXI - PXI ); elsif (Ymove = 1) then -- Person 'clicked' on next line as previous play PiecesWanted <= ( 36 - PXI + MXI ); else -- The number requested is greater than or equal to 2 lines below previous play PiecesWanted <= ( ( (36 - PXI) + MXI ) + ((YMove-1) * 32) + ((YMove-1) * 4) ); end if; end if; end process Check_Move; ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- -- Check_Mouse will check to see if the amount requested by the user is valid -- In the case of computer play, we know that the computer will always take -- a valid move, so pointer manipulation is the only thing required. ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- Check_Mouse : process(MouseL,Power_On) Begin if Power_On = '0' then LastTaken <= 251; -- This allows for all pieces to be taken except last of first move rule. Player <= '0'; -- First player PointerX <= "0000010";-- Pointer initalized to the mouse X PointerY <= "0000011";-- Pointer initalized to the mouse Y else -- Falling edge of mouse click occured. if (MouseL = '0' and MouseL'event) then -- Player 1 or Player 2 if no computer if (Computer_Play = '0' or Player = '0') then -- Valid move, therefore update Last number takem, pointerX and pointerY, -- and switch to other player. if ( (PiecesWanted <= (LastTaken * 2)) and (Error_Check = '0') and (PiecesWanted >=1) ) then LastTaken <= PiecesWanted; PointerX <= MouseX; PointerY <= MouseY; Player <= not(Player); -- Not a valid move, therefore do not update any of the pointers with the mouse, last taken -- or switch players. else LastTaken <= LastTaken; PointerX <= PointerX; PointerY <= PointerY; Player <= Player; end if; else -- Computer won, therefore set pointers to last pebble. if (Win_Flag = '1') then PointerY <= "0011101"; PointerX <= "0100101"; -- Computer forced pointer y to go off the screen, therefore set the Y pointer -- to the last line, and add the X calculated above. elsif (PointerY >= "0011101") then PointerY <= "0011101"; PointerX <= PointerX + conv_std_logic_vector(Pieces,7);--"0100101"; -- Computer picked a move that remains on the board, therefore just update -- the pointers. elsif(YStep /= "0000000") then PointerY <= (PointerY + YStep); PointerX <= ( "0000001" + conv_std_logic_vector(Remaining,7) ); -- Computer picked a move that keeps the same line, therefore the Y pointer -- is not updated to a new line, but X is incremented. else PointerY <= PointerY; PointerX <= PointerX + conv_std_logic_vector(Pieces,7); end if; -- As computer always takes a valid move, switch players, and update the last -- taken count. LastTaken <= Pieces; Player <= not(Player); end if; end if; end if; end process Check_Mouse; end Behavior;