othello.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 234 行

ERL
234
字号
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %%     $Id$%%-module(othello).-export([start/0,new_game/4,start1/5]).%%----------------------------------------------------------------------%% The Othello program now uses the gs graphical package instead of the %% pxw package. See module othello_board for details%%%%----------------------------------------------------------------------start() -> othello_board:start().new_game(Computer,Player,Depth,Init) ->    spawn_link(othello,start1,[self(),Computer,Player,Depth,Init]).start1(Win,Computer,Player,Depth,Init) ->    Board = othello_adt:new(t),    random:seed(),    init_display(Board,Win,Init),    play(Computer,Player,Board,Depth,Win,1).play(Computer,Player,Board,Depth,Win,NoDs) ->    tell_win(Win,Computer,Player),    case catch continue(Player,Board) of	{game_over,Result} ->	    game_over(Board,Player,Result,Win);	{omit_draw,Player} ->	    omit(Player,Win),	    play(Computer,swap(Player),Board,Depth,Win,NoDs);	ok ->	    Draw = choose_draw(Computer,Player,Board,Depth,Win,NoDs),	    Win ! {self(),draw,Draw},	    Board1 = othello_adt:set(Draw,Player,Board),	    display(Board1,Board,Win),	    play(Computer,swap(Player),Board1,Depth,Win,NoDs+1)    end.continue(Player,Board) ->    Draws = game_over(Player,Board),    not_allowed(Draws,Player),    ok.choose_draw(Computer,Computer,Board,Depth,_Win,NoDs) ->    % Depth > 0 !!    {Draw,_Value} = alpha_beta(Depth,Board,-11000,11000,Computer,NoDs),%    io:format('Choosen draw is {~w,~w} : (~w)~n',%	      [othello_adt:col(Draw),othello_adt:row(Draw),Value]),%    io:format('=====================~n',[]),    Draw;choose_draw(Computer,Player,Board,Depth,Win,NoDs) ->    receive	{Win,position,Draw} ->	    flush(Win),	    case othello_adt:is_draw(Draw,Player,Board) of		false ->		    Win ! {self(),illegal_draw,Draw},		    choose_draw(Computer,Player,Board,Depth,Win,NoDs);		true ->		    Draw	    end    end.flush(Win) ->    receive	{Win,position,_} ->	    flush(Win)    after 1 ->	    true    end.tell_win(Win,Computer,Player) ->    Win ! {self(),player,Computer,Player},    receive	{Win,go_on_play} -> true    end.alpha_beta(0,Board,_,_,Player,_) ->    {-1,othello_adt:evaluate_board(Player,Board)};alpha_beta(Depth,Board,Alpha,Beta,Player,NoDs) ->    case compute(Player,Board,NoDs) of	[] ->	    Player1 = swap(Player),	    case compute(Player1,Board,NoDs) of		[] ->		    dead_lock(Board,Player);		PosDraws1 ->		    choose(PosDraws1,Board,Depth-1,-Beta,-Alpha,-1,			   Player1,NoDs)	    end;	PosDraws ->	    choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs)%	    A = choose(PosDraws,Board,Depth-1,-Beta,-Alpha,-1,Player,NoDs),%	    io:format('Alpha-Beta (~w) ==> ~w~n',[Depth,A]),%	    A    end.choose([Draw|Draws],Board,Depth,Alpha,Beta,Record,Player,NoDs) ->    Player1 = swap(Player),    Board1 = othello_adt:set(Draw,Player,Board),%    io:format('Alpha <~w> Beta <~w> ~n',[Alpha,Beta]),    {_,Value} = alpha_beta(Depth,Board1,Alpha,Beta,Player1,NoDs+1),    Value1 = -Value,    cutoff(Draw,Value1,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs);choose([],_,_,Alpha,_,Draw,_,_) ->    {Draw,Alpha}.    cutoff(Draw,Value,_,_,Beta,_,_,_,_,_) when Value >= Beta ->    {Draw,Value};cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,_,Player,NoDs)  when Alpha < Value, Value < Beta ->    choose(Draws,Board,Depth,Value,Beta,Draw,Player,NoDs);cutoff(Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs)  when Value == Alpha, NoDs < 13 ->    choose(Draws,Board,Depth,Alpha,Beta,random_choice(Draw,Record),	   Player,NoDs);cutoff(_Draw,Value,Depth,Alpha,Beta,Draws,Board,Record,Player,NoDs)  when Value =< Alpha ->    choose(Draws,Board,Depth,Alpha,Beta,Record,Player,NoDs).compute(Player,Board,NoOfDraws) when NoOfDraws < 13 ->    case othello_adt:possible_draws(Player,Board,begin_play) of	[] ->	    othello_adt:possible_draws(Player,Board,playing);	Draws ->	    Draws    end;compute(Player,Board,_) ->    othello_adt:possible_draws(Player,Board,playing).%%----------------------------------------------------------%% Randomly choose between two draws with the same value.%%----------------------------------------------------------    random_choice(Draw,Draw1) ->    case random:uniform(2) of	1 ->	    Draw;	2 ->	    Draw1    end.dead_lock(Board,Player) ->    case win_or_loose(Board,Player) of	0                    -> {-1,0};	Value when Value > 0 -> {-1,10000};	_                    -> {-1,-10000}    end.win_or_loose(Board,Player) ->    Player1 = swap(Player),    othello_adt:pieces(Player,Board) - othello_adt:pieces(Player1,Board).game_over(Player,Board) ->    case othello_adt:possible_draws(Player,Board,playing) of	[] ->	    Player1 = swap(Player),	    case othello_adt:possible_draws(Player1,Board,playing) of		[] ->		    throw({game_over,{{Player,othello_adt:pieces(Player,Board)},				      {Player1,othello_adt:pieces(Player1,Board)}}});		_ ->		    []  % Player`s Draws !!	    end;	Draws ->	    Draws    end.game_over(_Board,_Player,Result,Win) ->    Win ! {self(),game_over,white_res(Result),black_res(Result)}.white_res({{white,Res},_}) -> Res;white_res({_,{white,Res}}) -> Res.	black_res({{black,Res},_}) -> Res;black_res({_,{black,Res}}) -> Res.not_allowed([],Player) ->    throw({omit_draw, Player});not_allowed(_,_Player) ->    ok.omit(Player,Win) ->    Win ! {self(),omit_draw,Player},    receive	{Win,continue} ->	    ok    end.init_display(_Board,_Win,first_time) ->    true;init_display(Board,Win,_) ->    display(Board,Win).display(Board,Win) ->    All = othello_adt:all_pos(Board),    display1(All,Win),    Win ! {self(),score,othello_adt:pieces(white,Board),	   othello_adt:pieces(black,Board)}.display(Board,OldB,Win) ->    Diff = othello_adt:diff(Board,OldB),    display1(Diff,Win),    Win ! {self(),score,othello_adt:pieces(white,Board),	   othello_adt:pieces(black,Board)}.    display1([{Pos,Colour}|Diff],Win) ->    Win ! {self(),new_mark,Pos,Colour},    display1(Diff,Win);display1(_,_) ->    true.swap(white) -> black;swap(black) -> white.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?