;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; GET_COMPUTER_MOVE_RHS ; ; FILE NAME: GET_COMPUTER_MOVE_RHS.OPS ; CREATION DATE: 11/20/89 ; AUTHOR: Frederick S. Schebor ; REVISIONS: ; Date Initials Reason for Revision ; PURPOSE: Given a tic-tac-toe board, determine the best move using the following priorities: ; 1) If the computer can win in one move, make that move. ; 2) If the human can win in one move, block that move. ; 3) Pick the best possible move. ; a) Pick the center. ; b) Pick a location in a row/column that only has one computer mark in it. ; c) Pick a random location. ; METHOD: OPS5 productions handle the above strategies. ; REFERENCED ROUTINES: ; get_blackboard_data_ops5_shell FUNCTION ; make_ttt_positions SUBROUTINE ; put_blackboard_data_ops5_shell FUNCTION ; update_ttt_board SUBROUTINE ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ( EXTERNAL ( get_blackboard_data_ops5_shell SYMBOLIC-ATOM ( SYMBOLIC-ATOM BY REFERENCE ) ) ( make_ttt_positions ) ( put_blackboard_data_ops5_shell INTEGER-ATOM ( SYMBOLIC-ATOM BY REFERENCE ) ( SYMBOLIC-ATOM BY REFERENCE ) ) ( update_ttt_board ) ) ( LITERALIZE mark human computer ) ( LITERALIZE opposite of is ) ( LITERALIZE position row column value identity ) ( LITERALIZE right_hand_side phase row column identity ) ( LITERALIZE status return_status ) ( STARTUP ( WATCH 0 ) ( DISABLE HALT ) ( STRATEGY LEX ) ( MAKE START ) ( RUN ) ) ( P get_ttt_board { ( START ) } --> ( REMOVE ) ( CALL make_ttt_positions ) ;Get the tic-tac-toe board from the blackboard ( MAKE mark ^human ( get_blackboard_data_ops5_shell HUMAN_MARK ) ^computer ( get_blackboard_data_ops5_shell COMPUTER_MARK )) ( MAKE opposite ^of 1 ^is 3 ) ( MAKE opposite ^of 3 ^is 1 ) ( MAKE right_hand_side ^phase look_for_win ) ;Set strategy to look for win ) ; ; The following four productions check the tic-tac-toe board to see if the computer can win in one move. If the computer ; can't win in one move, then change the strategy to prevent the user from winning in one move. ; ( P go_for_column_win ( right_hand_side ^phase look_for_win ) ( mark ^computer ) ( position ^row ^column ^value ) ( position ^row <> ^column ^value ) ( position ^row ^column ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ( P go_for_row_win ( right_hand_side ^phase look_for_win ) ( mark ^computer ) ( position ^row ^column ^value ) ( position ^row ^column <> ^value ) ( position ^row ^column ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ( P go_for_bl_tr_diagonal_win ( right_hand_side ^phase look_for_win ) ( mark ^computer ) ( position ^row 2 ^column 2 ^value ) ( position ^row { <> 2 } ^column { <> 2 <> } ^value ) ( position ^row ^column ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ( P go_for_tl_br_diagonal_win ( right_hand_side ^phase look_for_win ) ( mark ^computer ) ( position ^row 2 ^column 2 ^value ) ( position ^row { <> 2 } ^column ^value ) ( opposite ^of ^is ) ( position ^row ^column ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ( P no_win_foundq ;If we can't win in one move, can we ( right_hand_side ^phase look_for_win ) ;loose in one move? --> ( MODIFY 1 ^phase look_for_block ) ) ; ; The following four productions check the tic-tac-toe board to see if the user can win in one move. If the user ; can't win in one move, then check that we are not being set up for a no-win situation. ; ( P block_column_win ( right_hand_side ^phase look_for_block ) ( mark ^human ) ( position ^row ^column ^value ) ( position ^row <> ^column ^value ) ( position ^row ^column ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ( P block_row_win ( right_hand_side ^phase look_for_block ) ( mark ^human ) ( position ^row ^column ^value ) ( position ^row ^column <> ^value ) ( position ^row ^column ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ( P block_bl_tr_diagonal_win ( right_hand_side ^phase look_for_block ) ( mark ^human ) ( position ^row 2 ^column 2 ^value ) ( position ^row { <> 2 } ^column { <> 2 <> } ^value ) ( position ^row ^column ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ( P block_tl_br_diagonal_win ( right_hand_side ^phase look_for_block ) ( mark ^human ) ( position ^row 2 ^column 2 ^value ) ( position ^row { <> 2 } ^column ^value ) ( opposite ^of ^is ) ( position ^row ^column ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ; ; The following four productions check the tic-tac-toe board to see if the computer is being set up for a no-win situation. For ; example if the user is X and if the board contains the pattern: ; ; | X | ; ---+---+---. ; X | | ; ---+---+---. ; | | ; ; then move to the corner before the user does. ( P block_trick_1 ( right_hand_side ^phase look_for_block ) ( mark ^human ) ( position ^row 2 ^column 1 ^value ) ( position ^row 1 ^column 2 ^value ) ( position ^row 1 ^column 1 ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row 1 ^column 1 ^identity ) ) ( P block_trick_2 ( right_hand_side ^phase look_for_block ) ( mark ^human ) ( position ^row 2 ^column 3 ^value ) ( position ^row 1 ^column 2 ^value ) ( position ^row 1 ^column 3 ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row 1 ^column 3 ^identity ) ) ( P block_trick_3 ( right_hand_side ^phase look_for_block ) ( mark ^human ) ( position ^row 2 ^column 1 ^value ) ( position ^row 3 ^column 2 ^value ) ( position ^row 3 ^column 1 ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row 3 ^column 1 ^identity ) ) ( P block_trick_4 ( right_hand_side ^phase look_for_block ) ( mark ^human ) ( position ^row 2 ^column 3 ^value ) ( position ^row 3 ^column 2 ^value ) ( position ^row 3 ^column 3 ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row 3 ^column 3 ^identity ) ) ( P no_block_found ;No block needed, so just move ( right_hand_side ^phase look_for_block ) --> ( MODIFY 1 ^phase just_move ) ) ; ; The following four productions will pick a non-winning, non-blocking move using the following strategy: ; 1) Pick the center ; 2) Pick a row/column where one computer mark is present and the other two are empth ; 3) Pick any open location at random (not quite random - OPS5 will pick the location with the latest time tag). ; ( P select_center_position ( right_hand_side ^phase just_move ) ( position ^row 2 ^column 2 ^value | | ^identity ) --> ( MODIFY 1 ^phase register_position ^row 2 ^column 2 ^identity ) ) ( P select_in_nearly_empty_column ( right_hand_side ^phase just_move ) ( mark ^computer ) ( position ^row ^column ^value | | ^identity ) ( position ^row { <> } ^column ^value ) ( position ^row { <> } ^column ^value | | ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ( P select_in_nearly_empty_row ( right_hand_side ^phase just_move ) ( mark ^computer ) ( position ^row ^column ^value | | ^identity ) ( position ^row ^column { <> } ^value ) ( position ^row ^column { <> } ^value | | ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ( P select_any_empty_position ( right_hand_side ^phase just_move ) ( position ^row ^column ^value | | ^identity ) -( position ^row 2 ^column 2 ^value | | ) --> ( MODIFY 1 ^phase register_position ^row ^column ^identity ) ) ; ; The positon has been selected, so update the tic-tac-toe board. Change blackboard values so that the DISPLAY_BOARD ; knowledge source will trigger. ; ( P register_the_move ( right_hand_side ^phase register_position ^row ^column ^identity ) ( mark ^computer ) --> ( WRITE ( CRLF ) | I shall move to | |(| |,| |)| ) ( CALL update_ttt_board ) ( MAKE status ^return_status ( put_blackboard_data_ops5_shell NEXT_MOVE HUMAN ) ) ( MAKE status ^return_status ( put_blackboard_data_ops5_shell GAME_STATUS DISPLAY_BOARD ) ) ( HALT ) )