aboutsummaryrefslogtreecommitdiffstats
path: root/lib/gs/contribs/othello/othello.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gs/contribs/othello/othello.erl')
-rw-r--r--lib/gs/contribs/othello/othello.erl236
1 files changed, 236 insertions, 0 deletions
diff --git a/lib/gs/contribs/othello/othello.erl b/lib/gs/contribs/othello/othello.erl
new file mode 100644
index 0000000000..c66c9c2e79
--- /dev/null
+++ b/lib/gs/contribs/othello/othello.erl
@@ -0,0 +1,236 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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 online 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-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.
+
+