diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/gs/contribs/othello | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/gs/contribs/othello')
-rw-r--r-- | lib/gs/contribs/othello/Makefile | 100 | ||||
-rw-r--r-- | lib/gs/contribs/othello/othello.erl | 236 | ||||
-rw-r--r-- | lib/gs/contribs/othello/othello.gif | bin | 0 -> 148 bytes | |||
-rw-r--r-- | lib/gs/contribs/othello/othello.tool | 6 | ||||
-rw-r--r-- | lib/gs/contribs/othello/othello_adt.erl | 539 | ||||
-rw-r--r-- | lib/gs/contribs/othello/othello_board.erl | 642 | ||||
-rw-r--r-- | lib/gs/contribs/othello/priv/marker.bm | 43 | ||||
-rw-r--r-- | lib/gs/contribs/othello/priv/square.bm | 43 |
8 files changed, 1609 insertions, 0 deletions
diff --git a/lib/gs/contribs/othello/Makefile b/lib/gs/contribs/othello/Makefile new file mode 100644 index 0000000000..b81b35fb55 --- /dev/null +++ b/lib/gs/contribs/othello/Makefile @@ -0,0 +1,100 @@ +# +# %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% +# + +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../../vsn.mk +VSN=$(GS_VSN) + +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/contribs + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- + +MODULES= \ + othello \ + othello_adt \ + othello_board + +HRL_FILES= + +ERL_FILES= $(MODULES:%=%.erl) + +TARGET_FILES= $(MODULES:%=../ebin/%.$(EMULATOR)) $(TARGET_TOOLBOX_FILES) + +TOOLNAME = othello + +EXTRA_FILES= +TOOLBOX_FILES= $(TOOLNAME).tool $(TOOLNAME).gif +TARGET_TOOLBOX_FILES= $(TOOLBOX_FILES:%=$(EBIN)/%) +BITMAPS= priv/marker.bm priv/square.bm + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +ERL_COMPILE_FLAGS += + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- + +debug opt: $(TARGET_FILES) + +docs: + +clean: + rm -f $(TARGET_FILES) + rm -f core + +# ---------------------------------------------------- +# Special Build Targets +# ---------------------------------------------------- + +$(EBIN)/$(TOOLNAME).gif: $(TOOLNAME).gif + rm -f $@ + cp $(TOOLNAME).gif $@ + +$(EBIN)/$(TOOLNAME).tool: $(TOOLNAME).tool + rm -f $@ + cp $(TOOLNAME).tool $@ + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_spec: opt + $(INSTALL_DIR) $(RELSYSDIR)/ebin + $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin + $(INSTALL_DIR) $(RELSYSDIR)/othello + $(INSTALL_DATA) $(ERL_FILES) $(EXTRA_FILES) $(RELSYSDIR)/othello + $(INSTALL_DIR) $(RELSYSDIR)/othello/priv + $(INSTALL_DATA) $(BITMAPS) $(TOOLBOX_FILES) $(RELSYSDIR)/othello/priv + +release_docs_spec: + 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. + + diff --git a/lib/gs/contribs/othello/othello.gif b/lib/gs/contribs/othello/othello.gif Binary files differnew file mode 100644 index 0000000000..5970c50209 --- /dev/null +++ b/lib/gs/contribs/othello/othello.gif diff --git a/lib/gs/contribs/othello/othello.tool b/lib/gs/contribs/othello/othello.tool new file mode 100644 index 0000000000..47550a581d --- /dev/null +++ b/lib/gs/contribs/othello/othello.tool @@ -0,0 +1,6 @@ +{version,"0.1"}. +{{tool,"Othello"}, + {start,{othello,start,[]}}, + {icon,"othello.gif"}, + {message,"Othello - The Game"}, + {html,"http://www.armory.com/~iioa/othguide.html"}}. diff --git a/lib/gs/contribs/othello/othello_adt.erl b/lib/gs/contribs/othello/othello_adt.erl new file mode 100644 index 0000000000..d1d3ec950b --- /dev/null +++ b/lib/gs/contribs/othello/othello_adt.erl @@ -0,0 +1,539 @@ +%% +%% %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_adt). +-compile(export_all). +%%------------------------------------------------------- +%% Use three main states for the strategy: +%% +%% BeginPlay: Stay in the inner square as long as possible. +%% Use the possible_draws/3. +%% +%% MiddlePlay: Try to choose stable markers (?) +%% Use stable/3 +%% +%% EndPlay: Try to flip as many markers as possible +%% +%% The transition from Begin to Middle is obvious. From Middle +%% to End however, is can be discussed. +%%------------------------------------------------------- + +test(N,B) -> + X=new(B), + statistics(wall_clock), + test0(N,X), + {_,T} = statistics(wall_clock), + {time_was,T/N}. + + +test0(0,_) -> true; +test0(N,X) -> + possible_draws(black,X,begin_play), + test0(N-1,X). + +%%------------------------------------------------------- +%% new/1 - returns a new board +%% +%% Uses a tuple for storing the board +%%------------------------------------------------------- + +new(B) -> + Board = mk_board(B), + {ordsets:from_list([18,19,20,21,26,29,34,37,42,43,44,45]),Board}. + +mk_board(t) -> + Tup = list_to_tuple(gen_list(64,grey)), + Tup1 = setelement(28+1, Tup, white), + Tup2 = setelement(35+1, Tup1, white), + Tup3 = setelement(27+1, Tup2, black), + gen_score_board(), + setelement(36+1, Tup3, black). + +gen_list(0,_) -> []; +gen_list(I,Def) -> [Def|gen_list(I-1,Def)]. + +gen_score_board() -> put(score,list_to_tuple(gen_list(64,0))). + +%%------------------------------------------------------- +%% pos(Col,Row) - returns a position describing column +%% and row. +%% Col and Row have the range 1 - 8. +%%------------------------------------------------------- + +pos(Col,Row) -> ((Row - 1) bsl 3) + (Col - 1). + +%%------------------------------------------------------- +%% col(Pos) - returns the column of the Pos position +%%------------------------------------------------------- + +col(Pos) -> (Pos band 7) + 1. + +%%------------------------------------------------------- +%% row(Pos) - returns the row of the Pos position +%%------------------------------------------------------- + +row(Pos) -> (Pos bsr 3) + 1. + +%%------------------------------------------------------- +%% is_draw(Pos,Colour,Board) - returns true if Pos is a +%% correct draw. +%%------------------------------------------------------- + +is_draw(Pos,Colour,{Bset,Board}) -> + case ordsets:is_element(Pos,Bset) of + true -> + case catch is_good(Colour,Pos,Board) of + true -> + true; + _ -> + false + end; + _ -> + false + end. + +%%------------------------------------------------------- +%% set(Pos,Colour,Board) - returns an updated board +%%------------------------------------------------------- + +set(Pos,Colour,{Bset,Board}) -> + case ordsets:is_element(Pos,Bset) of + true -> + NewBoard = setelement(Pos+1,Board,Colour), + Empty = empty_neighbour(Pos,NewBoard), + NewBset = ordsets:union(Empty,ordsets:del_element(Pos,Bset)), + turn(Colour,Pos,{NewBset,NewBoard}); + _ -> + {error,invalid_position} + end. + +empty_neighbour(Pos,Board) -> + ordsets:from_list(empty_neighbour(Pos,Board,deltas())). + +empty_neighbour(_,_,[]) -> []; +empty_neighbour(Pos,Board,[H|T]) -> + case is_empty(Pos+H,dir(Pos,H),Board) of + true -> [Pos+H|empty_neighbour(Pos,Board,T)]; + _ -> empty_neighbour(Pos,Board,T) + end. + +is_empty(_,false,_) -> false; +is_empty(X,_,_Board) when X<0 -> false; +is_empty(X,_,_Board) when X>63 -> false; +is_empty(X,_,Board) -> + case element(X+1,Board) of + grey -> true; % Empty + _ -> false + end. + +%%------------------------------------------------------- +%% get(Pos,Board) - returns the contents in Pos +%%------------------------------------------------------- + +get(Pos,{_Bset,Board}) -> element(Pos+1,Board). + +%%------------------------------------------------------- +%% pieces(Colour,Board) - returns the number of Colour +%% pieces. +%%------------------------------------------------------- + +pieces(Colour,{_Bset,Board}) -> + pieces(Colour,Board,0,0). + +pieces(Colour,Board,Pos,Count) when Pos < 64 -> + case element(Pos+1,Board) of + Colour -> + pieces(Colour,Board,Pos+1,Count+1); + _ -> + pieces(Colour,Board,Pos+1,Count) + end; +pieces(_,_,_,Count) -> + Count. + +%%------------------------------------------------------- +%% possible_draws(Colour, Board, State) +%% +%% Returns a list of possible draws regarding the current +%% strategy state. +%%------------------------------------------------------- + +possible_draws(Colour,{Bset,Board},begin_play) -> + Dset = ordsets:intersection(Bset,inner_square()), + possible_draws_0(Colour,Dset,Board); +possible_draws(Colour,{Bset,Board},_) -> + possible_draws_0(Colour,Bset,Board). + +possible_draws(Colour,{Bset,Board}) -> + possible_draws_0(Colour,Bset,Board). + +possible_draws_0(_,[],_) -> []; +possible_draws_0(Colour,[H|T],Board) -> + case catch is_good(Colour,H,Board) of + true -> [H|possible_draws_0(Colour,T,Board)]; + false -> possible_draws_0(Colour,T,Board) + end. + + +%%------------------------------------------------------- +%% evaluate_board(Colour,Board) - returns the value of +%% the board from Colours +%% point of view. +%%------------------------------------------------------- + +evaluate_board(Colour,{_Bset,Board}) -> + Score = get(score), % Initialized (zeroed) score board !! + Colour1 = swap(Colour), + Score1 = eval_board(Colour,Colour1,Score,Board,0), + Score2 = cnt_corner(0,Score1,Board,Colour,Colour1), + Score3 = cnt_corner(7,Score2,Board,Colour,Colour1), + Score4 = cnt_corner(56,Score3,Board,Colour,Colour1), + Score5 = cnt_corner(63,Score4,Board,Colour,Colour1), + count(Score5,0). +% A = count(Score5,0), +% io:format('Score = ~w~n',[A]), +% A. + +eval_board(MyCol,OtCol,Score,Board,Pos) when Pos < 64 -> + case element(Pos+1,Board) of + MyCol -> + Score1 = setelement(Pos+1,Score,score(Pos)), + eval_board(MyCol,OtCol,Score1,Board,Pos+1); + OtCol -> + Score1 = setelement(Pos+1,Score,-score(Pos)), + eval_board(MyCol,OtCol,Score1,Board,Pos+1); + _ -> + eval_board(MyCol,OtCol,Score,Board,Pos+1) + end; +eval_board(_,_,Score,_,_) -> + Score. + +cnt_corner(Corner,Score,Board,MyCol,OtCol) -> + case element(Corner+1,Board) of + MyCol -> + cnt_corn(Corner,setelement(Corner+1,Score,50), + Board,50,MyCol); + OtCol -> + cnt_corn(Corner,setelement(Corner+1,Score,-50), + Board,-50,OtCol); + _ -> + Score + end. + +cnt_corn(0,Score,Board,Value,Colour) -> + Score1 = cnt_corn(0,1,8,Score,Board,Value,Colour), + cnt_corn(0,8,1,Score1,Board,Value,Colour); +cnt_corn(7,Score,Board,Value,Colour) -> + Score1 = cnt_corn(7,-1,8,Score,Board,Value,Colour), + cnt_corn(7,8,-1,Score1,Board,Value,Colour); +cnt_corn(56,Score,Board,Value,Colour) -> + Score1 = cnt_corn(56,1,-8,Score,Board,Value,Colour), + cnt_corn(56,-8,1,Score1,Board,Value,Colour); +cnt_corn(63,Score,Board,Value,Colour) -> + Score1 = cnt_corn(63,-1,-8,Score,Board,Value,Colour), + cnt_corn(63,-8,-1,Score1,Board,Value,Colour). + +cnt_corn(Pos,Dir,LineDir,Score,Board,Value,Colour) -> + case dir(Pos,Dir) of + Dir -> + NextEdge = Pos+Dir, + case element(NextEdge+1,Board) of + Colour -> + Score1 = setelement(NextEdge+1,Score,Value), + Score2 = cnt_line(NextEdge,LineDir,Score1,Board, + Colour,Value), + cnt_corn(NextEdge,Dir,LineDir,Score2,Board,Value,Colour); + _ -> + Score + end; + _ -> + Score + end. + +cnt_line(Pos,Dir,Score,Board,Colour,Value) -> + case dir(Pos,Dir) of + Dir -> + OnLinePos = Pos+Dir, + case element(OnLinePos+1,Board) of + Colour -> + Score1 = setelement(OnLinePos+1,Score,Value), + cnt_line(OnLinePos,Dir,Score1,Board,Colour,Value); + _ -> + Score + end; + _ -> + Score + end. + +count(Score,Pos) when Pos < 64 -> + element(Pos+1,Score) + count(Score,Pos+1); +count(_,_) -> + 0. + +swap(white) -> black; +swap(black) -> white. + +%%------------------------------------------------------- +%% stable(Colour,Pos,Board) - returns a value 0-8 +%% +%% A high value is regarded as more stable than a lower one. +%% The stability means how many "friendly" neighbours there +%% are, i.e markers of the same colour. Neighbours positions +%% outside the board are regarded as friendly. +%%------------------------------------------------------- + +stable(Colour,Pos,{_,Board}) -> + stable(deltas(),Colour,Pos,Board). + +stable([],_,_,_) -> 0; +stable([H|T],Colour,Pos,Board) -> + stable_val(Colour,Pos,H,Board) + stable(T,Colour,Pos,Board). + +stable_val(_,H,D,_) when H+D<0 -> 1; +stable_val(_,H,D,_) when H+D>63 -> 1; +stable_val(black,H,D,Board) -> + case element((H+D)+1,Board) of + black -> 1; + _ -> 0 + end; +stable_val(white,H,D,Board) -> + case element((H+D)+1,Board) of + white -> 1; + _ -> 0 + end. + +%%------------------------------------------------------- +%% diff(Board,OldBoard) - return a list of the positions +%% with changed pieces. +%% [{Pos1,Colour1},...] +%%------------------------------------------------------- + +diff(Board,OldBoard) -> diff(0,Board,OldBoard). + +diff(Pos,Board,OldBoard) when Pos < 64 -> + OldP = get(Pos,OldBoard), + case get(Pos,Board) of + OldP -> + diff(Pos+1,Board,OldBoard); + NewP -> + [{Pos,NewP}|diff(Pos+1,Board,OldBoard)] + end; +diff(_,_,_) -> + []. + +%%------------------------------------------------------- +%% all_pos(Board) - return a list of the positions colour. +%% [{Pos1,Colour1},...] +%%------------------------------------------------------- + +all_pos(Board) -> all_pos(0,Board). + +all_pos(Pos,Board) when Pos < 64 -> + [{Pos,get(Pos,Board)}|all_pos(Pos+1,Board)]; +all_pos(_,_) -> + []. + +%%------------------------------------------------------- +%% Internal stuff +%%------------------------------------------------------- + +deltas() -> [9,8,7,1,-1,-7,-8,-9]. + +inner_square() -> + [18,19,20,21,26,27,28,29,34,35,36,37,42,43,44,45]. % Is already an ordset + % Save list traversing. +% ordsets:list_to_set([18,19,20,21,26,27,28,29,34,35,36,37,42,43,44,45]). + +inv(black) -> white; +inv(white) -> black. + +is_good(Colour,H,Board) -> + is_good_0(Colour,H,dir(H,-9),Board), + is_good_0(Colour,H,dir(H,-8),Board), + is_good_0(Colour,H,dir(H,-7),Board), + is_good_0(Colour,H,dir(H,-1),Board), + is_good_0(Colour,H,dir(H,1),Board), + is_good_0(Colour,H,dir(H,7),Board), + is_good_0(Colour,H,dir(H,8),Board), + is_good_0(Colour,H,dir(H,9),Board), + false. + +is_good_0(_,_,false,_) -> false; +is_good_0(_,H,D,_) when integer(H), integer(D), H+D<0 -> false; +is_good_0(_,H,D,_) when integer(H), integer(D), H+D>63 -> false; +is_good_0(black,H,D,Board) when integer(H), integer(D) -> + case element((H+D)+1,Board) of + white -> is_good_1(black,H+D,dir(H+D,D),Board); + _ -> false + end; +is_good_0(white,H,D,Board) when integer(H), integer(D) -> + case element((H+D)+1,Board) of + black -> is_good_1(white,H+D,dir(H+D,D),Board); + _ -> false + end. + +is_good_1(_,_,false,_) -> false; +is_good_1(_,H,D,_) when integer(H), integer(D), H+D<0 -> false; +is_good_1(_,H,D,_) when integer(H), integer(D), H+D>63 -> false; +is_good_1(black,H,D,Board) when integer(H), integer(D) -> + case element((H+D)+1,Board) of + white -> is_good_1(black,H+D,dir(H+D,D),Board); + black -> throw(true); + _ -> false + end; +is_good_1(white,H,D,Board) when integer(H), integer(D) -> + case element((H+D)+1,Board) of + black -> is_good_1(white,H+D,dir(H+D,D),Board); + white -> throw(true); + _ -> false + end. + +%%------------------------------------------------------- +%% turn(Colour,Draw,Board) - returns an updated board +%% turn all possible pieces +%% on the board +%% Neighbours are not changed !! +%%------------------------------------------------------- + +turn(Colour,Draw,{Bset,Board}) -> + {Bset,turn(Colour,Draw,-9, + turn(Colour,Draw,-8, + turn(Colour,Draw,-7, + turn(Colour,Draw,-1, + turn(Colour,Draw,1, + turn(Colour,Draw,7, + turn(Colour,Draw,8, + turn(Colour,Draw,9,Board))))))))}. + +turn(Colour,H,D,Board) -> + case catch is_good_0(Colour,H,dir(H,D),Board) of + true -> + turn_0(Colour,H,D,Board); + false -> + Board + end. + +turn_0(_,H,D,B) when integer(H), integer(D), H+D<0 -> B; +turn_0(_,H,D,B) when integer(H), integer(D), H+D>63 -> B; +turn_0(black,H,D,Board) when integer(H), integer(D) -> + E = H+D, + case element(E+1,Board) of + white -> turn_0(black,H+D,D,swap(black,E,Board)); + _ -> Board + end; +turn_0(white,H,D,Board) when integer(H), integer(D) -> + E = H+D, + case element(E+1,Board) of + black -> turn_0(white,H+D,D,swap(white,E,Board)); + _ -> Board + end. + +%%------------------------------------------------------- +%% swap(Colour,Pos,Board) - returns an updated board +%% turn a piece on the board +%% Neighbours are not changed !! +%%------------------------------------------------------- + +swap(Colour,Pos,Board) when integer(Pos) -> + setelement(Pos+1,Board,Colour). + +score(Pos) -> score1({col(Pos),row(Pos)}). + +score1({Column,1}) when Column >= 3, Column =< 6 -> 20; +score1({Column,8}) when Column >= 3, Column =< 6 -> 20; +score1({1,Line}) when Line >= 3, Line =< 6 -> 20; +score1({8,Line}) when Line >= 3, Line =< 6 -> 20; +score1({Column,2}) when Column >= 3, Column =< 6 -> -7; +score1({Column,7}) when Column >= 3, Column =< 6 -> -7; +score1({2,Line}) when Line >= 3, Line =< 6 -> -7; +score1({7,Line}) when Line >= 3, Line =< 6 -> -7; +score1({Column,Line}) when Column >= 3, Column =< 6, + Line >= 3, Line =< 6 -> 1; +score1({1,1}) -> 100; +score1({1,8}) -> 100; +score1({8,1}) -> 100; +score1({8,8}) -> 100; +score1({2,1}) -> -30; +score1({7,1}) -> -30; +score1({1,2}) -> -30; +score1({8,2}) -> -30; +score1({1,7}) -> -30; +score1({8,7}) -> -30; +score1({2,8}) -> -30; +score1({7,8}) -> -30; +score1({2,2}) -> -50; +score1({7,2}) -> -50; +score1({2,7}) -> -50; +score1({7,7}) -> -50. + +%%------------------------------------------------------- +%% dir(Pos,Dir) - return Dir if allowed direction at Pos. +%% else return false. +%%------------------------------------------------------- + +dir(0,1) -> 1; % {1,1} +dir(0,8) -> 8; +dir(0,9) -> 9; +dir(0,_) -> false; + +dir(7,-1) -> -1; % {8,1} +dir(7,7) -> 7; +dir(7,8) -> 8; +dir(7,_) -> false; + +dir(56,-8) -> -8; % {1,8} +dir(56,-7) -> -7; +dir(56,1) -> 1; +dir(56,_) -> false; + +dir(63,-9) -> -9; % {8,8} +dir(63,-8) -> -8; +dir(63,-1) -> -1; +dir(63,_) -> false; + +dir(Pos,-1) when (Pos bsr 3) == 0 -> -1; % {_,1} +dir(Pos,1) when (Pos bsr 3) == 0 -> 1; +dir(Pos,7) when (Pos bsr 3) == 0 -> 7; +dir(Pos,8) when (Pos bsr 3) == 0 -> 8; +dir(Pos,9) when (Pos bsr 3) == 0 -> 9; +dir(Pos,_) when (Pos bsr 3) == 0 -> false; + +dir(Pos,-9) when (Pos bsr 3) == 7 -> -9; % {_,8} +dir(Pos,-8) when (Pos bsr 3) == 7 -> -8; +dir(Pos,-7) when (Pos bsr 3) == 7 -> -7; +dir(Pos,-1) when (Pos bsr 3) == 7 -> -1; +dir(Pos,1) when (Pos bsr 3) == 7 -> 1; +dir(Pos,_) when (Pos bsr 3) == 7 -> false; + +dir(Pos,-8) when (Pos band 7) == 0 -> -8; % {1,_} +dir(Pos,-7) when (Pos band 7) == 0 -> -7; +dir(Pos,1) when (Pos band 7) == 0 -> 1; +dir(Pos,8) when (Pos band 7) == 0 -> 8; +dir(Pos,9) when (Pos band 7) == 0 -> 9; +dir(Pos,_) when (Pos band 7) == 0 -> false; + +dir(Pos,-9) when (Pos band 7) == 7 -> -9; % {8,_} +dir(Pos,-8) when (Pos band 7) == 7 -> -8; +dir(Pos,-1) when (Pos band 7) == 7 -> -1; +dir(Pos,7) when (Pos band 7) == 7 -> 7; +dir(Pos,8) when (Pos band 7) == 7 -> 8; +dir(Pos,_) when (Pos band 7) == 7 -> false; + +dir(_Pos,Dir) -> Dir. + diff --git a/lib/gs/contribs/othello/othello_board.erl b/lib/gs/contribs/othello/othello_board.erl new file mode 100644 index 0000000000..0206ba2ded --- /dev/null +++ b/lib/gs/contribs/othello/othello_board.erl @@ -0,0 +1,642 @@ +%% +%% %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_board). +-export([start/0,stop/0,init/0]). + + +%%---------------------------------------------------------------------- +%% The Othello program now uses the gs graphical package instead of the +%% pxw package. +%% +%% Differences are, explanation why and source of change in parenthesis: +%% +%% - Buttons looks different (gs feature) +%% - The black box around "Black to draw" have been removed. (me) +%% - The Colour and Level menues have been moved directly down to the +%% 'Status' box. (usability update, my addition) +%% - The mouse pointer does not change into a watch when the computer +%% is thinking (not supported in gs) +%% - Buttons does not flash when being beeped. (not supported in gs) +%% +%% +%% /Peter +%% +%%---------------------------------------------------------------------- + + +-define(BGCOL,forestgreen). + +start() -> + spawn(othello_board,init,[]). + +stop() -> + ok. + +%% This is not an application so we don't have their way of knowing +%% a private data directory where the GIF files are located (this directory). +%% We can find GS and makes it relative from there /kgb + +-define(BitmapPath,"../contribs/othello/priv"). + +setup_path() -> + GsPrivDir = code:priv_dir(gs), + Path = filename:join(GsPrivDir,?BitmapPath), + put(path,Path). + +path() -> get(path). + + + +%% +%% The button area are the Quit, Rules buttons at the top of the window. +%% The Status area is the black and white scores level and colour etc +%% inbetween the buttons and the othello board. +%% The board is the 8x8 board where othello battles are fought. +%% +init() -> + process_flag(trap_exit,true), + setup_path(), + S = gs:start(), + put(windowroot,S), % Ugly global store + + %% Shell coordinates + W = 496, + H = 636, + + %% Fix top window + Shell = gs:create(window, S, [{title,"Othello"}, + {width, W},{height, H}]), + + + %% Setup window contents + + setup_buttons(Shell,0,0,W,40), % Fix Menubar + setup_status_box(Shell,0,40,W,100), % Fix Status area + setup_board(Shell,0,140,496,496), % Combat board + + GamePid = othello:new_game(white,black,1,first_time), + + %% Default settings + Options = {white,black,1}, + %%Wids = {Status,B,W,Dr,Le,Co}, + Wids = {change,this,at,later,stage,ponto}, + write_options(Options,Wids), + + gs:config(Shell, {map, true}), %Make win visible + + loop(computer,GamePid,Shell,Wids,Options). + + + + + + +loop(User,GamePid,Shell,Wids,Options) -> + receive + {gs,ButtId, click,_ButtId1,[Button]} -> + GamePid1 = but_pressed(Button,ButtId,User,GamePid,Shell, + Wids,Options), + loop(User,GamePid1,Shell,Wids,Options); + + {gs,_, click,_,[MenuItem,_MenuIndex]} -> + Ops = menu_selected(MenuItem,User,GamePid,Wids,Options), + loop(User,GamePid,Shell,Wids,Ops); + + {'EXIT',GamePid,_} -> + loop(User,null,Shell,Wids,Options); + + {'EXIT',_,_} -> + loop(User,GamePid,Shell,Wids,Options); + + GameMsg -> + game_msg(GameMsg,User,GamePid,Shell,Wids,Options) + end. + +but_pressed("Quit",_ButtId,_User,_GamePid,_Shell,_Wids,_Op) -> + stop(), + exit(quit); +but_pressed("Rules",_ButtId,_User,GamePid,_Shell,_Wids,_Op) -> + io:format("No rules, do as you wish~n",[]), + GamePid; +but_pressed("Help",_ButtId,_User,GamePid,_Shell,_Wids,_Op) -> + io:format("Othello game~n",[]), + io:format("------------~n",[]), + io:format(" Put markers by clicking in squares~n",[]), + io:format(" Change level by clicking on it~n",[]), + io:format(" Change colour by clicking on it~n",[]), + io:format("~n",[]), + GamePid; +but_pressed("Newgame",_ButtId,_User,GamePid,_Shell,Wids,Options) -> + new_game(GamePid,Wids,Options); +but_pressed([],ButtId,User,GamePid,_Shell,_Wids,_Op) + when pid(GamePid),User == player -> + [C,R] = atom_to_list(ButtId), + GamePid ! {self(),position,othello_adt:pos(C-96,translate(R-48))}, + GamePid; +but_pressed([],ButtId,_User,GamePid,_Shell,_Wids,_Op) -> + [C,R] = atom_to_list(ButtId), + beep(othello_adt:pos(C-96,translate(R-48))), + GamePid; +but_pressed(Button,ButtId,_User,GamePid,_Shell,_Wids,_Op) -> + io:format('Not implemented button pressed ~p, ~p!!!~n',[ButtId,Button]), + GamePid. + +menu_selected("Black",_User,_GamePid,Wids,Options) -> + Op0 = setelement(1,Options,white), + Op1 = setelement(2,Op0,white), + write_options(Op1,Wids), + Op1; +menu_selected("White",_User,_GamePid,Wids,Options) -> + Op0 = setelement(1,Options,black), + Op1 = setelement(2,Op0,black), + write_options(Op1,Wids), + Op1; +menu_selected("Black (begin)",_User,_GamePid,Wids,Options) -> + Op0 = setelement(1,Options,white), + Op1 = setelement(2,Op0,black), + write_options(Op1,Wids), + Op1; +menu_selected("White (begin)",_User,_GamePid,Wids,Options) -> + Op0 = setelement(1,Options,black), + Op1 = setelement(2,Op0,white), + write_options(Op1,Wids), + Op1; +menu_selected("Beginner",_User,_GamePid,Wids,Options) -> + Op1 = setelement(3,Options,1), + write_options(Op1,Wids), + Op1; +menu_selected("Intermediate",_User,_GamePid,Wids,Options) -> + Op1 = setelement(3,Options,2), + write_options(Op1,Wids), + Op1; +menu_selected("Advanced",_User,_GamePid,Wids,Options) -> + Op1 = setelement(3,Options,3), + write_options(Op1,Wids), + Op1; +menu_selected("Expert",_User,_GamePid,Wids,Options) -> + Op1 = setelement(3,Options,4), + write_options(Op1,Wids), + Op1; +menu_selected(What,_User,_GamePid,_Wids,Options) -> + io:format('Menu item not implemented <~s>~n',[What]), + Options. + +game_msg(Msg,User,GamePid,Shell,Wids,Options) -> + case Msg of + {GamePid,new_mark,Pos,Colour} -> + new_mark(Pos,Colour), + loop(User,GamePid,Shell,Wids,Options); + + {GamePid,illegal_draw,Draw} -> + beep(Draw), + loop(User,GamePid,Shell,Wids,Options); + + {GamePid,player,Computer,Computer} -> + show_player(element(1,Wids),Computer), + cursor("watch"), + GamePid ! {self(),go_on_play}, + loop(computer,GamePid,Shell,Wids,Options); + + {GamePid,player,_Computer,Player} -> + show_player(element(1,Wids),Player), + cursor("top_left_arrow"), + GamePid ! {self(),go_on_play}, + loop(player,GamePid,Shell,Wids,Options); + + {GamePid,omit_draw,Player} -> + omit_draw(GamePid,Player), + loop(User,GamePid,Shell,Wids,Options); + + {GamePid,score,WhiteRes,BlackRes} -> + write_score(Wids,WhiteRes,BlackRes), + loop(User,GamePid,Shell,Wids,Options); + + {GamePid,draw,Draw} -> + write_draw(Wids,Draw), + loop(User,GamePid,Shell,Wids,Options); + + {GamePid,game_over,WhiteRes,BlackRes} -> + game_over(WhiteRes,BlackRes), + loop(User,GamePid,Shell,Wids,Options); + + What -> + io:format('game_msg received: ~w~n',[What]), + loop(User,GamePid,Shell,Wids,Options) + end. + + +new_game(GamePid,Wids,Options) when pid(GamePid) -> + exit(GamePid,kill), + new_game(Wids,Options); +new_game(_,Wids,Options) -> + new_game(Wids,Options). + +new_game(_Wids,Options) -> + label("",lastdraw), + Computer = element(1,Options), + Start = element(2,Options), + Depth = element(3,Options), + othello:new_game(Computer,Start,Depth,restart). + +new_mark(Pos,Colour) -> + Col = othello_adt:col(Pos), + Row = othello_adt:row(Pos), + Name = [Col+96,translate(Row)+48], + Button = get(Name), + butbit(Button,Colour). + +beep(Draw) -> + Col = othello_adt:col(Draw), + Row = othello_adt:row(Draw), + Name = [Col+96,translate(Row)+48], + Button = get(Name), + bell(Button). + +show_player(_Status,white) -> + label("White to draw",todraw); +show_player(_Status,black) -> + label("Black to draw",todraw). + +write_score(_Wids,WhiteRes,BlackRes) -> + label(integer_to_list(BlackRes),bscore), + label(integer_to_list(WhiteRes),wscore). + +write_draw(_Wids,Draw) -> + Col = othello_adt:col(Draw), + Row = othello_adt:row(Draw), + label(lists:flatten(io_lib:format('{~w,~w}',[Col,Row])), lastdraw). + +write_options(Options,Wids) -> + write_colour(Options,Wids), + write_level(Options,Wids). + +write_colour(Options,Wids) -> + write_colour(element(1,Options),element(2,Options),Wids). + +write_colour(black,white,_Wids) -> label("White (begin)",colour); +write_colour(black,black,_Wids) -> label("White",colour); +write_colour(white,black,_Wids) -> label("Black (begin)",colour); +write_colour(white,white,_Wids) -> label("Black",colour). + +write_level(Options,_Wids) -> + case element(3,Options) of + 1 -> label("Beginner",level); + 2 -> label("Intermediate",level); + 3 -> label("Advanced",level); + 4 -> label("Expert",level) + end. + +cursor(_What) -> + done. +%cursor(What) -> cursor(get(),What). + +%cursor([{[C,R],Button}|Buts],What) -> +% set_widget(Button,"cursor",What), +% cursor(Buts,What); +%cursor([_|Buts],What) -> +% cursor(Buts,What); +%cursor([],_) -> +% true. + +translate(1) -> 8; +translate(2) -> 7; +translate(3) -> 6; +translate(4) -> 5; +translate(5) -> 4; +translate(6) -> 3; +translate(7) -> 2; +translate(8) -> 1. + +bitmap(grey) -> bitmap_path("square.bm"); +bitmap(black) -> bitmap_path("marker.bm"); +bitmap(white) -> bitmap_path("marker.bm"). + +bitmap_path(Bitmap) -> + filename:join(path(),Bitmap). + +xy_position([[Letter,Digit],_,_]) -> + LettPos = Letter - 97, + X = LettPos*60 , + Y = (8 - list_to_integer([Digit])) * 60, + {X+6,Y+6}; +xy_position(X) -> + io:format("xy_position: ~w~n",[{error,X}]). + + +board() -> + [["a1",grey,nil], + ["b1",grey,nil], + ["c1",grey,nil], + ["d1",grey,nil], + ["e1",grey,nil], + ["f1",grey,nil], + ["g1",grey,nil], + ["h1",grey,nil], + + ["a2",grey,nil], + ["b2",grey,nil], + ["c2",grey,nil], + ["d2",grey,nil], + ["e2",grey,nil], + ["f2",grey,nil], + ["g2",grey,nil], + ["h2",grey,nil], + + ["a3",grey,nil], + ["b3",grey,nil], + ["c3",grey,nil], + ["d3",grey,nil], + ["e3",grey,nil], + ["f3",grey,nil], + ["g3",grey,nil], + ["h3",grey,nil], + + ["a4",grey,nil], + ["b4",grey,nil], + ["c4",grey,nil], + ["d4",white,nil], + ["e4",black,nil], + ["f4",grey,nil], + ["g4",grey,nil], + ["h4",grey,nil], + + ["a5",grey,nil], + ["b5",grey,nil], + ["c5",grey,nil], + ["d5",black,nil], + ["e5",white,nil], + ["f5",grey,nil], + ["g5",grey,nil], + ["h5",grey,nil], + + ["a6",grey,nil], + ["b6",grey,nil], + ["c6",grey,nil], + ["d6",grey,nil], + ["e6",grey,nil], + ["f6",grey,nil], + ["g6",grey,nil], + ["h6",grey,nil], + + ["a7",grey,nil], + ["b7",grey,nil], + ["c7",grey,nil], + ["d7",grey,nil], + ["e7",grey,nil], + ["f7",grey,nil], + ["g7",grey,nil], + ["h7",grey,nil], + + ["a8",grey,nil], + ["b8",grey,nil], + ["c8",grey,nil], + ["d8",grey,nil], + ["e8",grey,nil], + ["f8",grey,nil], + ["g8",grey,nil], + ["h8",grey,nil]]. + + +omit_draw(GamePid,Player) -> +% %% Find mouse coords first +% %% This was not possible in gs + + W = 200, H = 100, Root = get(windowroot), + Box = gs:create(window, Root, [{title,"OMIT"}, {width, W},{height, H}]), + + mk_label_c(lists:flatten(io_lib:format('~w has to omit draw !',[Player])), + Box, W, 10), + + mk_button_c("Ok", Box, W, H-40, 80, 30), + + gs:config(Box, {map, true}), %Make win visible + + receive + {gs,_, click,_,["Ok"]} -> + gs:destroy(Box), + GamePid ! {self(),continue} + end. + +game_over(WhiteRes,BlackRes) -> +% %% Find mouse coords first +% %% This was not possible in gs + + W = 200, H = 160, + Root = get(windowroot), + Box = gs:create(window, Root, [{title,"GAME OVER"}, + {width, W},{height, H}]), + + mk_label_c("GAME OVER", Box, W, 10), + + mk_label_c(lists:flatten(io_lib:format('White score: ~w',[WhiteRes])), + Box,W,40), + mk_label_c(lists:flatten(io_lib:format('Black score: ~w',[BlackRes])), + Box,W,70), + + mk_button_c("Ok", Box, W, H-40, 80, 30), + + gs:config(Box, {map, true}), %Make win visible + + receive + {gs,_, click,_,["Ok"]} -> + gs:destroy(Box) + end. + + + +%% ---------------------------------------------------------------- +%% Library functions. +%% ---------------------------------------------------------------- + +bell(Widget) -> + %% gs does not support bells, + Widget. + +label(Text,Label) -> + gs:config(Label,[{label,{text,Text}}]). + +%% mk_label in centered version +mk_label_c(Label,Parent,Width,Y) -> + W = 8*length(Label), + X = trunc((Width-W)/2), + gs:create(label,Parent,[{width,W}, {height, 20}, {x,X}, {y,Y}, + {label, {text, Label}}]). + + + + +setup_buttons(Shell,X,Y,W,H) -> + ButBox = gs:create(frame, Shell,[{x,X}, {y,Y},{bg,white}, + {width,W}, {height,H}]), + C = gs:create(canvas,ButBox,[{x,X}, {y,Y}, {width, W}, {height, H}, + {bg,white}]), + gs:create(line, C, [{coords, [{0,H-1},{W,H-1}]}]), + + + mk_button("Quit",ButBox, 10, 10, 70, 20), + mk_button("Rules",ButBox, 80, 10, 70, 20), + mk_button("Newgame",ButBox, 150, 10, 70, 20), + mk_button("Help",ButBox, 220, 10, 70, 20), +%% mk_button("Level",ButBox, 290, 10, 70, 20), + + done. + + + + + +%%---------------------------------------- +%% Sets up the middle window w. all the status info in. +%% The labels are given names: +%% bscore, wscore, lastdraw, todraw, level and colour to simplify +%% their frequent setting +%% +setup_status_box(Shell,X,Y,W,H) -> + F = gs:create(frame, Shell,[{x,X}, {y,Y}, + {width,W}, {height,H},{bg,white}]), + C = gs:create(canvas,F,[{x,0}, {y,0}, {width, W}, {height, H},{bg,white}]), + gs:create(line, C, [{coords, [{0,H-1},{W,H-1}]}]), + + %% Left side + gs:create(label,F,[{align,w},{x,10}, {y,5}, {width, 100}, + {label,{text, "Black score:"}},{bg,white}]), + gs:create(label,bscore,F,[{align,w},{x,110}, {y,5}, {width, 40}, + {label,{text, "2"}},{bg,white}]), + gs:create(label,F,[{align,w},{x,10}, {y,35}, {width, 100}, + {label,{text, "White score:"}},{bg,white}]), + gs:create(label,wscore,F,[{align,w},{x,110}, {y,35}, {width, 40}, + {label,{text, "2"}},{bg,white}]), + gs:create(label,F,[{align,w},{x,10}, {y,65}, {width, 100}, + {label,{text, "Last draw:"}},{bg,white}]), + gs:create(label,lastdraw,F,[{align,w},{x,110}, {y,65}, {width, 40}, + {label,{text, ""}},{bg,white}]), + + + %% Right side + X2 = trunc(W/2)+10, + gs:create(label,todraw,F,[{align,w},{x,X2}, {y,5}, {width, 100}, + {label,{text, "Black to draw:"}},{bg,white}]), + + gs:create(label,F,[{align,w},{x,X2}, {y,35}, {width, 80}, + {label,{text, "Level:"}},{bg,white}]), + setup_level_menu(F,X2+80,35), + +%% gs:create(label,level,F,[{align,w},{x,X2+80}, {y,35}, {width, 130}, +%% {label,{text, "Intermediate"}},{bg,white}]), + gs:create(label,F,[{align,w},{x,X2}, {y,65}, {width, 80}, + {label,{text, "Colour:"}},{bg,white}]), + setup_col_menu(F,X2+80,65), + +%% gs:create(label,colour,F,[{align,w},{x,X2+80}, {y,65}, {width, 120}, +%% {label,{text, "black (begin)"}},{bg,white}]), + + done. + + +setup_col_menu(P,X,Y) -> + MB = gs:create(menubutton,colour,P, + [{x,X}, {y,Y}, {bw,3}, + %%{width,W}, {height,H}, + {align,w}, {bg,white}, + {relief, raised}, + {activefg,white}, {activebg,black}, + {label, {text,"Colours"}}]), + + M = gs:create(menu,MB,[]), + gs:create(menuitem,M,[{label,{text,"Black (begin)"}}]), + gs:create(menuitem,M,[{label,{text,"Black"}}]), + gs:create(menuitem,M,[{label,{text,"White (begin)"}}]), + gs:create(menuitem,M,[{label,{text,"White"}}]), + done. + +setup_level_menu(P,X,Y) -> + MB = gs:create(menubutton,level,P, + [{x,X}, {y,Y}, + %%{width,W}, {height,H}, + {relief, raised}, + {activefg,white}, {activebg,black}, + {align,w}, {bg,white}, + {label, {text,"Colours"}}]), + + M = gs:create(menu,MB,[]), + gs:create(menuitem,M,[{label,{text,"Beginner"}}]), + gs:create(menuitem,M,[{label,{text,"Intermediate"}}]), + gs:create(menuitem,M,[{label,{text,"Advanced"}}]), + gs:create(menuitem,M,[{label,{text,"Expert"}}]), + done. + + +setup_board(Shell,X,Y,W,H) -> + F = gs:create(frame, Shell,[{x,X}, {y,Y}, + {width,W}, {height,H},{bg,white}]), + display_board(F). + + +mk_button(Label, Parent, X, Y, W, H) -> + gs:create(button,Parent,[{width,W}, {height, H}, {x,X}, {y,Y}, + {label, {text, Label}}, {bg,white}, + {activefg,white}, {activebg,black}]). + +%% Centers a button around Width +mk_button_c(Label, Parent, Width, Y, W, H) -> + X = trunc((Width-W)/2), + gs:create(button,Parent,[{width,W}, {height, H}, {x,X}, {y,Y}, + {label, {text, Label}}, {bg,white}]). + + +butbit(Button,Col) -> + gs:config(Button,[ + {label,{image,bitmap(Col)}}, + {fg, Col}, + {activefg,Col}, + {label, {image, bitmap(Col)}}]), + Button. + +mk_board_butt(Top,Name,X,Y,Col) -> + B = gs:create(button,list_to_atom(Name), Top, + [{x,X}, {y,Y}, {width,60}, {height,60}, + {padx,5},{pady,5}, + {relief,flat}, + {bg,?BGCOL}, {activebg,?BGCOL}]), + butbit(B,Col), + B. + + + +display_board(Top) -> + Board = board(), + display_board(Top,Board,1). + +display_board(_,_,65) -> true; +display_board(Top,[H|T],Place) -> + [Name,Colour,_] = H, + {X,Y} = xy_position(H), + Button = mk_board_butt(Top,Name,X,Y,Colour), + %%Button = mk_button("",Name,Top,X,Y,60,60), + put(Name,Button), + %%Bitmap = bitmap(Colour), + %%butbit(Button,Bitmap), + %%set_widget(Button,"internalWidth","1"), + %%set_widget(Button,"internalHeight","1"), + %%borderWidth(2,Button), + display_board(Top,T,Place+1). + + diff --git a/lib/gs/contribs/othello/priv/marker.bm b/lib/gs/contribs/othello/priv/marker.bm new file mode 100644 index 0000000000..fe7f3df820 --- /dev/null +++ b/lib/gs/contribs/othello/priv/marker.bm @@ -0,0 +1,43 @@ +#define marker2_width 60 +#define marker2_height 60 +static unsigned char marker2_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, + 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, + 0xff, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0xff, 0xff, 0x03, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xfe, 0xff, 0xff, + 0xff, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, + 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x00, 0xc0, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x7f, 0x00, + 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, + 0xff, 0x3f, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0x00, + 0x00, 0xff, 0xff, 0xff, 0xff, 0x9f, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff, + 0xff, 0xcf, 0x1f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xc7, 0x0f, 0x00, + 0x00, 0xfc, 0xff, 0xff, 0xff, 0xe7, 0x07, 0x00, 0x00, 0xf8, 0xff, 0xff, + 0x7f, 0xf1, 0x03, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xbf, 0xfc, 0x03, 0x00, + 0x00, 0xf0, 0xff, 0xff, 0x59, 0xff, 0x01, 0x00, 0x00, 0xe0, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, + 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, + 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/lib/gs/contribs/othello/priv/square.bm b/lib/gs/contribs/othello/priv/square.bm new file mode 100644 index 0000000000..4e6880b330 --- /dev/null +++ b/lib/gs/contribs/othello/priv/square.bm @@ -0,0 +1,43 @@ +#define square_width 60 +#define square_height 60 +static unsigned char square_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |