:- use_module('$REGULUS/PrologLib/utilities', [prettyprint/1]). play_hand(Hand) :- format("O.K., changing this hand~n",[]), choose_hand(Hand). go(N) :- deal(N, Hand), retractall(analysis(_, _)), play_hand(Hand, known(contract(3, notrumps, south), west, []), []). save_state(Hand, Known, Plan):- trace_lvl(P), P >= 2, number_of_actions(_,_,_,N), N > 0, !, name('save/trick',Name), name(N,N1), append(Name,N1,NName), name(File,NName), save_program(File, (spy(play_trick), play_hand(Hand, Known, Plan))). save_state(_, _, _). analyze_suit(Player, Contract, [card(Suit,_)|Cards], Suit, Learned) :- !, next_play(Player, Player1), analyze_suit(Player1, Contract, Cards, Suit, Learned). analyze_suit(Player, contract(_,_,Dec), [card(_,_)|Cards], Suit, [Learnt|Learned]) :- ( next_play(Player,Dec) ; next_play(Dec,Player) ), next_play(Player, Player1), Learnt =..[Suit, void, Player], not(clause(known(Learnt),_)), !, analyze_suit(Player1, contract(_,_,Dec), Cards, Suit, Learned). analyze_suit(Player, Contract, [_|Cards], Suit, Learned) :- next_play(Player, Player1), analyze_suit(Player1, Contract, Cards, Suit, Learned). analyze_suit(_, _, _, _, []). find_new_plan(_, _, _, _) :- retract_it(plan(_,_)), retract_it(other_plans(_)), retract_it(analysis(_,_)), update_actions. update_actions :- retract(action(Action, 1, Suit, Player)), !, assert(action(Action, 2, Suit, Player)), update_actions. update_actions :- retract(action(Action, -1, Suit, Player)), !, assert(action(Action, -2, Suit, Player)), update_actions. update_actions :- !. update_actions(Suit) :- retract(action(Action, 1, Suit, Player)), !, assert(action(Action, 2, Suit, Player)), update_actions(Suit). update_actions(Suit) :- retract(action(Action, -1, Suit, Player)), !, assert(action(Action, -2, Suit, Player)), update_actions(Suit). update_actions(_) :- !. /* The case that the hlp is still valid */ action_taken(WinSuit, Analysis, Tactic1, T1, Tactic2, T2) :- plan((_,HLP),_), hi_lvl_tactic(HLP, WinSuit, HLT1), arg(1, HLT1, Tactic1), arg(3, HLT1, T1), get_tactic(Tactic1, Analysis, HLT2), !, functor(HLT2, Tactic2, _), get_potential(HLT2, T2). get_tactic(develop, Analysis, HLT1) :- member(HLT1, Analysis), functor(HLT1, cash, _), !. % choose cash over finesse if they have the same potential get_tactic(Tactic1, Analysis, HLT1) :- finesseable(Tactic1), member(HLT1, Analysis), functor(HLT1, cash, _), member(HLT2, Analysis), functor(HLT2, Tactic2, _), finesseable(Tactic2), HLT1 =.. [_|Pot], HLT2 =.. [_|Pot], !. % go from dbl1 to finnesse get_tactic(Tactic1, Analysis, HLT1) :- finesseable(Tactic1), member(HLT1, Analysis), functor(HLT1, Tactic2, _), finesseable(Tactic2). get_tactic(Tactic, Analysis, HLT1) :- member(HLT1, Analysis), functor(HLT1, Tactic, _), !. get_tactic(Tactic, Analysis, HLT1) :- finesseable(Tactic), member(HLT1, Analysis), functor(HLT1, cash, _), !. get_potential(HLT, C/CD) :- arg(1,HLT,C), arg(4,HLT,CD). /* Action result checks if something serendipitous has occurred action_result(+Action1, +WinSuit, +Potential1, +Action2, +Potential2, +WinningSide, -Update) */ % 1 action_result(Action1, WinSuit, T1, Action2, T2, Side, Delete, Update), action_result(cash, Suit, W1, _, W2/_, _, _) :- number_of_actions(cash, 1, Suit, N), W2 + N > W1, !, format("Thank you !!!~n",[]), fail. % 2 action_result(cash, _, _, _, _, _, []) :- !. % 3 action_result(develop, Suit, W1+W2-_, _, W3/(_-0), _, _) :- number_of_actions(_, 1, Suit, N), N + W3 > W1 + W2, !, format("Thank you !!!~n",[]), fail. /* 4 go from develop to cash */ action_result(develop, Suit, W1+W2-W, _, W3/(_-0), _, [cash]) :- number_of_actions(_, -1, Suit, W), number_of_actions(_, 1, Suit, N), W3 + N =:= W1 + W2, !. %format("Thank you !!!~n",[]), fail. % 5 action_result(develop, _, _, _, _, _, []) :- !. /* 6 go from finesse+develop to cash */ action_result(Fin, Suit, W1+W2-_, cash, W/(W-0), _, _) :- finesseable(Fin), number_of_actions(_, 1, Suit, N), W1 + W2 =:= W + N, !, format("Thank you !!!~n",[]), fail. /* 7 Win cheaply */ action_result(Fin, _, W, Fin, W/_, declarer, _) :- finesseable(Fin), dev_name(Fin,_), format("Thank you!!!~n",[]), fail. /* 8 go from finesse to cash */ action_result(Fin, Suit, W1, cash, W/_, declarer, _) :- finesseable(Fin), dev_name(Fin,_), number_of_actions(_, 1, Suit, N), W1 < W + N, !, format("Thank you!!!~n",[]), fail. /* 9 go from dbl1 to replan */ action_result(Fin1, _, _, cash, _, declarer, [cash]) :- (Fin1 = dbl1_fin_dec; Fin1 = dbl1_fin_dum). %format("Thank you !!!~n",[]), fail. /* 10 go from finesse to cash */ action_result(Fin, Suit, W1, cash, W/_, declarer, [cash]) :- ( Fin = sim_fin_dec ; Fin = sim_fin_dum ), number_of_actions(_, 1, Suit, N), last_action(1, Suit, _, Action), Action = cash, W1 =:= W + N, !, format("Thank you !!!~n",[]). /* 11 go from finesse to cash */ action_result(Fin, Suit, W1, cash, W/_, declarer, [cash]) :- ( Fin = sim_fin_dec ; Fin = sim_fin_dum ), number_of_actions(_, 1, Suit, N), W1 =:= W + N. % 12 action_result(Fin, Suit, W1, cash, W/_, declarer, []) :- ( Fin = sim_fin_dec ; Fin = sim_fin_dum), number_of_actions(_, 1, Suit, N), W1 > W + N, !, format("Current plan has failed~n",[]), fail. /* 13 repeat finesse */ action_result(Fin, Suit, W1, Fin, W/(W-0), _, []) :- finesseable(Fin), dev_name(Fin,_), number_of_actions(_, 1, Suit, N), W1 =:= W + N, !. /* 14 go from finesse + develop to develop */ action_result(Fin, Suit, W1+W2-L, cash, W3/(W4-L), declarer, []) :- finesseable(Fin), dev_name(_,Fin), number_of_actions(_, 1, Suit, N), W1+W2 =:= W3 + W4 + N, !. /* 15 go from dbl1 to new tactic */ action_result(Fin1, _, _, Tactic, W/(W-0), _, [Tactic]) :- ( Fin1 = dbl1_fin_dec ; Fin1 = dbl1_fin_dum ; Fin1 = dbl2_fin_dec ; Fin1 = dbl2_fin_dum ). /* 16 go from finesse to replan */ action_result(Fin, _, _, cash, _, defender, _) :- finesseable(Fin), !. %fail. last_action(Side, Suit, _, Action) :- action(Action, Side, Suit, _), !. suits_played([card(Suit1,_),card(Suit2,_),card(Suit3,_),card(Suit4,_)], [Suit1,Suit2,Suit3,Suit4]). close_trick :- format("Close Trick? ",[]), get0(_). play_trick(Hand, Played, Leader, Winners, Contract, Plan, [Card1, Card2, Card3, Card4], NHand, Played4, Plan1) :- arg(3,Contract,Dec), ( Leader = Dec ; partner(Leader,Dec) ), order(Leader, Hand, [Player1,Hand1,Player2,Hand2,Player3,Hand3,Player4,Hand4]), ( var(Plan), evaluate_hand(Hand, Contract, Analysis), !, write_analysis(4, Analysis), strategy(Hand, Contract, Winners, Analysis, Leader, LeadSuit, Plans), hi_lvl_plans(Plans, Hi_lvl_plan), winners_losers(Hi_lvl_plan, Win, Lose), format("Hi Level Plan (Potential Winners/Losers = ~d/~d)~n",[Win,Lose]), write_plan(Hi_lvl_plan), arg(3,Contract,Dec), ( partner(Leader,Dec), !, decompose_and_splice(Hi_lvl_plan, Hand3, Hand1, Hand2, Hand4, Contract, Plan) ; decompose_and_splice(Hi_lvl_plan, Hand1, Hand3, Hand2, Hand4, Contract, Plan) ), format("Decomposed Plan after Splicing:~n",[]), write_plan(Plan) ; true ), !, choose_tactic(Leader, Plan, Tactic, Plan1), functor(Tactic,TName,_), arg(2,Tactic,LeadSuit), retract_it(action(_,0,_,_)), asserta(action(TName, 0, LeadSuit,_)), get_suit(Hand1,LeadSuit,DecSuit1), get_suit(Hand2,LeadSuit,DefSuit1), get_suit(Hand3,LeadSuit,DecSuit2), get_suit(Hand4,LeadSuit,DefSuit2), merge(DefSuit1,DefSuit2,DefSuit), tactic_card(Tactic, Contract, Player1, [], DecSuit1, DecSuit2, DefSuit, Card1), print_out(Player1,Card1), replace(Hand1,Card1,Player1,Played,NHand1,Played1), defender_card(Hand2,Player2,LeadSuit,Contract,Card2), print_out(Player2,Card2), replace(Hand2,Card2,Player2,Played1,NHand2,Played2), ( tactic_card(Tactic, Contract, Player3, [Card2,Card1], DecSuit2, DecSuit1, DefSuit, Card3) ; defender_card(Hand3,Player3,LeadSuit,Contract,Card3) ), print_out(Player3,Card3), replace(Hand3,Card3,Player3,Played2,NHand3,Played3), defender_card(Hand4,Player4,LeadSuit,Contract,Card4), print_out(Player4,Card4), replace(Hand4,Card4,Player4,Played3,NHand4,Played4), close_trick, order(Leader, NHand, [Player1,NHand1,Player2,NHand2,Player3,NHand3,Player4,NHand4]), redraw([Card1, Card2, Card3, Card4], [Player1, NHand1, Player2, NHand2, Player3, NHand3, Player4, NHand4], Played1), redraw(NHand). play_trick(Hand, Played, Leader, Winners, Contract, Plan, [Card1, Card2, Card3, Card4], NHand, Played4, Plan1) :- order(Leader, Hand, [Player1,Hand1,Player2,Hand2,Player3,Hand3,Player4,Hand4]), defender_card(Hand1,Player1,LeadSuit,Contract,Card1), print_out(Player1,Card1), replace(Hand1,Card1,Player1,Played,NHand1,Played1), ( var(Plan), evaluate_hand(Hand, Contract, Analysis), !, write_analysis(4, Analysis), strategy(Hand, Contract, Winners, Analysis, Leader, LeadSuit, Plans), hi_lvl_plans(Plans, Hi_lvl_plan), winners_losers(Hi_lvl_plan, Win, Lose), format("Hi Level Plan (Winners/Losers = ~d/~d)~n",[Win,Lose]), write_plan(Hi_lvl_plan), arg(3,Contract,Dec), ( next_play(Leader,Dec), !, decompose_and_splice(Hi_lvl_plan, Hand2, Hand4, Hand1, Hand3, Contract, Plan) ; decompose_and_splice(Hi_lvl_plan, Hand4, Hand2, Hand1, Hand3, Contract, Plan) ), format("Decomposed Plan after Splicing:~n",[]), write_plan(Plan) ; true ), choose_tactic_suit(LeadSuit, Plan, Tactic, Plan1), functor(Tactic,TName,_), arg(2,Tactic,Suit), retract_it(action(_,0,_,_)), asserta(action(TName, 0, Suit,_)), get_suit(Hand1,LeadSuit,DefSuit1), get_suit(Hand2,LeadSuit,DecSuit1), get_suit(Hand3,LeadSuit,DefSuit2), get_suit(Hand4,LeadSuit,DecSuit2), merge(DefSuit1,DefSuit2,DefSuit), ( tactic_card(Tactic, Contract, Player2, [Card1], DecSuit1, DecSuit2, DefSuit, Card2) ; defender_card(Hand2,Player2,LeadSuit,Contract,Card2) ), print_out(Player2,Card2), replace(Hand2,Card2,Player2,Played1,NHand2,Played2), defender_card(Hand3,Player3,LeadSuit,Contract,Card3), print_out(Player3,Card3), replace(Hand3,Card3,Player3,Played2,NHand3,Played3), ( tactic_card(Tactic, Contract, Player4, [Card3,Card2,Card1], DecSuit2, DecSuit1, DefSuit, Card4) ; defender_card(Hand4,Player4,LeadSuit,Contract,Card4) ), print_out(Player4,Card4), replace(Hand4,Card4,Player4,Played3,NHand4,Played4), close_trick, redraw([Card1, Card2, Card3, Card4], [Player1, NHand1, Player2, NHand2, Player3, NHand3, Player4, NHand4], Played1), order(Leader, NHand, [Player1,NHand1,Player2,NHand2,Player3,NHand3,Player4,NHand4]), redraw(NHand). redraw([Card1|Cards],[Name,Hand|Hands],Played) :- redraw(Card1,Hand,Name,Played,played), redraw(Cards,Hands,Played). redraw([],_,_). pick_suit([],LeadSuit,LeadSuit). pick_suit([],_,spades). pick_suit([],_,hearts). pick_suit([],_,diamonds). pick_suit([],_,clubs). pick_suit([C|_],_,SuitName) :- name(Suit,[C]), atom(Suit), suit_initial(SuitName,Suit), !. pick_suit([_|Cs],LeadSuit,SuitName) :- pick_suit(Cs,LeadSuit,SuitName). pick_card([],_) :- !. pick_card([C|_],Value) :- name(Card,[C]), value(Card,Value), !. pick_card([_|Cs],Value) :- pick_card(Cs,Value). follow_suit(_,LeadSuit,_,LeadSuit) :- !. follow_suit(Hand,_,_,LeadSuit) :- not(belong(Hand,LeadSuit,_)), !. follow_suit(Hand,SuitName,_,LeadSuit) :- SuitName \== LeadSuit, belong(Hand,LeadSuit,_), !, %format("You must follow suit~n",[]), fail. in_hand([suit(_,_,[])|Suits],Player,Suit1,Value) :- var(Suit1), !, in_hand(Suits,Player,Suit1,Value). in_hand([suit(_,_,[])|Suits],Player,Suit1,Value) :- var(Value), !, in_hand(Suits,Player,Suit1,Value). in_hand([suit(_,Suit,Cards)|_],_,Suit,Value) :- var(Value), !, append(_,[Value],Cards). in_hand([suit(_,Suit,Cards)|_],_,Suit,Value) :- member(Value,Cards),!. /* in_hand([suit(_,Suit,_)|_],Player,Suit,_) :- format("That card does not exist in ~p's hand ~n",[Player]), !, fail. */ in_hand([_|Suits],Player,Suit,Value) :- in_hand(Suits,Player,Suit,Value). belong([suit(_,Suit,[Card|Cards])|_],Suit,Value) :- !, member(Value,[Card|Cards]). belong([_|Suits],Suit,Value) :- belong(Suits,Suit,Value). find_winner(Player1,[Card1,Card2,Card3,Card4],Contract,WinSuit,Winner,Side) :- next_play(Player1,Player2), winner(Player1,Card1,Player2,Card2,Contract, Winner2, WCard2), next_play(Player2,Player3), winner(Winner2,WCard2,Player3,Card3,Contract,Winner3,WCard3), next_play(Player3,Player4), winner(Winner3,WCard3,Player4,Card4,Contract,Winner,card(WinSuit,_)), arg(3,Contract,Dec), partnership(Winner,Dec,Side), curpos(48,16), format("~p won the trick ~n",Winner), curpos(1,24). partnership(Dec,Dec,declarer) :- !. partnership(Winner,Dec,declarer) :- partner(Winner, Dec), !. partnership(_,_,defender) :- !. winner(P1,card(S1,V1),_, card(S1,V2),contract(_,S1,_),P1,card(S1,V1)) :- V1 > V2,!. winner(_,card(S1,_),P2, card(S1,V2),contract(_,S1,_),P2,card(S1,V2)) :- !. winner(P1,card(S1,V1),_, card(_,_),contract(_,S1,_),P1,card(S1,V1)) :- !. winner(_,card(_,_),P2, card(S2,V2),contract(_,S2,_),P2,card(S2,V2)) :- !. winner(P1,card(S1,V1),_, card(S1,V2),contract(_,_,_),P1,card(S1,V1)) :- V1 > V2,!. winner(_,card(S1,_),P2, card(S1,V2),contract(_,_,_),P2,card(S1,V2)) :- !. winner(P1,card(S1,V1),_, card(_,_),contract(_,_,_),P1,card(S1,V1)). replace(Hand,card(SuitName,Value),Player,Played,NewHand,Played1) :- replace(Hand,card(SuitName,Value),NewHand), redraw(card(SuitName,Value),NewHand,Player,Played,playing), curpos(1,24), add(Played,card(SuitName,Value),Player,Played1). replace([suit(L,SuitName,Cards)|Rest],card(SuitName,Value), [suit(L1,SuitName,NewCards)|Rest]) :- !, delete_card(card(SuitName,Value),Cards,NewCards), L1 is L-1. replace([Suit|Suits],Card,[Suit|Suits1]) :- replace(Suits,Card,Suits1). add(hand(N,S,E,W),Card,north,hand(N1,S,E,W)) :- add_card(N,Card,N1). add(hand(N,S,E,W),Card,south,hand(N,S1,E,W)) :- add_card(S,Card,S1). add(hand(N,S,E,W),Card,east,hand(N,S,E1,W)) :- add_card(E,Card,E1). add(hand(N,S,E,W),Card,west,hand(N,S,E,W1)) :- add_card(W,Card,W1). add_card([suit(L,SuitName,Cards)|Rest],card(SuitName,Value), [suit(L1,SuitName,NewCards)|Rest]) :- !, insert_card(Value,Cards,NewCards), L1 is L+1. add_card([Suit|Suits],Card,[Suit|Suits1]) :- add_card(Suits,Card,Suits1). insert_card(Value,[],[Value]) :- !. insert_card(Value,[X|Xs],[Value,X|Xs]) :- Value >= X, !. insert_card(Value,[X|Xs],[X|Xs1]) :- insert_card(Value,Xs,Xs1). delete_card(card(_,Card),[Card|Cards],Cards) :- !. delete_card(card(_,Card),[Card1|Cards],[Card1|Cards1]) :- delete_card(card(_,Card),Cards,Cards1). order(north,hand(N,S,E,W),[north,N,east,E,south,S,west,W]). order(south,hand(N,S,E,W),[south,S,west,W,north,N,east,E]). order(east,hand(N,S,E,W),[east,E,south,S,west,W,north,N]). order(west,hand(N,S,E,W),[west,W,north,N,east,E,south,S]). redraw(card(SuitName,Value),NewHand,Player,Played,Mode) :- get_suit(NewHand,SuitName,Cards), get_hand(Played,Player,PlayedHand), get_suit(PlayedHand,SuitName,PlayedCards), redraw(Player,SuitName,Value,Cards,PlayedCards,Mode). cards_in_suit([],_,_,_). cards_in_suit([C|Cs],X,Y,Mode) :- C > 28, !, C1 is C - 28, write_card_in_box(C1,underline,X,Y), X1 is X + 3, cards_in_suit(Cs,X1,Y,Mode). cards_in_suit([C|Cs],X,Y,playing) :- C > 14, !, C1 is C - 14, write_card_in_box(C1,blink,X,Y), X1 is X + 3, cards_in_suit(Cs,X1,Y,_). cards_in_suit([C|Cs],X,Y,played) :- C > 14, !, C1 is C - 14, write_card_in_box(C1,underline,X,Y), X1 is X + 3, cards_in_suit(Cs,X1,Y,_). cards_in_suit([C|Cs],X,Y,Mode) :- write_card_in_box(C,normal,X,Y), X1 is X + 3, cards_in_suit(Cs,X1,Y,Mode). get_suit([suit(_,spades,Cards),_,_,_],spades,Cards) :- !. get_suit([_,suit(_,hearts,Cards),_,_],hearts,Cards) :- !. get_suit([_,_,suit(_,diamonds,Cards),_],diamonds,Cards) :- !. get_suit([_,_,_,suit(_,clubs,Cards)],clubs,Cards) :- !. get_suit([_,_,_,_],notrumps,[]). get_hand(hand(N,_,_,_),north,N). get_hand(hand(_,S,_,_),south,S). get_hand(hand(_,_,E,_),east,E). get_hand(hand(_,_,_,W),west,W). partner(Player,Player1) :- next_play(Player,P), next_play(P,Player1). write_analysis(L, analysis(S,H,D,C)) :- trace_lvl(T), ( T >= L, format("Spades: ~p~nHearts: ~p~nDiamonds: ~p~nClubs: ~p~n",[S,H,D,C]) ; true ). write_plans([]) :- !. write_plans([Plan|Plans]) :- write_plan(Plan), write_plans(Plans). write_plan([]) :- !, format("~n",[]). write_plan([Plan|RPlan]) :- format("~p ",[Plan]), write_plan(RPlan). retract_it(Head) :- clause(Head,_), retract(Head), fail. retract_it(_Head). winners_losers([Tactic|Tactics],Winners,Losers) :- arg(1,Tactic,Type), arg(3,Tactic,W), functor(Tactic1,Type,2), arg(2,Tactic1,W), ( (W = W1 + W2 - L, TW is W1 + W2, L1 = L) ; (TW = W, losers(Tactic1,L1)) ), winners_losers(Tactics,Winners1,Losers1), Winners is Winners1 + TW, Losers is Losers1 + L1. winners_losers([],0,0). % START DUPLICATED SECTION /* To evaluate hand, first evaluate each suit evaluate_hand(+Hand,+Contract,-Analysis). */ evaluate_hand(Hand, Contract, analysis(Spades, Hearts, Diamonds, Clubs)) :- evaluate(spades, Hand, Contract, Spades), evaluate(hearts, Hand, Contract, Hearts), evaluate(diamonds, Hand, Contract, Diamonds), evaluate(clubs, Hand, Contract, Clubs). evaluate(Suit, _, _, analysis(Suit,Analysis)) :- clause(analysis(Suit,Analysis),_), !. evaluate(Suit, Hand, Contract, Analysis) :- evaluate_suit(Suit, Hand, Contract, Analysis, _, _), assert(analysis(Suit,Analysis)), !. %remove_2way_finesses(Analysis, LDec, LDum, SAnalysis). /* remove_2way_finesses(Analysis, LDec, LDum, SAnalysis) :- member(sim_fin_dec(C,U,P,DC,DU,DP), Analysis), member(sim_fin_dum(C,U,P,DC,DU,DP), Analysis), ( LDec > LDum, delete(sim_fin_dum(C,U,P,DC,DU,DP), Analysis, SAnalysis); LDum > LDec, delete(sim_fin_dec(C,U,P,DC,DU,DP), Analysis, SAnalysis) ), !. remove_2way_finesses(Analysis, _, _, Analysis). */ evaluate_played_suits([],_,_,[]). evaluate_played_suits([Suit|Suits], Hand, Contract,[Tactic|Tactics]) :- evaluate_suit(Suit, Hand, Contract, Tactic, _, _), evaluate_played_suits(Suits, Hand, Contract, Tactics). evaluate_suit(Suit, Hand, contract(_, Trumps, Declarer), Tactics, LDef, LDum) :- partner(Declarer, Dummy), next_play(Declarer, Defender1), next_play(Dummy, Defender2), get_hand(Hand, Declarer, Dec), get_hand(Hand, Dummy, Dum), get_hand(Hand, Defender1, Def1), get_hand(Hand, Defender2, Def2), get_suit(Dec, Suit, DecCards), get_suit(Dum, Suit, DumCards), length(DecCards,LDef), length(DumCards, LDum), get_suit(Def1, Suit, Def1Cards), get_suit(Def2, Suit, Def2Cards), merge(Def1Cards, Def2Cards, DefCards), readln, top_winners(DecCards, DumCards, DefCards, CWinners, UWinners, PWinners), max_entries(DecCards, DumCards, DefCards, DumEntries), max_entries(DumCards,DecCards, DefCards, DecEntries), %format("Max. Entries Dec/Dum~d/~d~n",[DecEntries, DumEntries]), develop_tricks(DecCards, DumCards, DefCards, 1, CWinLose), develop_tricks(DecCards, DumCards, DefCards, 2, UWinLose), develop_tricks(DecCards, DumCards, DefCards, 3, PWinLose), cash_tactic(CWinLose,UWinLose,PWinLose,CDWinners-CL,UDWinners-UL,PDWinners-PL), finesse_winners(DecCards, DumCards, DefCards, Type1, CFWinners1, UFWinners1, PFWinners1, CDFWinners1, UDFWinners1, PDFWinners1), print_finesse_winners(dummy, Type1, CDWinners, UDWinners, PDWinners, CFWinners1, UFWinners1, PFWinners1, CDFWinners1, UDFWinners1, PDFWinners1, MCDFWinners1, MUDFWinners1, MPDFWinners1), add_tactic([cash(CWinners,UWinners,PWinners, CDWinners-CL,UDWinners-UL,PDWinners-PL), entries(DecEntries, DumEntries)], fin_dum(Type1, CFWinners1, UFWinners1, PFWinners1, MCDFWinners1, MUDFWinners1, MPDFWinners1),Tactic1), finesse_winners(DumCards, DecCards, DefCards, Type2, CFWinners2, UFWinners2, PFWinners2, CDFWinners2, UDFWinners2, PDFWinners2), print_finesse_winners(declarer,Type2, CDWinners, UDWinners, PDWinners, CFWinners2, UFWinners2, PFWinners2, CDFWinners2, UDFWinners2, PDFWinners2, MCDFWinners2, MUDFWinners2, MPDFWinners2), add_tactic(Tactic1, fin_dec(Type2, CFWinners2, UFWinners2, PFWinners2, MCDFWinners2, MUDFWinners2, MPDFWinners2), Tactic2), dfinesse_winners(DecCards, DumCards, DefCards, Certain_df1, Usual_df1, Possible_df1, Certain_df_dev1, Usual_df_dev1, Possible_df_dev1), print_dfinesse_winners(dummy, CDWinners, UDWinners, PDWinners, Certain_df1, Usual_df1, Possible_df1, Certain_df_dev1, Usual_df_dev1, Possible_df_dev1, Certaind_df_dev1, Usuald_df_dev1, Possibled_df_dev1), add_tactic(Tactic2, dbl2_fin_dum(Certain_df1, Usual_df1, Possible_df1, Certaind_df_dev1, Usuald_df_dev1, Possibled_df_dev1), Tactic3), dfinesse_winners(DumCards, DecCards, DefCards, Certain_df2, Usual_df2, Possible_df2, Certain_df_dev2, Usual_df_dev2, Possible_df_dev2), print_dfinesse_winners(declarer, CDWinners, UDWinners, PDWinners, Certain_df2, Usual_df2, Possible_df2, Certain_df_dev2, Usual_df_dev2, Possible_df_dev2, Certaind_df_dev2, Usuald_df_dev2, Possibled_df_dev2), add_tactic(Tactic3, dbl2_fin_dec(Certain_df2, Usual_df2, Possible_df2, Certaind_df_dev2, Usuald_df_dev2, Possibled_df_dev2), Tactics), get_suit(Dum, Trumps, DumTrumps), trump_winners(DecCards, DumCards, DefCards, DumTrumps, Suit, Trumps, Potential1, UTWinners1, PTWinners1), print_trump_winners(dummy, Potential1, UTWinners1, PTWinners1), get_suit(Dec, Trumps, DecTrumps), trump_winners(DumCards, DecCards, DefCards, DecTrumps, Suit, Trumps, Potential2, UTWinners2, PTWinners2), print_trump_winners(declarer, Potential2, UTWinners2, PTWinners2). cash_tactic(CWL, UWL, PWL, WL1, WL2, WL3) :- win_lose(CWL,WL1), win_lose(UWL,WL2), win_lose(PWL,WL3). win_lose(Arg1, W, L) :- win_lose(Arg1, W-L). win_lose([+,X|Rest],W-L) :- win_lose(Rest,W1-L), W is W1 + X. win_lose([-,X|Rest],W-L) :- member('+',Rest), win_lose(Rest,W-L1), L is L1 + X. win_lose([-,_|_], 0-0) :- !. win_lose([], 0-0) :- !. add_tactic(Tactic,dbl2_fin_dec(0,_,_,_,_,_), Tactic). add_tactic(Tactic,dbl2_fin_dum(0,_,_,_,_,_), Tactic). add_tactic(Tactic,fin_dec(_,0,_,_,_,_,_), Tactic) :- !. add_tactic(Tactic,fin_dum(_,0,_,_,_,_,_), Tactic) :- !. add_tactic(Tactic,fin_dec(0, C, U, P, CD, UD, PD), Tactic1) :- find_losers(C,U,P,CD,UD,PD,CL,UL,PL), append(Tactic, [rev_fin_dec(C, U, P, CD-CL, UD-UL, PD-PL)],Tactic1). add_tactic(Tactic,fin_dum(0, C, U, P, CD, UD, PD), Tactic1) :- find_losers(C,U,P,CD,UD,PD,CL,UL,PL), append(Tactic, [rev_fin_dum(C, U, P, CD-CL, UD-UL, PD-PL)],Tactic1). add_tactic(Tactic,fin_dec(1, C, U, P, CD, UD, PD), Tactic1) :- find_losers(C,U,P,CD,UD,PD,CL,UL,PL), append(Tactic, [sim_fin_dec(C ,U ,P, CD-CL, UD-UL, PD-PL)],Tactic1). add_tactic(Tactic,fin_dum(1, C, U, P, CD, UD, PD), Tactic1) :- find_losers(C,U,P,CD,UD,PD,CL,UL,PL), append(Tactic, [sim_fin_dum(C, U, P, CD-CL, UD-UL, PD-PL)],Tactic1). add_tactic(Tactic,fin_dec(2, C, U, P, CD, UD, PD), Tactic1) :- find_losers(C,U,P,CD,UD,PD,CL,UL,PL), append(Tactic, [dbl1_fin_dec(C, U, P, CD-CL, UD-UL, PD-PL)],Tactic1). add_tactic(Tactic,fin_dum(2, C, U, P, CD, UD, PD), Tactic1) :- find_losers(C,U,P,CD,UD,PD,CL,UL,PL), append(Tactic, [dbl1_fin_dum(C ,U, P, CD-CL, UD-UL, PD-PL)],Tactic1). add_tactic(Tactic,dbl2_fin_dec(C, U, P, CD, UD, PD), Tactic1) :- find_losers(C,U,P,CD,UD,PD,CL,UL,PL), ( delete(dbl1_fin_dec(_,_,_,_,_,_), Tactic, NTactic) ; NTactic=Tactic ), append(NTactic, [dbl2_fin_dec(C, U, P, CD-CL, UD-UL, PD-PL)],Tactic1). add_tactic(Tactic,dbl2_fin_dum(C, U, P, CD, UD, PD), Tactic1) :- find_losers(C,U,P,CD,UD,PD,CL,UL,PL), ( delete(dbl1_fin_dum(_,_,_,_,_,_), Tactic, NTactic) ; NTactic=Tactic ), append(NTactic, [dbl2_fin_dum(C, U, P, CD-CL, UD-UL, PD-PL)],Tactic1). find_losers(C,U,P,CD,UD,PD,CL,UL,PL) :- (CD > C, CL = 1; CL = 0), (UD > U, UL = 1; UL = 0), (PD > P, PL = 1; PL = 0). print_trump_winners(_, 0, 0, 0) :- !. print_trump_winners(_Player, _Potential, _UTWinners, _PTWinners) :- !. print_finesse_winners(_, _, _, _, _, 0, 0, 0, _, _, _, 0, 0, 0) :- !. print_finesse_winners(_, 0, CDWinners, UDWinners, PDWinners, _, _, _, CDFWinners,UDFWinners,PDFWinners,MCDFWinners,MUDFWinners,MPDFWinners) :- max(CDFWinners, CDWinners, MCDFWinners), max(UDFWinners, UDWinners, MUDFWinners), max(PDFWinners, PDWinners, MPDFWinners). print_finesse_winners(_, 1, CDWinners, UDWinners, PDWinners, _, _, _, CDFWinners,UDFWinners,PDFWinners,MCDFWinners,MUDFWinners,MPDFWinners) :- max(CDFWinners, CDWinners, MCDFWinners), max(UDFWinners, UDWinners, MUDFWinners), max(PDFWinners, PDWinners, MPDFWinners). print_finesse_winners(_, 2, CDWinners, UDWinners, PDWinners, _, _, _, CDFWinners,UDFWinners,PDFWinners,MCDFWinners,MUDFWinners,MPDFWinners) :- Temp1 is CDWinners - 1, Temp2 is UDWinners - 1, Temp3 is PDWinners - 1, max(CDFWinners, Temp1, MCDFWinners), max(UDFWinners, Temp2, MUDFWinners), max(PDFWinners, Temp3, MPDFWinners). print_dfinesse_winners(_, _, _, _, 0, 0, 0, _, _, _,0, 0, 0) :- !. print_dfinesse_winners(_, CDWinners, UDWinners, PDWinners, _, _, _, CDFWinners,UDFWinners,PDFWinners,MCDFWinners,MUDFWinners,MPDFWinners) :- max(CDFWinners, CDWinners, MCDFWinners), max(UDFWinners, UDWinners, MUDFWinners), max(PDFWinners, PDWinners, MPDFWinners). /* Evaluates how many tricks can be made in a suit in a trump contract */ trump_winners(_, _, _, _, Suit, Suit, 0, 0, 0) :- !. trump_winners(_, _, _, _, _, notrumps, 0, 0, 0) :- !. trump_winners(DecCards, DumCards, DefCards, DumTrumps, _Suit, _Trumps, Potential, UTWinners, PTWinners) :- length(DumCards, LDum), length(DecCards, LDec), LDec > LDum, highest(DefCards, Highest), tops(DecCards, Highest, Tops1), tops(DumCards, Highest, Tops2), Tops is Tops1 + Tops2, length(DumTrumps, TLength), TLength > 0, Small is LDec - Tops, Small > 0, length(DefCards, CDef), UDef is (CDef - 1)//2, PDef is CDef//2, PDef > LDum, !, Rounds1 is UDef - LDum, Delta is LDec - LDum, min(Delta, Small, SDelta), min(SDelta, TLength, Potential), min(Rounds1, Delta, URuffs), min(URuffs, Potential, UTWinners), Rounds2 is PDef - LDum, min(Rounds2, Delta, PRuffs), min(PRuffs, Potential, PTWinners). trump_winners(_, _, _, _, _, _, 0, 0, 0) :- !. /* Calculates number of winners and developed tricks a finesse can generate finesse_winners(+DeclarerCards, +Dummy_Cards, +Defender_Cards, -Finesse_Type, -Certain_Finesse_Winners, -Usual_Finesse_Winners, -Pos_Finesse_Winners, -Certain_Developed_Finesse_Winners, -Usual_Developed_Finesse_Winners, -Pos_Developed_Finesse_Winners).*/ /* Evaluates simple i.e A,Q,x op. x,x and repeating finesse A,J,10, op. x,x */ finesse_winners(DecCards, DumCards, DefCards, Type, CFWinners, UFWinners, PFWinners, CDFWinners, UDFWinners, PDFWinners) :- highest(DefCards, Highest), tops(DecCards, Highest, Tops1), tops(DumCards, Highest, Tops2), Tops2 > 0, length(DumCards, LDum), length(DecCards, LDec), highest_non_winners(DecCards, DumCards, DefCards, DefHigher, HnwDec, HnwDum, Type), reduce(HnwDec, HnwDec1), Hnw is HnwDum + HnwDec1, Hnw >= DefHigher, SmallDum is LDum - Tops2, SmallDec is LDec - Tops1, SmallDec >= DefHigher, SmallDum >= DefHigher, !, min(SmallDec, SmallDum, Small), DevWinners is Hnw + 1 - DefHigher, min(DevWinners, Small, FinWinners), Tops is Tops1 + Tops2 + FinWinners, evaluate_finesse(DefCards, LDec, LDum, Tops, Type, CFWinners, UFWinners, PFWinners, CDFWinners, UDFWinners, PDFWinners). /* Evaluates reverse finesse i.e A,x,x op. Q,x */ finesse_winners(DecCards, DumCards, DefCards, 0, CFWinners, UFWinners, PFWinners, CDFWinners, UDFWinners, PDFWinners) :- highest(DefCards, Highest), tops(DecCards, Highest, Tops1), tops(DumCards, Highest, 0), length(DumCards, LDum), length(DecCards, LDec), highest_non_winners(DecCards, DumCards, DefCards, 1, HnwDec, HnwDum, _), SmallDum is LDum - HnwDum, SmallDum > 0, SmallDec is LDec - Tops1, SmallDec > HnwDec, min(HnwDum, SmallDec, DTops), DTops > 0, max(LDec, LDum, Length), Length > HnwDec + HnwDum, Tops is Tops1 + DTops, evaluate_finesse(DefCards, LDec, LDum, Tops, 2, CFWinners, UFWinners, PFWinners, CDFWinners, UDFWinners, PDFWinners). finesse_winners(_, _, _, _, 0, 0, 0, 0, 0, 0). /* Evaluates double finesse i.e A,K,10 op. x,x dfinesse_winners(+DeclarerCards, +Dummy_Cards, +Defender_Cards, -Certain_Finesse_Winners, -Usual_Finesse_Winners, -Pos_Finesse_Winners, -Certain_Developed_Finesse_Winners, -Usual_Developed_Finesse_Winners, -Pos_Developed_Finesse_Winners).*/ dfinesse_winners(DecCards, DumCards, DefCards, CFWinners, UFWinners, PFWinners, CDFWinners, UDFWinners, PDFWinners) :- highest(DefCards, Highest), tops(DecCards, Highest, Tops1), tops(DumCards, Highest, Tops2), Tops2 >= 2, length(DumCards, LDum), length(DecCards, LDec), highest_non_winners(DecCards, DumCards, DefCards, 2, HnwDec, HnwDum, _), reduce(HnwDec, HnwDec1), Hnw is HnwDum + HnwDec1, SmallDum is LDum - Tops2, SmallDec is LDec - Tops1, SmallDec >= 2, SmallDum >= 1, !, SmallDec1 is SmallDec - 1, min(SmallDec1, SmallDum, Small), min(Hnw, Small, FinWinners), Tops is Tops1 + Tops2 + FinWinners, evaluate_finesse(DefCards, LDec, LDum, Tops, 1, CFWinners, UFWinners, PFWinners, CDFWinners, UDFWinners, PDFWinners). dfinesse_winners(_, _, _, 0, 0, 0, 0, 0, 0). /* Given the number of winners a finesse will generate, evaluate how many tricks can be won and developed in a suit with certain, usual, and possible probabilities evaluate_finesse(+DefCards, +LDec, +LDum, +Winners, +Type, -CFWinners,-UFWinners,-PFWinners,-CDFWinners,-UDFWinners,-PDFWinners) */ evaluate_finesse(DefCards, LDec, LDum, Tops, Type, CFWinners, UFWinners, PFWinners, CDFWinners, UDFWinners, PDFWinners) :- length(DefCards, CDef), max(LDec, LDum, Length), min(Tops,Length,Tops1), winners(Tops1, CDef, Length, Type, CFWinners), UDef is (CDef)//2 + 1, winners(Tops1, UDef, Length, Type, UFWinners), PDef is (CDef + 1)//2, winners(Tops1, PDef, Length, Type, PFWinners), winners_with_finesse(Tops1, CDef, Length, Type, CDFWinners), winners_with_finesse(Tops1, UDef, Length, Type, UDFWinners), winners_with_finesse(Tops1, PDef, Length, Type, PDFWinners). /* Find the number of winners the finesse will win winners_with_finesse(+Tops, +Def_Length, +Dec_Length, +Type, -Winners). */ winners_with_finesse(Tops, Def, Length, 1, Length) :- Tops >= Def, !. winners_with_finesse(Tops, Def, Length, _, Tops) :- Length =< Def, !. winners_with_finesse(Tops, Def, Length, 1, Winners) :- Winners is Tops + Length - Def. winners_with_finesse(Tops, Def, Length, 2, Length1) :- Tops >= Def - 1, !, Length1 is Length - 1. winners_with_finesse(Tops, Def, Length, 2, Winners) :- Winners is Tops + Length - Def, Winners < Length, !. winners_with_finesse(_, _, Length, 2, Length1) :- Length1 is Length - 1. highest_non_winners(DecCards, DumCards, [H1,H2|_], 1, HnwDec, HnwDum, 1) :- remove_winners(DecCards,H1, DecLow), remove_winners(DumCards,H1, DumLow), highest(DecLow, DumLow, Highest), Highest > H2, !, remove_losers(DecLow, H2, DecHnw), remove_losers(DumLow, H2, DumHnw), length(DecHnw, HnwDec), length(DumHnw, HnwDum). highest_non_winners(DecCards, DumCards, [H1,H2,H3|_], 2, HnwDec, HnwDum, 2) :- remove_winners(DecCards, H1, DecLow), remove_winners(DumCards, H1, DumLow), highest(DecLow, DumLow, Highest), Highest < H2, Highest > H3, remove_losers(DecLow, H3, DecHnw), remove_losers(DumLow, H3, DumHnw), length(DecHnw, HnwDec), length(DumHnw, HnwDum). remove_winners([],_,[]) :- !. remove_winners([C|Cs],H,[C|Cs]) :- C < H, !. remove_winners([_|Cs],H, Low) :- remove_winners(Cs, H, Low). remove_losers([],_,[]) :- !. remove_losers([C|_],H, []) :- C < H, !. remove_losers([C|Cs],H,[C|Hnw]) :- remove_losers(Cs, H, Hnw). reduce(N, N1) :- N > 0, !, N1 is N - 1. reduce(N, N). highest([],0) :- !. highest([High|_], High) :- !. highest([],[],0) :- !. highest([],[C|_],C) :- !. highest([C|_],[],C) :- !. highest([C1|_],[C2|_],C1) :- C1 > C2, !. highest([_|_],[C2|_],C2). tops([C|Cards],[D|_],Tops) :- !, tops([C|Cards],D,Tops). tops([C|Cards], Highest, Tops) :- C > Highest, !, tops(Cards, Highest, Tops1), Tops is Tops1 + 1. tops(_, _, 0). top_winners(DecCards, DumCards, DefCards, CWinners, UWinners, PWinners) :- highest(DefCards,Highest), tops(DecCards, Highest, Tops1), tops(DumCards, Highest, Tops2), Tops is Tops1 + Tops2, length(DecCards, LDec), length(DumCards, LDum), max(LDec, LDum, Length), min(Tops,Length,Min), length(DefCards, CDef), winners(Min, CDef, Length, CWinners), UDef is (CDef)//2 + 1, winners(Min, UDef, Length, UWinners), PDef is (CDef + 1)//2, winners(Min, PDef, Length, PWinners). winners(Tops, LDef, Length, Length) :- Tops >= LDef, !. winners(Tops, _, _, Tops). winners(Tops, LDef, Length, 1, Length1) :- winners(Tops, LDef, Length, Length1). winners(Tops, LDef, Length, 2, Length1) :- Tops >= LDef - 1, !, Length1 is Length - 1. winners(Tops, _, _, 2, Tops). /* Find number of entries max_entries(+Cards1, +Cards2, +DefCards, -Entries) */ max_entries(DecCards, DumCards, DefCards, DumEntries) :- highest(DefCards, Highest), small_entries(DecCards, DumCards, Highest, RDecCards, RDumCards, SmallDumEntries), high_entries(RDecCards, RDumCards, Highest, BigDumEntries), DumEntries is SmallDumEntries + BigDumEntries. high_entries([DecCard|DecCards], [DumCard|DumCards], Highest, Entries) :- DecCard > Highest, DecCard < DumCard, !, high_entries(DecCards, DumCards, Highest, Entries1), Entries is Entries1 + 1. high_entries(_, _, _, 0). small_entries([DecCard|DecCards], [DumCard|DumCards], Highest, ODec, ODum, Entries) :- DumCard > Highest, delete_lowest_high([DumCard|DumCards], Highest, RDum), delete_lowest([DecCard|DecCards], RDec), !, small_entries(RDec, RDum, Highest, ODec, ODum, Entries1), Entries is Entries1 + 1. small_entries(Dec, Dum, _, Dec, Dum, 0). delete_lowest_high([C1,C2|Cs], Highest, [C2|Cs]) :- C1 > Highest, C2 < Highest, !. delete_lowest_high([C1,C2|Cs], Highest,[C1|Result]) :- C2 > Highest, !, delete_lowest_high([C2|Cs], Highest, Result). delete_lowest_high([_], _, []) :- !. delete_lowest_and_high(1, DefCards, [Highest|_], DefCards1) :- !, delete_lowest_high(DefCards, Highest, DefCards1). delete_lowest_and_high(2, [C1,C2], [Highest|_], [C1]) :- C2 > Highest, !. delete_lowest_and_high(2, [_,C2], [_|_], [C2]) :- !. delete_lowest_and_high(_, DefCards, [Highest|_], DefCards1) :- delete_lowest_high(DefCards, Highest, DefCards2), delete_lowest(DefCards2, DefCards1). delete_Nlowest(1,L1,L2) :- !, delete_lowest(L1, L2). delete_Nlowest(2,[X,_],[X]) :- !. delete_Nlowest(_,L1,L2) :- !, delete_2lowest(L1, L2). delete_highest([_|Cs],Cs). delete_lowest(List,List1) :- append(List1,[_],List), !. delete_lowest(_,[]) :- !. delete_2lowest(List,List1) :- append(List1,[_,_],List), !. delete_2lowest(_,[]) :- !. /* Find number of tricks that can be won through developent, i.e. cashing winners, and using heuristics such as playing highest non winners, etc. develop_tricks(+DecCards, +DumCards, +DefCards, +Probability, Winners) */ /* Use accumulator */ develop_tricks(DecCards, DumCards, DefCards, Num, Winners) :- developed_winners(DecCards, DumCards, DefCards, Num, [], Winners). developed_winners([], [], _, _, Winners, Winners) :- !. developed_winners(DecCards, DumCards, [], _, Winners, TWinners) :- length(DecCards, LDec), length(DumCards, LDum), LDec >= LDum, !, append(Winners,[+,LDec],TWinners). developed_winners(_, DumCards, [], _, Winners, TWinners) :- !, length(DumCards, LDum), append(Winners,[+,LDum],TWinners). /* If both hands have winners, Cash winner in longest hand */ developed_winners(DecCards, DumCards, DefCards, Num, Winners, TWinners) :- tops(DecCards, DefCards, Tops1), tops(DumCards, DefCards, Tops2), Tops2 > 0, Tops1 > 0, length(DecCards, LDec), length(DumCards, LDum), LDec >= LDum, !, delete_lowest(DecCards, DecCards1), delete_highest(DumCards, DumCards1), delete_Nlowest(Num, DefCards, DefCards1), append(Winners,[+,1],Winners1), developed_winners(DecCards1, DumCards1, DefCards1, Num, Winners1, TWinners). developed_winners(DecCards, DumCards, DefCards, Num, Winners, TWinners) :- tops(DecCards, DefCards, Tops1), tops(DumCards, DefCards, Tops2), Tops2 > 0, Tops1 > 0, !, delete_highest(DecCards, DecCards1), delete_lowest(DumCards, DumCards1), append(Winners,[+,1],Winners1), delete_Nlowest(Num, DefCards, DefCards1), developed_winners(DecCards1, DumCards1, DefCards1, Num, Winners1, TWinners). /* If one hand has winners, cash it */ developed_winners(DecCards, DumCards, DefCards, Num, Winners, TWinners) :- tops(DecCards, DefCards, Tops1), Tops1 > 0, !, delete_highest(DecCards, DecCards1), delete_lowest(DumCards, DumCards1), delete_Nlowest(Num, DefCards, DefCards1), append(Winners,[+,1],Winners1), developed_winners(DecCards1, DumCards1, DefCards1, Num, Winners1, TWinners). developed_winners(DecCards, DumCards, DefCards, Num, Winners, TWinners) :- tops(DumCards, DefCards, Tops2), Tops2 > 0, !, delete_lowest(DecCards, DecCards1), delete_highest(DumCards, DumCards1), delete_Nlowest(Num, DefCards, DefCards1), append(Winners,[+,1],Winners1), developed_winners(DecCards1, DumCards1, DefCards1, Num, Winners1, TWinners). /* If no hand has a winner, and only one hand has highest non winner - play it*/ developed_winners(DecCards, DumCards, DefCards, Num, Winners, TWinners) :- number_higher(DecCards, DefCards, Higher_Dec), number_higher(DumCards, DefCards, Higher_Dum), Higher_Dec < Higher_Dum, !, delete_highest(DecCards, DecCards1), delete_lowest(DumCards, DumCards1), delete_lowest_and_high(Num, DefCards, DecCards, DefCards1), append(Winners,[-,1],Winners1), developed_winners(DecCards1, DumCards1, DefCards1, Num, Winners1, TWinners). developed_winners(DecCards, DumCards, DefCards, Num, Winners, TWinners) :- number_higher(DecCards, DefCards, Higher_Dec), number_higher(DumCards, DefCards, Higher_Dum), Higher_Dec > Higher_Dum, !, delete_lowest(DecCards, DecCards1), delete_highest(DumCards, DumCards1), delete_lowest_and_high(Num, DefCards, DumCards, DefCards1), append(Winners,[-,1],Winners1), developed_winners(DecCards1, DumCards1, DefCards1, Num, Winners1, TWinners). /* If no hand has a winner, and both have highest non winner play the highest non winner from the shorter hand */ developed_winners(DecCards, DumCards, DefCards, Num, Winners, TWinners) :- length(DecCards, LDec), length(DumCards, LDum), LDec >= LDum, !, delete_lowest(DecCards, DecCards1), delete_highest(DumCards, DumCards1), delete_lowest_and_high(Num, DefCards, DumCards, DefCards1), append(Winners,[-,1],Winners1), developed_winners(DecCards1, DumCards1, DefCards1, Num, Winners1, TWinners). developed_winners(DecCards, DumCards, DefCards, Num, Winners, TWinners) :- !, delete_highest(DecCards, DecCards1), delete_lowest(DumCards, DumCards1), delete_lowest_and_high(Num, DefCards, DecCards, DefCards1), append(Winners,[-,1],Winners1), developed_winners(DecCards1, DumCards1, DefCards1, Num, Winners1, TWinners). number_higher([], _, 13) :- !. number_higher([C|_], [D|DefCards], Higher) :- C < D, !, number_higher([C|_], DefCards, Higher1), Higher is Higher1 + 1. number_higher(_, _, 0). % END DUPLICATED SECTION % ================================================================== % draw.pl % % A file for nice output of hands, etc. % % Author - Yossi Nygate . % Last Modified - October 28, 1988. % ================================================================== /* Predicates list : predicate name number of arguments -------------- ------------------- write_deal 1 write_full_hand 2 write_titled_suits 3 cards_in_box 3 write_card_in_box 4 initial_string 2 card_to_string 3 */ write_deal(hand(N,S,E,W)) :- format(" West North ",[]), format(" East South~n",[]), write_full_hand(W,N,E,S). write_full_hand([],[],[],[]). write_full_hand([suit(WL,Suit,WCards)|WSuits], [suit(NL,_,NCards)|NSuits], [suit(EL,_,ECards)|ESuits], [suit(SL,_,SCards)|SSuits]) :- suit_initial(Suit,I), format("~p: ",[I]), write_suit(WCards), fillin(WL), format("~p: ",[I]), write_suit(NCards), fillin(NL), format("~p: ",[I]), write_suit(ECards), fillin(EL), format("~p: ",[I]), write_suit(SCards), fillin(SL), format("~n",[]), write_full_hand(WSuits, NSuits, ESuits, SSuits). fillin(L) :- Spaces is 17 - L*2, tab(Spaces). tab(I) :- I =< 0, !. tab(I) :- I > 0, format(" ", []), I1 is I - 1, !, tab(I1). write_suit([]). write_suit([C|Cs]) :- format("~p ",[C]), write_suit(Cs). find_contract(contract(Level,SuitName,Declarer),Lead) :- format("What is the contract? ",[]), read_line(Line), [C1, C2 | _ ] = Line, name(Level,[C1]), name(Suit,[C2]), suit_initial(SuitName,Suit), !, format("Who is declarer? ",[]), read_line([C3|_]), name(Dec,[C3]), player_initial(Declarer,Dec), format("Contract: ~d ~p by ~p, ",[Level,SuitName,Declarer]), next_play(Declarer,Lead), format("~p on lead.~n",[Lead]). update_winners(winners(Dec,Def),Player,contract(_,_,Player), winners(Dec1,Def)) :- !, Dec1 is Dec + 1, format("Tricks - Declarer ~d, Defender ~d~n",[Dec1, Def]). update_winners(winners(Dec,Def),Player1,contract(_,_,Player), winners(Dec1,Def)) :- partner(Player,Player1), !, Dec1 is Dec + 1, format("Tricks - Declarer ~d, Defender ~d~n",[Dec1, Def]). update_winners(winners(Dec,Def),_,_,winners(Dec,Def1)) :- !, Def1 is Def + 1, format("Tricks - Declarer ~d, Defender ~d~n",[Dec, Def1]). redraw(_,_,_,_,_,_). readln. curpos(_,_). co_ordinates(_,_,_,_,_). update_x(_,_). update_y(_,_,_). cards_in_box(_,_,_,_). print_out(Player,card(Suit,Value)) :- format("~p - Playing the ~p of ~p~n",[Player,Value,Suit]). redraw(Deal) :- write_deal(Deal). deal(1, hand([suit(1,spades,[2]),suit(3,hearts,[9,7,3]), suit(5,diamonds,[14,13,8,3,2]),suit(4,clubs,[14,12,9,5])], [suit(5,spades,[14,12,11,10,3]),suit(5,hearts,[14,13,12,8,5]), suit(2,diamonds,[6,5]),suit(1,clubs,[10])], [suit(4,spades,[13,7,6,5]),suit(2,hearts,[10,4]), suit(2,diamonds,[9,7]),suit(5,clubs,[8,7,6,3,2])], [suit(3,spades,[9,8,4]),suit(3,hearts,[11,6,2]), suit(4,diamonds,[12,11,10,4]),suit(3,clubs,[13,11,4])]) ). deal('1a', hand([suit(1,spades,[2]),suit(3,hearts,[9,7,3]), suit(5,diamonds,[14,13,8,3,2]),suit(4,clubs,[14,9,5,2])], [suit(5,spades,[14,13,12,11,10]),suit(5,hearts,[14,13,12,11,10]), suit(2,diamonds,[6,5]),suit(1,clubs,[10])], [suit(4,spades,[7,6,5,3]),suit(2,hearts,[8,4]), suit(2,diamonds,[9,7]),suit(5,clubs,[12,8,7,6,3])], [suit(3,spades,[9,8,4]),suit(3,hearts,[6,5,2]), suit(4,diamonds,[12,11,10,4]),suit(3,clubs,[13,11,4])]) ). deal(2, hand([suit(2,spades,[4,3]),suit(4,hearts,[9,7,4,3]), suit(3,diamonds,[14,12,5]),suit(4,clubs,[13,10,8,7])], [suit(3,spades,[14,13,6]),suit(3,hearts,[14,10,8]), suit(3,diamonds,[13,9,3]),suit(4,clubs,[12,11,9,6])], [suit(4,spades,[12,7,5,2]),suit(4,hearts,[13,11,5,2]), suit(3,diamonds,[10,8,2]),suit(2,clubs,[5,3])], [suit(4,spades,[11,10,9,8]),suit(2,hearts,[12,6]), suit(4,diamonds,[11,7,6,4]),suit(3,clubs,[14,4,2])]) ). deal(3, hand([suit(2,spades,[3,2]),suit(3,hearts,[13,12,2]), suit(5,diamonds,[14,5,4,3,2]),suit(3,clubs,[4,3,2])], [suit(3,spades,[14,13,4]),suit(3,hearts,[11,10,3]), suit(3,diamonds,[8,7,6]),suit(4,clubs,[14,13,6,5])], [suit(4,spades,[12,11,10,9]),suit(3,hearts,[6,5,4]), suit(3,diamonds,[11,9,8]),suit(4,clubs,[9,8,7])], [suit(4,spades,[8,7,6,5]),suit(4,hearts,[14,9,8,7]), suit(2,diamonds,[13,12]),suit(3,clubs,[12,11,10])]) ). b0 :- play_hand(hand( [suit(1,spades,[12]),suit(1,hearts,[3]), suit(1,diamonds,[14]),suit(0,clubs,[])], [suit(1,spades,[3]),suit(2,hearts,[14,11]), suit(0,diamonds,[]),suit(0,clubs,[])], [suit(1,spades,[14]),suit(2,hearts,[13,12]), suit(0,diamonds,[]),suit(0,clubs,[])], [suit(1,spades,[2]),suit(1,hearts,[5]), suit(1,diamonds,[5]),suit(0,clubs,[])])). b1 :- play_hand(hand([suit(1,spades,[2]),suit(3,hearts,[9,7,3]), suit(5,diamonds,[14,13,8,3,2]),suit(4,clubs,[14,12,9,5])], [suit(5,spades,[14,12,11,10,3]),suit(5,hearts,[14,13,12,8,5]), suit(2,diamonds,[6,5]),suit(1,clubs,[10])], [suit(4,spades,[13,7,6,5]),suit(2,hearts,[10,4]), suit(2,diamonds,[9,7]),suit(5,clubs,[8,7,6,3,2])], [suit(3,spades,[9,8,4]),suit(3,hearts,[11,6,2]), suit(4,diamonds,[12,11,10,4]),suit(3,clubs,[13,11,4])])). b2 :- play_hand(hand( [suit(4,spades,[12,10,8,4]),suit(2,hearts,[11,3]), suit(3,diamonds,[14,12,10]),suit(4,clubs,[14,10,8,7])], [suit(4,spades,[11,9,7,3]),suit(3,hearts,[14,10,4]), suit(2,diamonds,[11,8]),suit(4,clubs,[6,5,4,2])], [suit(2,spades,[14,5]),suit(2,hearts,[13,12]), suit(6,diamonds,[13,9,7,6,3,2]),suit(3,clubs,[11,9,3])], [suit(3,spades,[13,6,2]),suit(6,hearts,[9,8,7,6,5,2]), suit(2,diamonds,[5,4]),suit(2,clubs,[13,12])])). b3 :- play_hand(hand( [suit(1,spades,[2]),suit(3,hearts,[9,7,3]), suit(5,diamonds,[14,13,8,3,2]),suit(4,clubs,[14,10,9,5])], [suit(5,spades,[14,13,12,11,10]),suit(5,hearts,[14,13,8,5,2]), suit(2,diamonds,[6,5]),suit(1,clubs,[12])], [suit(4,spades,[7,6,5,3]),suit(2,hearts,[10,4]), suit(2,diamonds,[9,7]),suit(5,clubs,[8,7,6,3,2])], [suit(3,spades,[9,8,4]),suit(3,hearts,[12,11,6]), suit(4,diamonds,[12,11,10,4]),suit(3,clubs,[13,11,4])])). b4 :- play_hand(hand( [suit(4,spades,[13,9,6,3]),suit(2,hearts,[14,10]), suit(2,diamonds,[14,5]),suit(5,clubs,[14,6,5,3,2])], [suit(7,spades,[14,12,8,7,5,4,2]),suit(2,hearts,[9,5]), suit(1,diamonds,[11]),suit(3,clubs,[10,8,4])], [suit(1,spades,[10]),suit(6,hearts,[13,11,7,6,4,2]), suit(6,diamonds,[13,12,9,7,6,3]),suit(0,clubs,[])], [suit(1,spades,[11]),suit(3,hearts,[12,8,3]), suit(4,diamonds,[10,8,4,2]),suit(5,clubs,[13,12,11,9,7])])). b5 :- play_hand(hand( [suit(1,spades,[2]),suit(3,hearts,[9,7,3]), suit(5,diamonds,[14,13,8,3,2]),suit(4,clubs,[14,12,9,5])], [suit(5,spades,[14,12,11,10,3]),suit(5,hearts,[14,13,8,5,2]), suit(2,diamonds,[6,5]),suit(1,clubs,[10])], [suit(4,spades,[13,7,6,5]),suit(2,hearts,[10,4]), suit(2,diamonds,[9,7]),suit(5,clubs,[8,7,6,3,2])], [suit(3,spades,[9,8,4]),suit(3,hearts,[12,11,6]), suit(4,diamonds,[12,11,10,4]),suit(3,clubs,[13,11,4])])). b6 :- play_hand(hand( [suit(3,spades,[8,7,6]),suit(2,hearts,[8,7]), suit(4,diamonds,[14,13,8,7]),suit(4,clubs,[14,12,7,6])], [suit(4,spades,[14,13,12,2]),suit(5,hearts,[14,13,12,11,9]), suit(2,diamonds,[3,2]),suit(2,clubs,[13,2])], [suit(3,spades,[11,10,9]),suit(3,hearts,[6,5,2]), suit(3,diamonds,[6,5,4]),suit(4,clubs,[11,10,9,8])], [suit(3,spades,[5,4,3]),suit(3,hearts,[10,4,3]), suit(4,diamonds,[12,11,10,9]),suit(3,clubs,[5,4,3])])). b7 :- play_hand(hand( [suit(1,spades,[2]),suit(3,hearts,[9,7,3]), suit(5,diamonds,[14,13,8,3,2]),suit(4,clubs,[14,11,9,5])], [suit(5,spades,[14,13,12,11,10]),suit(5,hearts,[14,13,8,5,2]), suit(2,diamonds,[6,5]),suit(1,clubs,[12])], [suit(4,spades,[7,6,5,3]),suit(2,hearts,[10,4]), suit(2,diamonds,[9,7]),suit(5,clubs,[8,7,6,3,2])], [suit(3,spades,[9,8,4]),suit(3,hearts,[12,11,6]), suit(4,diamonds,[12,11,10,4]),suit(3,clubs,[13,10,4])])). b8 :- play_hand(hand( [suit(2,spades,[13,11]),suit(3,hearts,[10,9,3]), suit(4,diamonds,[14,12,11,3]),suit(4,clubs,[14,13,11,10])], [suit(4,spades,[14,10,9,2]),suit(4,hearts,[14,12,11,2]), suit(2,diamonds,[10,9]),suit(3,clubs,[5,4,3])], [suit(3,spades,[5,4,3]),suit(3,hearts,[13,8,7]), suit(3,diamonds,[13,8,7]),suit(4,clubs,[8,7,6,2])], [suit(4,spades,[12,8,7,6]),suit(3,hearts,[6,5,4]), suit(4,diamonds,[6,5,4,2]),suit(2,clubs,[12,9])])). b9 :- play_hand(hand( [suit(2,spades,[13,11]),suit(2,hearts,[11,4]), suit(3,diamonds,[14,11,3]),suit(6,clubs,[14,11,10,8,7,5])], [suit(2,spades,[14,2]),suit(4,hearts,[14,12,3,2]), suit(4,diamonds,[13,10,9,2]),suit(3,clubs,[13,3,2])], [suit(3,spades,[5,4,3]),suit(3,hearts,[10,9,8]), suit(4,diamonds,[8,7,6,5]),suit(3,clubs,[12,9,6])], [suit(6,spades,[12,10,9,8,7,6]),suit(4,hearts,[13,7,6,5]), suit(2,diamonds,[12,4]),suit(1,clubs,[4])])). b10 :- play_hand(hand( [suit(5,spades,[14,11,10,4,3]),suit(4,hearts,[14,13,11,10]), suit(4,diamonds,[14,13,11,9]),suit(0,clubs,[])], [suit(2,spades,[13,2]),suit(3,hearts,[4,3,2]), suit(3,diamonds,[4,3,2]),suit(5,clubs,[14,13,12,10,9])], [suit(2,spades,[6,5]),suit(3,hearts,[12,9,8]), suit(3,diamonds,[12,10,8]),suit(5,clubs,[6,5,4,3,2])], [suit(4,spades,[12,9,8,7]),suit(3,hearts,[7,6,5]), suit(3,diamonds,[7,6,5]),suit(3,clubs,[11,8,7])])). b11 :- play_hand(hand( [suit(5,spades,[14,11,9,4,3]),suit(4,hearts,[14,11,10,8]), suit(4,diamonds,[14,11,10,9]),suit(0,clubs,[])], [suit(2,spades,[13,2]),suit(3,hearts,[13,3,2]), suit(3,diamonds,[13,3,2]),suit(5,clubs,[14,13,12,11,9])], [suit(2,spades,[6,5]),suit(3,hearts,[12,9,4]), suit(3,diamonds,[12,8,4]),suit(5,clubs,[6,5,4,3,2])], [suit(4,spades,[12,10,8,7]),suit(3,hearts,[7,6,5]), suit(3,diamonds,[7,6,5]),suit(3,clubs,[10,8,7])])). b12 :- play_hand(hand( [suit(5,spades,[14,11,10,4,3]),suit(4,hearts,[13,12,11,2]), suit(4,diamonds,[14,11,10,9]),suit(0,clubs,[])], [suit(2,spades,[13,2]),suit(3,hearts,[5,4,3]), suit(3,diamonds,[13,3,2]),suit(5,clubs,[14,13,12,11,9])], [suit(2,spades,[6,5]),suit(3,hearts,[10,9,8]), suit(3,diamonds,[12,8,4]),suit(5,clubs,[6,5,4,3,2])], [suit(4,spades,[12,9,8,7]),suit(3,hearts,[14,7,6]), suit(3,diamonds,[7,6,5]),suit(3,clubs,[10,8,7])])). b13 :- play_hand(hand( [suit(4,spades,[14,11,10,5]),suit(2,hearts,[3,2]), suit(4,diamonds,[5,4,3,2]),suit(3,clubs,[14,3,2])], [suit(3,spades,[4,3,2]),suit(4,hearts,[14,13,10,9]), suit(3,diamonds,[14,12,10]),suit(3,clubs,[11,10,9])], [suit(3,spades,[13,9,8]),suit(3,hearts,[12,11,8]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,12,8,7])], [suit(3,spades,[12,7,6]),suit(4,hearts,[7,6,5,4]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b13a :- play_hand(hand( [suit(3,spades,[14,11,10]),suit(3,hearts,[4,3,2]), suit(4,diamonds,[5,4,3,2]),suit(3,clubs,[14,3,2])], [suit(3,spades,[4,3,2]),suit(4,hearts,[14,13,10,9]), suit(3,diamonds,[14,12,10]),suit(3,clubs,[11,10,9])], [suit(3,spades,[13,12,8]),suit(3,hearts,[12,11,8]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,12,8,7])], [suit(4,spades,[9,7,6,5]),suit(3,hearts,[7,6,5]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b13b :- play_hand(hand( [suit(4,spades,[14,11,10,9]),suit(3,hearts,[4,3,2]), suit(3,diamonds,[5,4,3]),suit(3,clubs,[14,3,2])], [suit(3,spades,[4,3,2]),suit(4,hearts,[14,13,10,9]), suit(3,diamonds,[14,12,10]),suit(3,clubs,[11,10,9])], [suit(3,spades,[12,8,7]),suit(3,hearts,[12,11,8]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,12,8,7])], [suit(3,spades,[13,6,5]),suit(3,hearts,[7,6,5]), suit(4,diamonds,[8,7,6,5]),suit(3,clubs,[6,5,4])])). b13c :- play_hand(hand( [suit(4,spades,[14,11,10,9]),suit(3,hearts,[4,3,2]), suit(3,diamonds,[4,3,2]),suit(3,clubs,[14,3,2])], [suit(3,spades,[4,3,2]),suit(4,hearts,[14,13,10,9]), suit(3,diamonds,[14,12,10]),suit(3,clubs,[11,10,9])], [suit(3,spades,[12,8,7]),suit(3,hearts,[12,11,8]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,12,8,7])], [suit(3,spades,[13,6,5]),suit(3,hearts,[7,6,5]), suit(4,diamonds,[8,7,6,5]),suit(3,clubs,[6,5,4])])). b13d :- play_hand(hand( [suit(4,spades,[14,11,10,9]),suit(3,hearts,[4,3,2]), suit(3,diamonds,[4,3,2]),suit(3,clubs,[14,3,2])], [suit(3,spades,[4,3,2]),suit(4,hearts,[14,13,10,9]), suit(3,diamonds,[14,12,10]),suit(3,clubs,[11,10,9])], [suit(3,spades,[12,8,7]),suit(3,hearts,[11,8,7]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,12,8,7])], [suit(3,spades,[13,6,5]),suit(3,hearts,[12,6,5]), suit(4,diamonds,[8,7,6,5]),suit(3,clubs,[6,5,4])])). b13e :- play_hand(hand( [suit(3,spades,[14,11,10]),suit(3,hearts,[4,3,2]), suit(4,diamonds,[5,4,3,2]),suit(3,clubs,[14,3,2])], [suit(3,spades,[4,3,2]),suit(4,hearts,[14,13,10,9]), suit(3,diamonds,[12,11,10]),suit(3,clubs,[11,10,9])], [suit(3,spades,[13,12,8]),suit(3,hearts,[12,11,8]), suit(3,diamonds,[14,9,8]),suit(4,clubs,[13,12,8,7])], [suit(4,spades,[9,7,6,5]),suit(3,hearts,[7,6,5]), suit(3,diamonds,[13,7,6]),suit(3,clubs,[6,5,4])])). b14 :- play_hand(hand( [suit(3,spades,[14,11,10]),suit(4,hearts,[5,4,3,2]), suit(4,diamonds,[5,4,3,2]),suit(2,clubs,[14,3])], [suit(3,spades,[4,3,2]),suit(3,hearts,[14,13,10]), suit(3,diamonds,[14,12,10]),suit(4,clubs,[11,10,9,2])], [suit(3,spades,[13,9,8]),suit(3,hearts,[12,11,8]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,12,8,7])], [suit(4,spades,[12,7,6,5]),suit(3,hearts,[9,7,6]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b15 :- play_hand(hand( [suit(5,spades,[14,11,10,3,2]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(2,clubs,[14,3])], [suit(1,spades,[4]),suit(5,hearts,[14,13,10,3,2]), suit(3,diamonds,[14,12,10]),suit(4,clubs,[11,10,9,2])], [suit(3,spades,[13,9,8]),suit(3,hearts,[12,11,8]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,12,8,7])], [suit(4,spades,[12,7,6,5]),suit(3,hearts,[9,7,6]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b16 :- play_hand(hand( [suit(5,spades,[14,11,10,3,2]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(2,clubs,[14,8])], [suit(2,spades,[5,4]),suit(4,hearts,[14,13,11,10]), suit(3,diamonds,[14,12,10]),suit(4,clubs,[11,10,9,7])], [suit(4,spades,[13,9,8,6]),suit(2,hearts,[12,8]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,12,3,2])], [suit(2,spades,[12,7]),suit(5,hearts,[9,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b17 :- play_hand(hand( [suit(5,spades,[14,11,10,3,2]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(2,clubs,[14,8])], [suit(3,spades,[6,5,4]),suit(3,hearts,[14,13,11]), suit(3,diamonds,[14,12,10]),suit(4,clubs,[11,10,9,7])], [suit(3,spades,[13,9,8]),suit(3,hearts,[12,10,8]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,12,3,2])], [suit(2,spades,[12,7]),suit(5,hearts,[9,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b18 :- play_hand(hand( [suit(5,spades,[14,11,10,3,2]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(2,clubs,[14,8])], [suit(3,spades,[6,5,4]),suit(3,hearts,[14,13,11]), suit(3,diamonds,[14,12,11]),suit(4,clubs,[11,10,9,7])], [suit(3,spades,[13,9,8]),suit(3,hearts,[12,10,8]), suit(3,diamonds,[13,10,9]),suit(4,clubs,[13,12,3,2])], [suit(2,spades,[12,7]),suit(5,hearts,[9,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b19 :- play_hand(hand( [suit(5,spades,[14,11,9,4,3]),suit(4,hearts,[14,11,10,8]), suit(4,diamonds,[14,11,10,9]),suit(0,clubs,[])], [suit(2,spades,[13,2]),suit(3,hearts,[13,3,2]), suit(3,diamonds,[13,3,2]),suit(5,clubs,[14,13,12,11,9])], [suit(2,spades,[6,5]),suit(3,hearts,[12,9,4]), suit(3,diamonds,[12,8,4]),suit(5,clubs,[10,6,5,4,3])], [suit(4,spades,[12,10,8,7]),suit(3,hearts,[7,6,5]), suit(3,diamonds,[7,6,5]),suit(3,clubs,[8,7,2])])). b20 :- play_hand(hand( [suit(5,spades,[14,11,10,3,2]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(2,clubs,[14,8])], [suit(1,spades,[4]),suit(4,hearts,[14,11,10,2]), suit(3,diamonds,[14,12,11]),suit(5,clubs,[12,10,9,7,2])], [suit(5,spades,[13,9,8,6,5]),suit(2,hearts,[12,8]), suit(3,diamonds,[13,10,9]),suit(3,clubs,[13,11,3])], [suit(2,spades,[12,7]),suit(5,hearts,[13,9,7,6,3]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b21 :- play_hand(hand( [suit(5,spades,[14,11,10,3,2]),suit(1,hearts,[5]), suit(4,diamonds,[5,4,3,2]),suit(3,clubs,[14,8,3])], [suit(1,spades,[4]),suit(4,hearts,[14,13,11,10]), suit(3,diamonds,[14,12,10]),suit(5,clubs,[12,10,6,5,4])], [suit(5,spades,[13,9,8,6,5]),suit(3,hearts,[12,8,4]), suit(3,diamonds,[13,11,9]),suit(2,clubs,[13,11])], [suit(2,spades,[12,7]),suit(5,hearts,[9,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[9,7,2])])). b22 :- play_hand(hand( [suit(5,spades,[14,11,10,3,2]),suit(2,hearts,[5,4]), suit(4,diamonds,[9,4,3,2]),suit(2,clubs,[14,8])], [suit(1,spades,[4]),suit(4,hearts,[14,13,10,9]), suit(3,diamonds,[14,12,10]),suit(5,clubs,[12,10,9,7,2])], [suit(5,spades,[13,9,8,6,5]),suit(2,hearts,[12,8]), suit(3,diamonds,[13,11,5]),suit(3,clubs,[13,11,3])], [suit(2,spades,[12,7]),suit(5,hearts,[11,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b23 :- play_hand(hand( [suit(5,spades,[14,11,10,3,2]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(2,clubs,[14,8])], [suit(2,spades,[5,4]),suit(4,hearts,[14,13,11,10]), suit(3,diamonds,[14,12,10]),suit(4,clubs,[12,11,9,7])], [suit(4,spades,[13,9,8,6]),suit(2,hearts,[12,8]), suit(3,diamonds,[13,11,9]),suit(4,clubs,[13,10,3,2])], [suit(2,spades,[12,7]),suit(5,hearts,[9,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(3,clubs,[6,5,4])])). b24 :- play_hand(hand( [suit(5,spades,[12,10,6,4,3]),suit(1,hearts,[11]), suit(3,diamonds,[14,12,10]),suit(4,clubs,[14,10,8,7])], [suit(3,spades,[11,7,5]),suit(4,hearts,[14,10,4,3]), suit(2,diamonds,[11,8]),suit(4,clubs,[6,5,4,2])], [suit(2,spades,[14,9]),suit(2,hearts,[13,12]), suit(6,diamonds,[13,9,7,6,3,2]),suit(3,clubs,[11,9,3])], [suit(3,spades,[13,8,2]),suit(6,hearts,[9,8,7,6,5,2]), suit(2,diamonds,[5,4]),suit(2,clubs,[13,12])])). b25 :- play_hand(hand( [suit(3,spades,[14,13,2]),suit(3,hearts,[4,3,2]), suit(3,diamonds,[14,13,11]),suit(4,clubs,[14,7,6,5])], [suit(5,spades,[12,10,9,8,7]),suit(4,hearts,[14,13,11,10]), suit(2,diamonds,[4,3]),suit(2,clubs,[13,3])], [suit(4,spades,[11,5,4,3]),suit(4,hearts,[12,9,8,7]), suit(4,diamonds,[12,9,8,7]),suit(1,clubs,[2])], [suit(1,spades,[6]),suit(2,hearts,[6,5]), suit(4,diamonds,[10,6,5,2]),suit(6,clubs,[12,11,10,9,8,4])])). b26 :- play_hand(hand( [suit(3,spades,[14,13,2]),suit(3,hearts,[4,3,2]), suit(3,diamonds,[14,13,10]),suit(4,clubs,[14,7,6,5])], [suit(5,spades,[12,10,9,8,7]),suit(4,hearts,[14,13,11,10]), suit(2,diamonds,[4,3]),suit(2,clubs,[4,3])], [suit(4,spades,[11,5,4,3]),suit(4,hearts,[12,9,8,7]), suit(4,diamonds,[12,9,8,7]),suit(1,clubs,[2])], [suit(1,spades,[6]),suit(2,hearts,[6,5]), suit(4,diamonds,[11,6,5,2]),suit(6,clubs,[13,12,11,10,9,8])])). b27 :- play_hand(hand( [suit(2,spades,[13,11]),suit(2,hearts,[11,4]), suit(3,diamonds,[14,11,3]),suit(6,clubs,[14,11,10,8,7,5])], [suit(2,spades,[14,2]),suit(4,hearts,[14,12,3,2]), suit(4,diamonds,[13,10,9,2]),suit(3,clubs,[13,3,2])], [suit(3,spades,[5,4,3]),suit(3,hearts,[10,9,8]), suit(4,diamonds,[8,7,6,5]),suit(3,clubs,[9,6,4])], [suit(6,spades,[12,10,9,8,7,6]),suit(4,hearts,[13,7,6,5]), suit(2,diamonds,[12,4]),suit(1,clubs,[12])])). b27a :- play_hand(hand( [suit(2,spades,[13,11]),suit(2,hearts,[11,4]), suit(3,diamonds,[14,11,3]),suit(6,clubs,[14,11,10,8,7,5])], [suit(2,spades,[14,2]),suit(4,hearts,[14,12,3,2]), suit(4,diamonds,[13,10,9,2]),suit(3,clubs,[13,3,2])], [suit(3,spades,[5,4,3]),suit(3,hearts,[10,9,8]), suit(4,diamonds,[8,7,6,5]),suit(3,clubs,[12,6,4])], [suit(6,spades,[12,10,9,8,7,6]),suit(4,hearts,[13,7,6,5]), suit(2,diamonds,[12,4]),suit(1,clubs,[9])])). b28 :- play_hand(hand( [suit(3,spades,[14,13,2]),suit(3,hearts,[4,3,2]), suit(3,diamonds,[14,13,11]),suit(4,clubs,[14,7,6,5])], [suit(5,spades,[12,10,9,8,7]),suit(4,hearts,[14,13,11,10]), suit(2,diamonds,[4,3]),suit(2,clubs,[13,3])], [suit(1,spades,[6]),suit(2,hearts,[6,5]), suit(4,diamonds,[10,6,5,2]),suit(6,clubs,[12,11,10,9,8,4])], [suit(4,spades,[11,5,4,3]),suit(4,hearts,[12,9,8,7]), suit(4,diamonds,[12,9,8,7]),suit(1,clubs,[2])])). b29 :- play_hand(hand( [suit(3,spades,[14,13,2]),suit(3,hearts,[4,3,2]), suit(3,diamonds,[14,13,11]),suit(4,clubs,[14,11,6,5])], [suit(5,spades,[12,7,5,4,3]),suit(4,hearts,[14,13,11,10]), suit(2,diamonds,[4,3]),suit(2,clubs,[13,3])], [suit(1,spades,[6]),suit(0,hearts,[]), suit(5,diamonds,[10,7,6,5,2]),suit(7,clubs,[12,10,9,8,7,4,2])], [suit(4,spades,[11,10,9,8]),suit(6,hearts,[12,9,8,7,6,5]), suit(3,diamonds,[12,9,8]),suit(0,clubs,[])])). b30 :- play_hand(hand( [suit(2,spades,[13,11]),suit(3,hearts,[10,9,3]), suit(4,diamonds,[14,12,11,3]),suit(4,clubs,[14,13,11,10])], [suit(4,spades,[14,10,9,2]),suit(4,hearts,[14,12,11,2]), suit(2,diamonds,[10,9]),suit(3,clubs,[5,4,3])], [suit(3,spades,[5,4,3]),suit(3,hearts,[13,8,7]), suit(3,diamonds,[13,8,7]),suit(4,clubs,[12,8,7,6])], [suit(4,spades,[12,8,7,6]),suit(3,hearts,[6,5,4]), suit(4,diamonds,[6,5,4,2]),suit(2,clubs,[9,2])])). b31 :- play_hand(hand( [suit(3,spades,[8,7,6]),suit(3,hearts,[10,9,8]), suit(3,diamonds,[8,7,6]),suit(4,clubs,[10,9,8,7])], [suit(4,spades,[12,11,10,9]),suit(5,hearts,[13,12,11,7,6]), suit(3,diamonds,[13,10,9]),suit(1,clubs,[12])], [suit(3,spades,[14,13,2]),suit(2,hearts,[14,2]), suit(4,diamonds,[5,4,3,2]),suit(4,clubs,[13,6,5,4])], [suit(3,spades,[5,4,3]),suit(3,hearts,[5,4,3]), suit(3,diamonds,[14,12,11]),suit(4,clubs,[14,11,3,2])])). b32 :- play_hand(hand( [suit(3,spades,[8,7,6]),suit(3,hearts,[10,9,8]), suit(3,diamonds,[8,7,6]),suit(4,clubs,[9,8,7,3])], [suit(4,spades,[12,11,10,9]),suit(5,hearts,[13,12,11,7,6]), suit(3,diamonds,[13,10,9]),suit(1,clubs,[12])], [suit(3,spades,[14,13,2]),suit(2,hearts,[14,2]), suit(4,diamonds,[5,4,3,2]),suit(4,clubs,[13,6,5,4])], [suit(3,spades,[5,4,3]),suit(3,hearts,[5,4,3]), suit(3,diamonds,[14,12,11]),suit(4,clubs,[14,11,10,2])])). b33a :- play_hand(hand( [suit(5,spades,[13,12,10,3,2]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(2,clubs,[14,8])], [suit(4,spades,[14,9,5,4]),suit(3,hearts,[14,13,10]), suit(2,diamonds,[14,12]),suit(4,clubs,[11,10,9,7])], [suit(4,spades,[11,8,7,6]),suit(3,hearts,[12,11,8]), suit(4,diamonds,[13,11,10,9]),suit(2,clubs,[12,2])], [suit(0,spades,[]),suit(5,hearts,[9,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(5,clubs,[13,6,5,4,3])])). b33b :- play_hand(hand( [suit(5,spades,[13,12,10,3,2]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(2,clubs,[14,8])], [suit(4,spades,[14,9,5,4]),suit(3,hearts,[14,13,10]), suit(2,diamonds,[14,12]),suit(4,clubs,[11,10,9,7])], [suit(0,spades,[]),suit(5,hearts,[9,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(5,clubs,[13,6,5,4,3])], [suit(4,spades,[11,8,7,6]),suit(3,hearts,[12,11,8]), suit(4,diamonds,[13,11,10,9]),suit(2,clubs,[12,2])])). b33c :- play_hand(hand( [suit(4,spades,[13,12,9,8]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(3,clubs,[14,8,7])], [suit(5,spades,[14,6,5,4,2]),suit(3,hearts,[14,13,10]), suit(2,diamonds,[14,12]),suit(3,clubs,[11,10,9])], [suit(0,spades,[]),suit(5,hearts,[9,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(5,clubs,[13,6,5,4,3])], [suit(4,spades,[11,10,7,3]),suit(3,hearts,[12,11,8]), suit(4,diamonds,[13,11,10,9]),suit(2,clubs,[12,2])])). b33d :- play_hand(hand( [suit(4,spades,[13,12,9,8]),suit(2,hearts,[5,4]), suit(4,diamonds,[5,4,3,2]),suit(3,clubs,[14,8,7])], [suit(5,spades,[14,6,5,4,2]),suit(3,hearts,[14,13,10]), suit(2,diamonds,[14,12]),suit(3,clubs,[11,10,9])], [suit(4,spades,[11,10,7,3]),suit(3,hearts,[12,11,8]), suit(4,diamonds,[13,11,10,9]),suit(2,clubs,[12,2])], [suit(0,spades,[]),suit(5,hearts,[9,7,6,3,2]), suit(3,diamonds,[8,7,6]),suit(5,clubs,[13,6,5,4,3])])). %:- Assert(Trace_Lvl(2)), [Newhand, Eg, Gdraw, Facts, Bridge, Analysis, Synthesis, Planning, Exec_Mon]. %:- assert(trace_lvl(2)), [newhand, eg, gdraw, facts, bridge, analysis, synthesis, planning, exec_mon]. /* File - bridge.pl */ /* Main loop of program */ /* play_hand(+Hands, +Known, +Plan) */ play_hand(Hands, Known, Plan) :- play_trick(Hands, Known, Plan, Hands1, Known1, Plan1), play_hand(Hands1, Known1, Plan1). play_hand(hand([suit(0,_,_),suit(0,_,_),suit(0,_,_),suit(0,_,_)],_,_,_),_,_) :- !, format("Congratulations, hand is over~n",[]). /* Play one trick play_trick(+Hands, +Known, +Plan, -Hands1, -Known1, -Plan1) */ play_trick(Hands, known(Contract,Leader,Winners), Plan, Hands1, known(Contract,Winner,Winners1), NPlan) :- ( /* If a plan does not exist either as this is the beginning of play or that a plan that was being executed failed we need to find one */ Plan = [], /* ---THE ABSTRACTION STAGE---*/ evaluate_hand(Hands, Contract, Analysis), format('~NHand:~n~n', []), write_deal(Hands), format('~N~n~n', []), format('~NSuit analysis:~n~n', []), prettyprint(Analysis), format('~N~n', []), !, /* ---THE SYNTHESIS STAGE---*/ strategy(Contract, Winners, Analysis, Leader, LeadSuit, Plans), /* ---THE PLANNING STAGE---*/ planning(Hands, Contract, Plans, BestPlan) ; true ), /* ---THE EXECUTION STAGE---*/ play_trick(Hands, Leader, Contract, BestPlan, PlayedCards, Hands1, Tactic, Plan1), /* Find who wins the trick */ find_winner(Leader, PlayedCards, Contract, WinSuit, Winner, Side), /* Update the number of winners */ update_winners(Winners, Winner, Contract, Winners1), ( /* ---THE MONITORING STAGE---*/ /* evaluate played suit */ evaluate_suit(WinSuit, Hands1, Contract, Analysis), /* Check whether any defender did not follow suit */ defender_showed_out(Leader, Contract, PlayedCards,Learned), /* Update what has been learnt about the opponents cards */ update_learnt(Contract, WinSuit, Hands1, Side, Winner, Learned), /* take result of analysis and see if plan requirement has failed */ check_plan(Contract, WinSuit, Side, Winner, Tactic), /* Find the current potential of the same tactic after trick */ find_tactic(Tactic, Analysis, Tactic1), arg(3, Tactic, Potential), arg(3, Tactic1, Potential1), /* See if anything serendipitious has occurred */ action_result(Tactic, WinSuit, Potential, Tactic1, Potential1, Side, Update), /* If all went as planned, update the plan to reflect this trick */ update_llp(Plan1, Hands1, WinSuit, Analysis, Update, Contract, NPlan) ; /* Else, if plan failed then set NPlan to be empty */ NPlan = [] ). /* Executing one trick play_trick(+Hands, +Leader, +Winners, +Contract, +Plan, -PlayedCards, -Hands1, -Tactic, -Plan1) */ /* The case that declarer or dummy is on lead */ play_trick(Hands, Leader, Contract, Plan, [Card1, Card2, Card3, Card4], NHands, Tactic, Plan1) :- arg(3,Contract,Dec), ( Leader = Dec ; partner(Leader,Dec) ), !, /* Choose the first tactic from plan */ choose_tactic(Leader,_, Plan, Tactic, Plan1), /* Find the suit of that tactic */ arg(2,Tactic,LeadSuit), /* Find declarer, dummy and combined defendered holding in the suit*/ get_players_suit(Hands, Leader, DecSuit1, DecSuit2, DefSuit), /* Execution stage chooses the appropriate card from declarer's holding */ tactic_card(Tactic, Contract, Leader, [], DecSuit1, DecSuit2, DefSuit, Card1), /* Choose first defenders card */ next_play(Leader, Def1), defender_card(Hands, Def1, LeadSuit, Contract, Card2), /* Execution stage chooses the appropriate card from dummy's holding */ partner(Leader,Partner), tactic_card(Tactic, Contract, Partner, [Card2, Card1], DecSuit2, DecSuit1, DefSuit, Card3), /* Choose second defenders card */ next_play(Def2, Leader), defender_card(Hands, Def2, LeadSuit, Contract, Card4), close_trick, update_hand(Hands, Card1, Card2, Card3, Card4, NHands), display(NHands). /* The code for play trick is similar if a defender is on lead except choose_tactic changes to select the first tactic in the led suit */ /* Action result checks if something serendipitous has occurred action_result(+Action1, +WinSuit, +Potential1, +Action2, +Potential2, +WinningSide, -Update) */ /* File - abstraction.pl */ /* Variables that start with C,U,P stand for Certain, Usual, and Possible */ /* Evaluates the potential of each tactic for one suit evaluate_suit(+Suit, +Hand, +Contract, -Tactics) */ evaluate_suit(Suit, Hand, contract(_, _Trumps, Declarer), Tactics) :- partner(Declarer, Dummy), next_play(Declarer, Defender1), next_play(Dummy, Defender2), get_hand(Hand, Declarer, DecHand), get_hand(Hand, Dummy, DumHand), get_hand(Hand, Defender1, DefHand1), get_hand(Hand, Defender2, DefHand2), get_suit(DecHand, Suit, DecCards), get_suit(DumHand, Suit, DumCards), get_suit(DefHand1, Suit, Def1Cards), get_suit(DefHand2, Suit, Def2Cards), merge(Def1Cards, Def2Cards, DefCards), top_winners(DecCards, DumCards, DefCards, CWinners, UWinners, PWinners), max_entries(DecCards, DumCards, DefCards, DumEntries), max_entries(DumCards, DecCards, DefCards, DecEntries), develop_tricks(DecCards, DumCards, DefCards, certain, CWinLose), develop_tricks(DecCards, DumCards, DefCards, usual, UWinLose), develop_tricks(DecCards, DumCards, DefCards, possible, PWinLose), cash_tactic(CWinLose,UWinLose,PWinLose, CDWinners-CL,UDWinners-UL,PDWinners-PL), finesse_winners(DecCards, DumCards, DefCards, Type1, CFWinners1, UFWinners1, PFWinners1, CDFWinners1, UDFWinners1, PDFWinners1), add_tactic([cash(CWinners,UWinners,PWinners, CDWinners-CL,UDWinners-UL,PDWinners-PL), entries(DecEntries, DumEntries)], fin_dum(Type1, CFWinners1, UFWinners1, PFWinners1, CDFWinners1, UDFWinners1, PDFWinners1),Tactic1), finesse_winners(DumCards, DecCards, DefCards, Type2, CFWinners2, UFWinners2, PFWinners2, CDFWinners2, UDFWinners2, PDFWinners2), add_tactic(Tactic1, fin_dec(Type2, CFWinners2, UFWinners2, PFWinners2, CDFWinners2, UDFWinners2, PDFWinners2),Tactic2), dfinesse_winners(DecCards, DumCards, DefCards, Certain_df1, Usual_df1, Possible_df1, Certain_df_dev1, Usual_df_dev1, Possible_df_dev1), add_tactic(Tactic2, dbl2_fin_dum(Certain_df1, Usual_df1, Possible_df1, Certain_df_dev1, Usual_df_dev1, Possible_df_dev1), Tactic3), dfinesse_winners(DumCards, DecCards, DefCards, Certain_df2, Usual_df2, Possible_df2, Certain_df_dev2, Usual_df_dev2, Possible_df_dev2), add_tactic(Tactic3, dbl2_fin_dec(Certain_df2, Usual_df2, Possible_df2, Certain_df_dev2, Usual_df_dev2, Possible_df_dev2), Tactics). /* just to show where the trump analysis would fit get_suit(Dum, Trumps, DumTrumps), trump_winners(DecCards, DumCards, DefCards, DumTrumps, Suit, Trumps, Potential1, UTWinners1, PTWinners1), trump_winners(DumCards, DecCards, DefCards, DecTrumps, Suit, Trumps, Potential2, UTWinners2, PTWinners2). */ /* File - synthesis.pl */ /* Find the best strategy to fulfill the contract For each Suit the following analysis is generated by the abstraction stage - tricks([Tactic(CT, UT, PT, CD, UD, PD)|Other_Tactics]) tactic = cash|entries|sim_fin_dec|sim_fin_dum|rev_fin_dec|rev_fin_dum| dbl1_fin_dec|dbl1_fin_dum|dbl2_fin_dec|dbl2_fin_dum C/U/P = certain/usual/possible; T/D = Top/Developed; - cash and entries tactic is always included, others tactics are included only if applicable - entries(Dec, Dum), strategy(+Contract, +Winners, +Analysis, +Leader, +LeadSuit, -Plans) */ strategy(Contract, Winners, Analysis, Leader, LeadSuit, [BestPlan|Others]) :- /* Simplify removes repeating occurences of a tactic with same potential with different probabilities, Only need to keep the most likely one */ simplify(Analysis, S_Analysis, H_Analysis, D_Analysis, C_Analysis), /* Find all feasible strategies */ setof(Plan,strategies(Contract, Winners, S_Analysis, H_Analysis, D_Analysis, C_Analysis, Plan), Plans), /* Order them by probability of success */ order_plans(Plans, Contract, Leader, LeadSuit, [Plan1|Plans1]), !, /* Find enhancements to the plan */ enhance_plan(Plan1, Plans1, BestPlan, Others). /* If no strategy found, find one that generates the most number of tricks */ strategy(_, _, Analysis, _, _, [(999, [spades(S_Tactic, S_Prob, S_Win), hearts(H_Tactic, H_Prob, H_Win), diamonds(D_Tactic, D_Prob, D_Win), clubs(C_Tactic, C_Prob, C_Win)])]) :- simplify(Analysis, S_Analysis, H_Analysis, D_Analysis, C_Analysis), format("No good plan found!!! - going with this~n",[]), maximize(S_Analysis, S_Tactic, S_Prob, S_Win), maximize(H_Analysis, H_Tactic, H_Prob, H_Win), maximize(D_Analysis, D_Tactic, D_Prob, D_Win), maximize(C_Analysis, C_Tactic, C_Prob, C_Win). /* strategies(+Contract, +Winners, +SpadeAnalysis, +HeartAnalysis, +DiamondAnalysis, +ClubAnalysis, +Leader, +LeadSuit, -Strategies) */ strategies(contract(Level, _, _), winners(Won, Lost), S, H, D, C, [spades(S1, S_Prob, S_Winners), hearts(H1, H_Prob, H_Winners), diamonds(D1, D_Prob, D_Winners), clubs(C1, C_Prob, C_Winners)]) :- num_tricks(S, S1, T1, S_Prob, S_Winners, S_Losers), num_tricks(H, H1, T2, H_Prob, H_Winners, H_Losers), num_tricks(D, D1, T3, D_Prob, D_Winners, D_Losers), num_tricks(C, C1, T4, C_Prob, C_Winners, C_Losers), /* Check that enough tricks are won*/ S_Winners + H_Winners + D_Winners + C_Winners >= Level + 6 - Won, /* Make sure that there are enough entries for tactic to be executable */ check_entries(S, H, D, C, T1, T2, T3, T4), /* Number of actions calculates number of tricks played */ number_of_actions(_,_,_,N), /* Make sure there are not too many winners */ 13 >= S_Winners + H_Winners + D_Winners + C_Winners + S_Losers + H_Losers + D_Losers + C_Losers + N, /* Make sure there are not too many losers */ S_Losers + H_Losers + D_Losers + C_Losers =< Lost + 13 - Level - 6. /* Number of tricks won and lost by a tactic num_tricks(+Tactics, +Suit, -TacticName, -Tactic_Prob, -Tactic_Winners, -Tactic_Losers */ num_tricks([Tactic|_], Name, Tactic, Prob, Win+Dev, Losers) :- functor(Tactic,Name,_), arg(1,Tactic,Prob), arg(2,Tactic,Win+Dev-_), losers(Tactic, Losers), !. num_tricks([_|Tactics], Name, Tactic, Prob, Tricks, Winners) :- num_tricks(Tactics, Name, Tactic, Prob, Tricks, Winners). /* Number of losers accrued executing a tactic losers(+Tactic, -Losers) /* For example cash, simple finesse, and double2 finesse have any no losers */ losers(cash(_,_),0) :- !. losers(sim_fin_dec(_,_),0) :- !. losers(sim_fin_dum(_,_),0) :- !. losers(dbl2_fin_dec(_,_),0) :- !. losers(dbl2_fin_dum(_,_),0) :- !. /* double1 finesse has one loser */ losers(dbl1_fin_dec(_,_),1) :- !. losers(dbl1_fin_dum(_,_),1) :- !. /* Losers using development is already done */ losers(develop(_,_+_-L),L) :- !. /* Use quicksort to sort the plans by the relative probabilites order_plans(+Plans, +Contract, +Leader, +LeadSuit, -OPlans). */ order_plans([], _, _, _, []). order_plans([Plan|Plans], Contract, Leader, LeadSuit, OPlans) :- plan_prob(Plan, Contract, Leader, LeadSuit, V1), !, partition(Plans, Contract, Leader, LeadSuit, V1, Littles, Bigs), order_plans(Littles, Contract, Leader, LeadSuit, Ls), order_plans(Bigs, Contract, Leader, LeadSuit, Bs), append(Ls,[(V1,Plan)|Bs],OPlans). order_plans([_|Plans], Contract, Leader, LeadSuit, OPlans) :- order_plans(Plans, Contract, Leader, LeadSuit, OPlans). /* Probability of a plan is the combined probabities of each suit tactic */ plan_prob([Tactic|Tactics], Contract, Leader, LeadSuit, PV) :- suit_prob(Tactic, Contract, Leader, LeadSuit, SV), plan_prob(Tactics, Contract, Leader, LeadSuit, PVs), PV is SV * PVs. /* Probability of a tactic is the probability of the tactic succeeding e.g. p(finesse) = 0.5, multiplied by the required suit division, e.g. prob(usual) = 0.66 suit_prob(+Tactic, +Contract, +Leader, +LeadSuit, Suit_Probability) */ suit_prob(Tactic, Contract, Leader, LeadSuit, Suit_Probability) :- tactic_prob(Tactic, Contract, Leader, LeadSuit, Tactic_Prob), !, distribution_prob(Tactic, Distribution_Prob), Suit_Probability is Tactic_Prob * Distribution_Prob. /* tactic_prob(+Tactic, +Contract, +Leader, +LeadSuit, -Tactic_Prob) In order to avoid division, we use inverse probabilities, thus the higher the value, the less likely the tactics will succeed */ /* Probability of cash and develop = 1 i.e. a certainty */ tactic_prob(Tactic, _, _, _, 1) :- ( arg(1, Tactic, develop) ; arg(1, Tactic, cash) ), !. /* Probability of finesse = 1 if the right defender is know to be void */ tactic_prob(Tactic, contract(_,_,Dec), _, _, 1) :- ( arg(1,Tactic,sim_fin_dec) ; arg(1,Tactic,dbl1_fin_dec); arg(1,Tactic,dbl2_fin_dec) ), functor(Tactic, Suit,_), next_play(Dec,Next), Known =.. [Suit, void, Next], clause(known(Known),_), !. /* Probability of finesse = 0 if the wrong defender is know to be void */ tactic_prob(Tactic, contract(_,_,Dec), _, _, 999) :- ( arg(1,Tactic,sim_fin_dec) ; arg(1,Tactic,dbl1_fin_dec) ; arg(1,Tactic,dbl2_fin_dec) ), functor(Tactic, Suit,_), next_play(Next,Dec), Known =.. [Suit,void,Next], clause(known(Known),_), !, fail. /* Probability of finesse = 2 (inverse of 0.5) */ tactic_prob(Tactic, _, _, _, 2) :- arg(1, Tactic, sim_dfin_dec) ; arg(1, Tactic, sim_dfin_dum) ; arg(1, Tactic, rev_fin_dec) ; arg(1, Tactic, rev_fin_dum) ; arg(1, Tactic, rev_dfin_dec) ; arg(1, Tactic, rev_dfin_dum). /* Probability of double_finesse = is usually 4 but can be 2 if left hand opponent leads into the finesse suit */ tactic_prob(Tactic, contract(_,_,Dec), Leader, LeadSuit, V) :- ( ( arg(1, Tactic, dbl2_fin_dec) ; arg(1, Tactic, dbl2_dfin_dec) ), !, ( functor(Tactic,LeadSuit,_), next_play(Dec, Leader), V = 2 ; V = 4) ) ; ( ( arg(1, Tactic, dbl2_fin_dum) ; arg(1, Tactic, dbl2_dfin_dum) ), !, ( functor(Tactic,LeadSuit,_), next_play(Leader, Dec), V = 2 ; V = 4) ). /* distribution_Prob(+Tactic,-Distribution_Prob) In order to avoid division, we use inverse probabilities, thus the higher the value, the less likely the tactics will succeed */ /* Certain distribuition = 1, Possible is 3/2 (i.e. inverse of .66) and possible = 3 (i.e. inverse of .33) */ distribution_prob(Tactic, 1) :- arg(2,Tactic,cert), !. distribution_prob(Tactic, 3/2) :- arg(2,Tactic,usual), !. distribution_prob(Tactic, 3) :- arg(2,Tactic,pos), !. /* Enhance a plan by enhancing each tactic enhance_plan(+Plan, +Plans, -BestPlan, -OtherPlans). */ enhance_plan(Plan, [], Plan, []) :- !. enhance_plan((V, Plan), [(V1, Plan1)|Plans], BestPlan, [(V,Plan)|OtherPlans]) :- better_tactics(Plan1, Plan), !, enhance_plan((V1,Plan1), Plans, BestPlan, OtherPlans). enhance_plan(Plan, [Plan1|Plans], BestPlan, [Plan1|OtherPlans]) :- enhance_plan(Plan, Plans, BestPlan, OtherPlans). /* Compare which of the two plans are betters. Check each suit, if one tactic generates more tricks than another then choose the plan with the tactic that generates more tricks. better_tactics(+Plan1, +Plan) */ better_tactics([Tactic1|Tactics1],[Tactic|Tactics]) :- arg(1, Tactic, Type), arg(1, Tactic1, Type), arg(3, Tactic, W), arg(3, Tactic1, W1), better(W1, W), !, better_tactics(Tactics1, Tactics). better_tactics([Tactic1|Tactics1],[Tactic|Tactics]) :- (arg(1, Tactic, cash); arg(1, Tactic, develop)), arg(1, Tactic1, Fin), /* Is the tactic a type of finesse such as sim_fin_dec or dbl_dfin_dum */ finesseable(Fin), arg(3, Tactic, W), arg(3, Tactic1, W1), better(W1, W), !, better_tactics(Tactics1, Tactics). /* better(+Potential_Tactic1, +Potential_Tactic2) */ /* Does the first tactic wins more tricks */ better(W1+W2-_,W3+W4-_) :- W1 + W2 > W3 + W4. better(W1,W2+W3-_) :- W1 > W2 + W3. better(W1+W2-_,W) :- W1 + W2 > W. better(N2,N1) :- N2 > N1. /* Does the first tactic wins the same number of tricks but has more winners */ better(W1+W2-_,W3+W4-_) :- W1 + W2 =:= W3 + W4, W1 > W3. /* File - planning.pl */ /* planning(+Hands, +Contract, +Plans, -BestPlan) */ planning(Hands, Contract, Plans, Spliced) :- delete((Prob, Plan), Plans, OtherPlans), get_hands(Hands, DecHand, DumHand, DefHand), linearize_plan(Plan, Linearized), decompose_and_splice(Linearized, DecHand, DumHand,DefHand,Contract,Spliced), /* assert requirements needed for plan to succeed */ requirements(Prob, Plan), assert_other_plans(OtherPlans). linearize_plan(Plan, Linearized) :- change_format_of_plan(Plan, Linearized). change_format_of_plan([], []). change_format_of_plan([F | R], [F1 | R1]) :- change_format_of_plan_element(F, F1), !, change_format_of_plan(R, R1). /* Change spades(cash, cert, 5) into tactic(cash, spades, 5) */ change_format_of_plan_element(CashElement, CashElement1) :- compound(CashElement), functor(CashElement, Suit, 3), arg(1, CashElement, cash), arg(3, CashElement, N), CashElement1 = tactic(cash, Suit, N), !. change_format_of_plan_element(CashElement, CashElement). get_hands(Hands, DecHand, DumHand, DefHand) :- Hands = hand(North, South, East, _West), DecHand = South, DumHand = North, DefHand = East. /* Decompose and splice checks whether entry problems can be resolved if not then we back track to find next plan in Plans decompose_and_splice(+Linearized, +DecHand, +DumHand, +DefHand, -Spliced) */ decompose_and_splice(Tactics, Dec, Dum, Def, contract(_,_,Declarer), Lo_lvl) :- /* decompose tactics recursively decompose each tactic into a set of tricks, using heuristics and safety plays */ decompose_tactics(Tactics, Declarer, Dec, Dum, Def, Lo_lvl), /*Find number of entries needed to execute plan */ splice(Lo_lvl, Declarer, Dec_Entries_Needed, Dum_Entries_Needed), /* Find number of entries available */ number_of_entries(Dec_Entries_Avail,Dum_Entries_Avail), /* Make sure that there are enough entries */ Dec_Entries_Avail >= Dec_Entries_Needed, Dum_Entries_Avail >= Dum_Entries_Needed. decompose_tactics([], _, _, _, _, _, []) :- !. decompose_tactics([Tactic|Tactics], Declarer,Dec,Dum,Def,[Lo_lvl|Lo_lvls]) :- arg(1,Tactic,Name), arg(2,Tactic,Suit), arg(3, Tactic,NumofTricks), decompose_tactic(Name, NumofTricks, Suit, Declarer, Dec, Dum, Def, Lo_lvl), decompose_tactics(Tactics, Declarer, Dec, Dum, Def, Lo_lvls). /* Decompose each tactic into low level actions decompose_tactic(+Tactic, +Tricks, +Suit, +Declarer, +Dec, +Dum, +Def, -Lo_lvl) */ /* some examples of decompose tactic */ /* Can we use a safety play */ decompose_tactic(Tactic,_, Suit,Declarer,DecCards,DumCards,DefCards,Lo_lvl) :- length(DecCards, L1), length(DumCards, L2), length(DefCards, L3), 13 is L1 + L2 + L3, safety_play(Tactic, Suit, Declarer, DecCards, DumCards, Lo_lvl). /* If tactic is cash and either only declarer has the winner or both hands have winners but declarer has fewer cards so use heuristic of cashing winner in shorter hand first */ decompose_tactic(cash, Win, Suit, Declarer, [Dec1|DecCards],[Dum1|DumCards], [DefHighest|DefCards], [cash(1,Suit,Declarer)|Tactics]) :- ( ( Dec1 > DefHighest, Dum1 > DefHighest, length(DecCards,L1), length(DumCards,L2), L1 < L2 ) ; ( Dec1 > DefHighest, Dum1 < DefHighest ) ; ( Dec1 < DefHighest, Dum1 < DefHighest, Dec1 > Dum1 ) ), !, delete_highest([Dec1|DecCards], DecCards1), delete_lowest([Dum1|DumCards], DumCards1), Win1 is Win - 1, decompose_tactic(cash, Win1, Suit, Declarer, DecCards1, DumCards1, [DefHighest|DefCards], Tactics). /* decompose a finesse */ decompose_tactic(finesse, Tricks, Suit, Declarer, DecCards, DumCards, DefCards, Lo_lvl) :- tops(DecCards, DefHighest, Tops_Dec), tops(DumCards, DefHighest, Tops_Dum), length(DumCards,LDum), length(DecCards,LDec), partner(Declarer,Dummy), /* Cash dummy's winner if declarer has more or the same number of cards */ ( LDec >= LDum, decompose_tactic(cash, Tops_Dum, Suit, Dummy, Tactic1), decompose_tactic(cash, Tops_Dec, Suit, Declarer, Tactic3), Tactic4 = []; decompose_tactic(cash, Tops_Dec, Suit, Declarer, Tactic3), decompose_tactic(cash, Tops_Dum, Suit, Dummy, Tactic4), Tactic1 = [] ), length(Tactic1, Cashed1), length(Tactic3, Cashed3), length(Tactic4, Cashed4), Cashed is Cashed1 + Cashed3 + Cashed4, %Finesse the cards Fin is Tricks - Tops_Dec - Tops_Dum, Low_Dum is LDum - Tops_Dum, min(Fin, Low_Dum, Fin1), decompose(finesse, Fin1, Suit, Declarer, Tactic2), Remainder is Tricks - Fin1 - Cashed, Rest_Dec is LDec - Fin1 - Cashed, Rest_Dum is LDum - Fin1 - Cashed, decompose_tactic(cash, Remainder, Declarer, Rest_Dec, Rest_Dum, DefCards, Tactic5), append(Tactic1, Tactic2, Temp1), append(Tactic3, Tactic4, Temp2), append(Temp1, Temp2, Temp), append(Temp,Tactic5, Lo_lvl). /* some safety plays safety_play(Tactic, Suit, Declarer, DecCards, DumCards, Lo_lvl) */ /* If you are going to cash a suit with 9 cards with 2 winners in one hand and 1 in the other and you can finesse both hands, cash the winner in the hand with two winners */ safety_play(cash, Suit, Declarer, DecCards, [_|DumCards], DecCards1, DumCards, [cash(1, Suit, Dummy)]) :- length(DecCards, L1), length([_|DumCards], L2), 9 is L1 + L2, analysis(Suit, Analysis), member(sim_fin_dum(_,_,_,_,_,_),Analysis), member(sim_fin_dec(_,_,_,_,_,_),Analysis), member(entries(1,2),Analysis), !, partner(Declarer,Dummy), delete_lowest(DecCards,DecCards1). /* If you are going to cash a suit with 9 cards, with 2 winners in one hand and 1 in the other and you can double finesse the first hand, cash the winner in hand with one winner */ safety_play(cash, Suit, DecCards, [_|DumCards], Declarer, DecCards1, DumCards, [cash(1, Suit, Dummy)]) :- length(DecCards, L1), length([_|DumCards], L2), 9 is L1 + L2, analysis(Suit, Analysis), member(dbl2_fin_dec(_,_,_,_,_,_),Analysis), member(entries(1,2),Analysis), !, partner(Declarer,Dummy), delete_lowest(DecCards,DecCards1). /* Generalized Safety Play for something like A,10,x,x vs K,Q,x,x If you are going to cash a suit with a finesse in one hand, cash the winners in the other hand first */ safety_play(cash, Suit, DecCards, [_|DumCards], Declarer, DecCards1, DumCards, [cash(1, Suit, Dummy)]) :- analysis(Suit, Analysis), member(sim_fin_dec(_,_,_,_,_,_),Analysis), member(entries(_,N),Analysis), !, N > 0, partner(Declarer,Dummy), delete_lowest(DecCards,DecCards1). /* One example of splice plan splice(+Lo_lvl, +Declarer, -Dec_Entries, -Dum_Entries) */ /* A cash followed by a finesse in the same hand cannot be done without finding an entry back to the other hand first */ splice([cash(_,_,Declarer),finesse(_,_,Declarer)|Actions], Declarer, DecEnts, DumEnts1) :- splice([finesse(_,_,Declarer)|Actions], Declarer, DecEnts, DumEnts), DumEnts1 is DumEnts + 1. /* File - exec_mon.pl */ /* Choose tactic from plan to execute choose_tactic(+Leader, +LeadSuit, +Plan, -Tactic, -RemainingPlan) */ /* if declarer is on lead then choose first legal tactic we must be in the other hand for a finesse or duck with void opposite */ choose_tactic(Leader, LeadSuit, Plan, Tactic, Plan1) :- var(LeadSuit), delete(Tactic, Plan, Plan1), ( functor(Tactic, duck, Leader) ; functor(Tactic,finesse,_), arg(3,Tactic,Player), partner(Leader,Player) ). /* For all other tactics we can be in any hand */ choose_tactic(_Leader, LeadSuit, Plan, Tactic, Plan1) :- var(LeadSuit), delete(Tactic, Plan, Plan1). /* if defender is on lead then choose first tactic in their suit*/ choose_tactic(_Leader, LeadSuit, Plan, Tactic, Plan1) :- delete(Tactic, Plan, Plan1), arg(2, Tactic, LeadSuit). /* Depending on the tactic, choose the card to play tactic_card(+Tactic, +Contract, +Player, +Cards, +DecSuit1, +DecSuit2, +DefSuit, -Card) Player is who is playing, and Cards are cards that have been played DecSuit1 is the hand to play, DecSuit2 is partner's hand */ /* Some examples of the cash tactic */ /* Only 1 player has winner */ tactic_card(cash(_, Suit, anyone), _, _, _, [Card|_], [Card1|_], DefSuit, card(Suit,Card)) :- defenders_highest(DefSuit,H), Card > H, Card1 < H. /* If both player have winners, play winner from shorter hand */ tactic_card(cash(_,Suit,anyone), _, _, _, [Card|DecSuit1], [Card1|DecSuit2], DefSuit, card(Suit,Card)) :- defenders_highest(DefSuit,H), Card > H, Card1 > H, length(DecSuit1, L1), length(DecSuit2, L2), L1 < L2. /* else play small */ tactic_card(cash(_,Suit,anyone), _, _, _, DecSuit1, _, _, card(Suit,Card)) :- append(_,[Card],DecSuit1). /* If winner has been chosen */ tactic_card(cash(_,Suit,Player), _, Player, [C1,_,C3], DecSuit1, _, _,card(Suit,Card)) :- defenders_highest(Suit, C1, C3, C), win_cheaply(DecSuit1,C,Card). /* Example of the duck tactic */ tactic_card(duck(_,Suit,_), _, _, _, DecSuit1, _, _,card(Suit,Card)) :- append(_,[Card],DecSuit1). /* Some examples of the develop tactic */ /* In fourth seat play small if Defenders win trick */ tactic_card(develop(_,Suit,_), _, _, [C1,C2,C3], [Card1|DecSuit1], _, _, card(Suit,Card)) :- ( ( higher(Suit, C1, card(Suit,Card1)), higher(Suit, C1, C2) ) ; ( higher(Suit, C3, card(Suit,Card1)), higher(Suit, C3, C2) ) ), !, append(_,[Card],[Card1|DecSuit1]). /* In third seat play highest if Defender and Partner play small */ tactic_card(develop(_,Suit,_), _, _, [card(Suit,C1),_], [Card1|_], _, Def, card(Suit,Card1)) :- number_higher([Card1], Def, NH1), number_higher([C1], Def, NH2), NH1 < NH2, !. /* finesse 1st Seat - play hnw if finesse card only in this hand */ tactic_card(finesse(_, Suit, Player), _, Partner, [], DecSuit1, DecSuit2, [Highest|DefSuit], card(Suit,HNW1)) :- partner(Player, Partner), highest_non_winner(DecSuit1,Highest,HNW1), highest_non_winner(DecSuit2,Highest,HNW2), number_higher([HNW1],[Highest|DefSuit], N1), number_higher([HNW2],[Highest|DefSuit], N2), N1 < N2, !. /* play high if defender played finesse card */ tactic_card(finesse(_, Suit,Player), _, Player, [card(Suit,Card)|_], [Card1|DecSuit1], DecSuit2, [Highest|_], card(Suit,Card1)) :- highest_non_winner([Card1|DecSuit1], Highest, HNW1), highest_non_winner(DecSuit2, Highest, HNW2), HNW1 < Card, HNW2 < Card, Card1 > Card, !. /* finesse 2st Seat - play hnw if finesse card only in this hand and led low*/ tactic_card(finesse(_,Suit,_), _, _, [card(Suit,Card)], DecSuit1, DecSuit2, [Highest|DefSuit], card(Suit,HNW1)) :- highest_non_winner(DecSuit1,Highest,HNW1), highest_non_winner(DecSuit2,Highest,HNW2), number_higher([HNW1],[Highest|DefSuit], N1), number_higher([HNW2],[Highest|DefSuit], N2), HNW1 > Card, N1 < N2. /* 3rd Seat - play hnw if finesse card in this hand and defender follows low */ tactic_card(finesse(_,Suit,Player), _, Player, [_, card(Suit,Card)], DecSuit, _, [Highest|DefSuit], card(Suit,HNW1)) :- highest_non_winner(DecSuit,Highest,HNW1), number_higher([HNW1],[Highest|DefSuit], N1), number_higher([Card],[Highest|DefSuit], N2), N1 < N2. /* Check to see whtehr the plan has failed check_plan(+Contract, +WinSuit, +Side, +Winner, +Tactic) */ /* For example, a required finesse has failed */ check_plan(_, Suit, defender, _, Action) :- finesseable(Action), plan(_, Reqs), Req =.. [Suit, finesse], member(Req, Reqs), !, fail. /* INPUTS 1) Declarer, Dummy and Outstanding Cards 2) contract(level, suit) 3) won(number_of_tricks) 4) in_hand(Hand), 5) For each Suit the following analysis - tricks([Tactic(CT, UT, PT, CD, UD, PD)|Other_Tactics]) tactic = cash|entries|sim_fin_dec|sim_fin_dum|rev_fin_dec|rev_fin_dum| dbl1_fin_dec|dbl1_fin_dum|dbl2_fin_dec|dbl2_fin_dum C/U/P = certain/usual/possible; T/D = Top/Developed; cash and entries tactic is always included, others will be included only if applicable - PUP Trump Winners - how many tricks can be made by trumping (PUP-TW) - entries(Dec, Dum), 6) Accumulated Defender's data Three levels of making a plan 1) first use heuristics to find a "good" selection of tactics in each suit 2) organize which suits to play in which order by a set of rules 3) break down how many tricks to cash in each suit i.e many problem of communications 1) Done!! 2) List of Rules - partial list for NT follows - In NT trick is to count number of winners - Develop longest suit first - If 2 suits equal length develop one with most outside loosers 3) Is the hardest. Take care of the following 1) Do we need to get to a different hand to cash a winner 2) Do we need to get to a different hand in order to trump 3) Do we need to get to a diffent hand to finesse (maybe finesse needs to be repeated - A,Q,J op. x,x versus A,Q,x op x,x, etc.) For each tactic keep eye out for good and bad unexpected list of things that happen. If so - backtrack. */ strategy(_, Contract, Winners, Analysis, Leader, LeadSuit, [BestPlan|OtherPlans]) :- simplify(Analysis,S,H,D,C), rm_inferior(S, S1), member(cash(_,W1), S1), ( not(clause(winners(spades,_),_)), assert(winners(spades,W1)) ; true ), rm_inferior(H, H1), member(cash(_,W2), H1), ( not(clause(winners(hearts,_),_)), assert(winners(hearts,W2)) ; true ), rm_inferior(D, D1), member(cash(_,W3), D1), ( not(clause(winners(diamonds,_),_)), assert(winners(diamonds,W3)) ; true ), rm_inferior(C, C1), member(cash(_,W4), C1), ( not(clause(winners(clubs,_),_)), assert(winners(clubs,W4)) ; true ), setof(Plan,strategy1(_, Contract, Winners, S1, H1, D1, C1, Plan), Plans), order_plans(Plans, Contract, Leader, LeadSuit, [Plan1|Plans1]), !, enhance_plan(Plan1, Plans1, BestPlan, OtherPlans). strategy(_, _, _, Analysis, _, _, [(999, [spades(T1, P1, W1), hearts(T2, P2, W2), diamonds(T3, P3, W3), clubs(T4, P4, W4)])]) :- format("No good plan found!!! - going with this~n",[]), simplify(Analysis,S,H,D,C), maximize(S, T1, P1, W1), maximize(H, T2, P2, W2), maximize(D, T3, P3, W3), maximize(C, T4, P4, W4). strategy1(_Hand,contract(Level, _, _), winners(Won, Lost), S, H, D, C, [spades(S1, Prob1, W1), hearts(H1, Prob2, W2), diamonds(D1, Prob3, W3), clubs(C1, Prob4, W4)]) :- num_tricks(S, S1, T1, Prob1, W1, Win1), num_tricks(H, H1, T2, Prob2, W2, Win2), num_tricks(D, D1, T3, Prob3, W3, Win3), num_tricks(C, C1, T4, Prob4, W4, Win4), Win1 + Win2 + Win3 + Win4 >= Level + 6 - Won, number_of_actions(_,_,_,N), losers(T1, L1), losers(T2, L2), losers(T3, L3), losers(T4, L4), %format("Check ~p ~p ~p ~p~n" , [T1, T2, T3, T4]), 13 >= Win1 + Win2 + Win3 + Win4 + L1 + L2 + L3 + L4 + N, L1 + L2 + L3 + L4 =< Lost + 13 - Level - 6. %format("Found ~p ~p ~p ~p~n" , [T1, T2, T3, T4]). %format("Too many losers ~p ~p ~p ~p~n" , [T1, T2, T3, T4]), fail). requirements(Prob,Plan) :- suit_reqs(Plan,Reqs), format("Required Plan (~p) ~p Reqs ~p~n",[Prob,Plan,Reqs]), assert(plan((Prob,Plan),Reqs)). suit_reqs([],[]). /* suit_reqs([HLT|HLTs],[Req|Reqs]) :- arg(1,HLT,Tactic), (Tactic = dbl1_fin_dec, Fin = dbl1_dec; Tactic = dbl1_fin_dum, Fin = dbl1_dum), !, functor(HLT, Suit, _), functor(Req, Suit, 1), arg(1, Req, Fin), !, suit_reqs(HLTs,Reqs). */ suit_reqs([HLT|HLTs],[Req1,Req2|Reqs]) :- arg(1,HLT,Tactic), finesseable(Tactic), dev_name(_,Tactic), arg(2,HLT,Prob), Prob \== cert, functor(HLT,Suit,_), functor(Req1,Suit,1), arg(1,Req1,finesse), functor(Req2,Suit,1), arg(1,Req2,Prob), !, suit_reqs(HLTs,Reqs). suit_reqs([HLT|HLTs],[Req1|Reqs]) :- arg(1,HLT,Tactic), finesseable(Tactic), functor(HLT,Suit,_), functor(Req1,Suit,1), arg(1,Req1,finesse), !, suit_reqs(HLTs,Reqs). suit_reqs([HLT|HLTs],[Req1|Reqs]) :- functor(HLT,Suit,_), arg(2,HLT,Prob), Prob \== cert, functor(Req1,Suit,1), arg(1,Req1,Prob), !, suit_reqs(HLTs,Reqs). suit_reqs([_|HLTs],Reqs) :- suit_reqs(HLTs,Reqs). maximize([Tactic],T, P, W) :- functor(Tactic,T,_), arg(1,Tactic,P), arg(2,Tactic,W). maximize([Tactic|Tactics],T,P,W) :- maximize(Tactics, _, _,W1), arg(2,Tactic,W), W > W1, !, arg(1,Tactic,P), functor(Tactic,T,_). maximize([_|Tactics],T,P,W) :- maximize(Tactics,T,P,W). rm_inferior(Suit,Suit1) :- rm_inferior(Suit,[],Suit1). rm_inferior([],Suit,Suit). rm_inferior([rev_fin_dec(_,_)|Tactics],SoFar,BTactics) :- ( member(sim_fin_dum(_,_),Tactics) ; member(sim_fin_dum(_,_),SoFar) ), !, rm_inferior(Tactics,SoFar,BTactics). rm_inferior([rev_fin_dum(_,_)|Tactics],SoFar,BTactics) :- ( member(sim_fin_dec(_,_),Tactics) ; member(sim_fin_dec(_,_),SoFar) ), !, rm_inferior(Tactics,SoFar,BTactics). rm_inferior([sim_fin_dec(Prob,Tricks)|Tactics],SoFar,BTactics) :- ( member(sim_fin_dum(Prob,T1),Tactics), T1 > Tricks ; member(sim_fin_dum(Prob,T2),SoFar), T2 > Tricks ), !, rm_inferior(Tactics,SoFar,BTactics). rm_inferior([sim_dfin_dec(Prob,Tricks)|Tactics],SoFar,BTactics) :- ( member(sim_fin_dum(Prob,T1),Tactics), T1 > Tricks ; member(sim_fin_dum(Prob,T2),SoFar), T2 > Tricks ), !, rm_inferior(Tactics,SoFar,BTactics). rm_inferior([sim_fin_dum(Prob,Tricks)|Tactics],SoFar,BTactics) :- ( member(sim_fin_dec(Prob,T1),Tactics), T1 > Tricks ; member(sim_fin_dec(Prob,T2),SoFar), T2 > Tricks ), !, rm_inferior(Tactics,SoFar,BTactics). rm_inferior([sim_dfin_dum(Prob,Tricks)|Tactics],SoFar,BTactics) :- ( member(sim_fin_dec(Prob,T1),Tactics), T1 > Tricks ; member(sim_fin_dec(Prob,T2),SoFar), T2 > Tricks ), !, rm_inferior(Tactics,SoFar,BTactics). rm_inferior([Tactic|Tactics], SoFar, BTactics) :- rm_inferior(Tactics,[Tactic|SoFar],BTactics). num_tricks([Tactic|_], Name, Tactic, Prob, Win+Dev-Losers, Win+Dev) :- functor(Tactic,Name,_), arg(1,Tactic,Prob), arg(2,Tactic,Win+Dev-Losers). num_tricks([Tactic|_], Name, Tactic, Prob, Tricks, Tricks) :- functor(Tactic,Name,_), arg(1,Tactic,Prob), arg(2,Tactic,Tricks), integer(Tricks). num_tricks([_|Tactics], Name, Tactic, Prob, Tricks, Winners) :- num_tricks(Tactics, Name, Tactic, Prob, Tricks, Winners). losers(cash(_,_),0) :- !. losers(sim_fin_dec(_,_),0) :- !. losers(sim_fin_dum(_,_),0) :- !. losers(sim_dfin_dec(_,_+_-L),L) :- !. losers(sim_dfin_dum(_,_+_-L),L) :- !. losers(dbl2_fin_dec(_,W),L) :- L is 2 - W, L > 0, !. losers(dbl2_fin_dum(_,W),L) :- L is 2 - W, L > 0, !. losers(dbl2_fin_dec(_,_),0) :- !. losers(dbl2_fin_dum(_,_),0) :- !. losers(dbl1_fin_dec(_,_),1) :- !. losers(dbl1_fin_dum(_,_),1) :- !. losers(dbl1_dfin_dec(_,_),2) :- !. losers(dbl1_dfin_dum(_,_),2) :- !. losers(develop(_,_+_-L),L) :- !. simplify(analysis(S,H,D,C),SSimp,HSimp,DSimp,CSimp) :- simplify_suit(S,SSimp), simplify_suit(H,HSimp), simplify_suit(D,DSimp), simplify_suit(C,CSimp). simplify_suit(analysis(_Suit, Tactics), Tactics1) :- simplify_tactics(Tactics, Tactics1), !. simplify_suit(Tactics, Tactics1) :- simplify_tactics(Tactics, Tactics1). simplify_tactics([Tactic|Tactics],STactics1) :- simplify_tactic(Tactic,STactic), simplify_tactics(Tactics,STactics), append(STactic,STactics,STactics1). simplify_tactics([],[]). order_plans([], _, _, _, []). order_plans([Plan|Plans], Contract, Leader, LeadSuit, OPlans) :- plan_value(Plan, Contract, Leader, LeadSuit, V1), !, %format("Plan = ~p/~p ~n", [Plan, V1]), partition(Plans, Contract, Leader, LeadSuit, V1, Littles, Bigs), order_plans(Littles, Contract, Leader, LeadSuit, Ls), order_plans(Bigs, Contract, Leader, LeadSuit, Bs), append(Ls,[(V1,Plan)|Bs],OPlans). order_plans([_|Plans], Contract, Leader, LeadSuit, OPlans) :- order_plans(Plans, Contract, Leader, LeadSuit, OPlans). partition([Plan|Plans], Contract, Leader, LeadSuit, V1, [Plan|Ls], Bs) :- plan_value(Plan, Contract, Leader, LeadSuit, V), %format("Plan = ~p/~p ~n", [Plan, V]), V < V1, !, partition(Plans, Contract, Leader, LeadSuit, V1, Ls, Bs). partition([Plan|Plans], Contract, Leader, LeadSuit, V1, Ls, [Plan|Bs]) :- %plan_value(Plan, Contract, Leader, LeadSuit, V), %format("Plan = ~p/~p ~n", [Plan, V]), partition(Plans, Contract, Leader, LeadSuit, V1, Ls, Bs). partition([], _, _, _, _, [], []). plan_value([], _, _, _, 1). plan_value([Tactic|Tactics], Contract, Leader, LeadSuit, PV) :- suit_value(Tactic, Contract, Leader, LeadSuit, SV), plan_value(Tactics, Contract, Leader, LeadSuit, PVs), PV is SV * PVs. suit_value(Tactic, Contract, Leader, LeadSuit, TV) :- tactic_value(Tactic, Contract, Leader, LeadSuit, V1), !, prob_value(Tactic, V2), TV is V1 * V2. enhance_plan(Plan, [], Plan, []) :- !. enhance_plan((V, Plan), [(V1, Plan1)|Plans], BestPlan, [(V,Plan)|OtherPlans]) :- better_tactics(Plan1, Plan), !, %format("Plan = ~p, BPlan = ~p~n",[Plan, Plan1]), enhance_plan((V1,Plan1), Plans, BestPlan, OtherPlans). enhance_plan(Plan, [Plan1|Plans], BestPlan, [Plan1|OtherPlans]) :- enhance_plan(Plan, Plans, BestPlan, OtherPlans). better_tactics([],[]) :- !. better_tactics([Tactic|Tactics1],[Tactic|Tactics]) :- !, better_tactics(Tactics1, Tactics). better_tactics([Tactic1|Tactics1],[Tactic|Tactics]) :- arg(1, Tactic, Type), arg(1, Tactic1, Type), arg(3, Tactic, W), arg(3, Tactic1, W1), better(W1, W), !, better_tactics(Tactics1, Tactics). better_tactics([Tactic1|Tactics1],[Tactic|Tactics]) :- arg(1, Tactic, cash), arg(1, Tactic1, develop), arg(3, Tactic, W), arg(3, Tactic1, W1), better(W1, W), !, better_tactics(Tactics1, Tactics). better_tactics([Tactic1|Tactics1],[Tactic|Tactics]) :- arg(1, Tactic, develop), arg(1, Tactic1, cash), arg(3, Tactic, W), arg(3, Tactic1, W1), better(W1, W), !, better_tactics(Tactics1, Tactics). better_tactics([Tactic1|Tactics1],[Tactic|Tactics]) :- ( arg(1, Tactic, cash) ; arg(1, Tactic, develop) ), arg(1, Tactic1, Fin), finesseable(Fin), arg(3, Tactic, W), arg(3, Tactic1, W1), better(W1, W), !, better_tactics(Tactics1, Tactics). better(W1+W2-_,W3+W4-_) :- W1 + W2 > W3 + W4. better(W1+W2-_,W3+W4-_) :- W1 + W2 =:= W3 + W4, W1 > W3. better(W1,W2+W3-_) :- W1 > W2 + W3. better(W1+W2-_,W) :- W1 + W2 > W. better(N2,N1) :- N2 > N1. %tactic_value(Tactic, Contract, Leader, LeadSuit, V1), !, tactic_value(Tactic, _,_, _, 1) :- %(arg(1, Tactic, develop); arg(1, Tactic, cash)), !. tactic_value(Tactic, contract(_,_,Dec), _, _, 1) :- ( arg(1,Tactic,sim_fin_dec) ; arg(1,Tactic,dbl1_fin_dec) ; arg(1,Tactic,dbl2_fin_dec) ), functor(Tactic, Suit,_), next_play(Dec,Next), Known =.. [Suit,void,Next], clause(known(Known),_), !. tactic_value(Tactic, contract(_,_,Dec), _, _, 1) :- ( arg(1,Tactic,sim_fin_dum) ; arg(1,Tactic,dbl1_fin_dum) ; arg(1,Tactic,dbl2_fin_dum) ), functor(Tactic, Suit, _), next_play(Next,Dec), Known =.. [Suit,void,Next], clause(known(Known),_), !. tactic_value(Tactic, contract(_,_,Dec), _, _, 999) :- ( arg(1,Tactic,sim_fin_dec) ; arg(1,Tactic,dbl1_fin_dec) ; arg(1,Tactic,dbl2_fin_dec) ), functor(Tactic, Suit,_), next_play(Next,Dec), Known =.. [Suit,void,Next], clause(known(Known),_), !, fail. tactic_value(Tactic, contract(_,_,Dec), _, _, 999) :- ( arg(1,Tactic,sim_fin_dum) ; arg(1,Tactic,dbl1_fin_dum) ; arg(1,Tactic,dbl2_fin_dum) ), functor(Tactic, Suit, _), next_play(Dec,Next), Known =.. [Suit,void,Next], clause(known(Known),_), !, fail. tactic_value(Tactic, contract(_,_,Dec), Leader, LeadSuit, V) :- ( arg(1, Tactic, sim_fin_dec), !, ( functor(Tactic,LeadSuit,_), next_play(Dec, Leader), functor(Tactic, Suit,_), winners(Suit, W1), arg(3,Tactic,W2), W2 is W1 + 1, V = 1 ; V = 2 ) ) ; ( arg(1, Tactic, sim_fin_dum), !, ( functor(Tactic,LeadSuit,_), next_play(Leader, Dec), functor(Tactic, Suit,_), winners(Suit, W1), arg(3, Tactic, W2), W2 is W1 + 1, V = 1 ; V = 2 ) ). tactic_value(Tactic, _, _, _, 2) :- arg(1, Tactic, sim_dfin_dec) ; arg(1, Tactic, sim_dfin_dum) ; arg(1, Tactic, rev_fin_dec) ; arg(1, Tactic, rev_fin_dum) ; arg(1, Tactic, rev_dfin_dec) ; arg(1, Tactic, rev_dfin_dum). tactic_value(Tactic, contract(_,_,Dec), Leader, LeadSuit, V) :- ( ( arg(1, Tactic, dbl1_fin_dec) ; arg(1, Tactic, dbl1_dfin_dec) ), !, ( functor(Tactic,LeadSuit,_), next_play(Dec, Leader), V = 1 ; V = 4/3) ) ; ( ( arg(1, Tactic, dbl1_fin_dum) ; arg(1, Tactic, dbl1_dfin_dum) ), !, ( functor(Tactic,LeadSuit,_), next_play(Leader, Dec), V = 1 ; V = 4/3 ) ). tactic_value(Tactic, contract(_,_,Dec), Leader, LeadSuit, V) :- ( ( arg(1, Tactic, dbl2_fin_dec) ; arg(1, Tactic, dbl2_dfin_dec) ), !, ( functor(Tactic,LeadSuit,_), next_play(Dec, Leader), V = 2 ; V = 4 ) ) ; ( ( arg(1, Tactic, dbl2_fin_dum) ; arg(1, Tactic, dbl2_dfin_dum) ), !, ( functor(Tactic,LeadSuit,_), next_play(Leader, Dec), V = 2 ; V = 4 ) ). %prob_value(Tactic, V2), prob_value(Tactic, 999) :- functor(Tactic,Suit,_), arg(2,Tactic,Prob), Failed =.. [Suit,Prob], clause(failed(Failed),_), !, fail. prob_value(Tactic, 1) :- arg(2,Tactic,cert), !. prob_value(Tactic, 3/2) :- arg(2,Tactic,usual), !. prob_value(Tactic, 3) :- arg(2,Tactic,pos), !. simplify_tactic(entries(_,_),[]) :- !. simplify_tactic(Tactic,STactic) :- arg(1,Tactic,C), arg(2,Tactic,U), arg(3,Tactic,P), arg(4,Tactic,CD), arg(5,Tactic,UD), arg(6,Tactic,PD), remove_multiples([cert,C,usual,U,pos,P],Cash), functor(Tactic,Name,_), new_tactic(Name,Cash,Cash1), dev_name(Name,DevName), simplify_dev([C,U,P],[CD,UD,PD],Dev), remove_multiples(Dev,Dev1), new_tactic(DevName,Dev1,NDev1), append(Cash1,NDev1,STactic). remove_multiples([],[]) :- !. remove_multiples([Prob1,Pot1],[Prob1,Pot1]) :- !. remove_multiples([Prob1,Pot1,_,Pot1],[Prob1,Pot1]) :- !. remove_multiples([Prob1,Pot1,Prob2,Pot2],[Prob1,Pot1,Prob2,Pot2]) :- !. remove_multiples([Prob1,Pot1,_,Pot1,_,Pot1],[Prob1,Pot1]) :- !. remove_multiples([Prob1,Pot1,Prob2,Pot2,_,Pot2],[Prob1,Pot1,Prob2,Pot2]):-!. remove_multiples([Prob1,Pot1,_,Pot1,Prob3,Pot3],[Prob1,Pot1,Prob3,Pot3]):-!. remove_multiples(Tricks,Tricks). new_tactic(_,[],[]). new_tactic(Name,[Prob,Pot|Tricks], [New_Tactic|Tricks1]) :- functor(New_Tactic,Name,2), arg(1,New_Tactic,Prob), arg(2,New_Tactic,Pot), new_tactic(Name,Tricks,Tricks1). simplify_dev([C,U,P],[CD,UD,PD],[cert,CD1|Dev]) :- win_lose(CD,W,L), W > C, !, W1 is W - C, win_lose(CD1,C+W1,L), simplify_dev([U,P],[UD,PD],Dev). simplify_dev([U,P],[UD,PD],[usual,UD1|Dev]) :- win_lose(UD,W,L), W > U, !, W1 is W - U, win_lose(UD1,U+W1,L), simplify_dev([P],[PD],Dev). simplify_dev([P],[PD],[pos,PD1]) :- win_lose(PD,W,L), W > P, !, W1 is W - P, win_lose(PD1,P+W1,L). simplify_dev([_|W],[_|D],Dev) :- simplify_dev(W, D, Dev). simplify_dev([],[],[]). %win_lose(W-L,W1+W2,L) :- var(W), W is W1 + W2, !. win_lose(W-L,W,L) :- !. %win_lose(W,W1+W2,0) :- var(W), W is W1 + W2, !. win_lose(W,W,0) :- !. dev_name(cash,develop). dev_name(sim_fin_dec,sim_dfin_dec). dev_name(sim_fin_dum,sim_dfin_dum). dev_name(rev_fin_dec,rev_dfin_dec). dev_name(rev_fin_dum,rev_dfin_dum). dev_name(dbl1_fin_dec,dbl1_dfin_dec). dev_name(dbl1_fin_dum,dbl1_dfin_dum). dev_name(dbl2_fin_dec,dbl2_dfin_dec). dev_name(dbl2_fin_dum,dbl2_dfin_dum). finesseable(sim_fin_dec) :- !. finesseable(sim_fin_dum) :- !. finesseable(rev_fin_dec) :- !. finesseable(rev_fin_dum) :- !. finesseable(dbl1_fin_dec) :- !. finesseable(dbl1_fin_dum) :- !. finesseable(dbl2_fin_dec) :- !. finesseable(dbl2_fin_dum) :- !. finesseable(sim_dfin_dec) :- !. finesseable(sim_dfin_dum) :- !. finesseable(rev_dfin_dec) :- !. finesseable(rev_dfin_dum) :- !. finesseable(dbl1_dfin_dec) :- !. finesseable(dbl1_dfin_dum) :- !. finesseable(dbl2_dfin_dec) :- !. finesseable(dbl2_dfin_dum) :- !. better_to_develop(N1,N1,N1,N1,_,N2-_,_) :- N2 > N1, !. better_to_develop(N1,N1,_,_,N2-_,_,_) :- N2 > N1, !. better_to_develop(N1,_,N1,_,_,N2-_,_) :- N2 > N1, !. better_to_develop(N1,_,_,N1,_,_,N2-_) :- N2 > N1, !. create_hand(Hand) :- write_deal(Hand), curpos(1,24), choose_hand(Hand). choose_hand(Hand) :- format("Choose player: ",[]), read_line([P|_]), name(Initial, [P]), make_hand(Initial, Hand). make_hand(q,Hand) :- !, write_hand(Hand). make_hand(r,Hand) :- !, create_hand(Hand). make_hand(Initial,Hand) :- player_initial(Player,Initial), !, choose_suit(Player,Hand, s). make_hand(_,Hand) :- format("Type in player [n,s,e,w] or [q] to write hand or [r] to redraw~n",[]), !, choose_hand(Hand). choose_suit(Player,Hand, Init) :- suit_initial(SName, Init), format("Choose suit (~p): ",[SName]), read_line(Suit), get_initial(Init, Suit, Initial), !, make_suit(Initial,Player,Hand). make_suit(p,_,Hand) :- !, choose_hand(Hand). make_suit(q,_,Hand) :- !, choose_hand(Hand). make_suit(Initial, Player, Hand) :- suit_initial(Suit, Initial), !, format("Type in cards: ",[]), get_cards(Cards,Initial,Player,Hand), update(Hand,Cards,Suit,Player,Hand1), co_ordinates(Player,X,Y,_,_), update_x(X,X1), update_y(Y,Suit,Y1), cards_in_box(Cards,X1,Y1,Suit), curpos(1,24), next_suit(Suit, NSuit), suit_initial(NSuit, NInitial), choose_suit(Player,Hand1, NInitial). make_suit(_,Player,Hand) :- format("Type in a suit [s,h,d,c] or [p/q] to choose new player~n",[]), !, choose_suit(Player,Hand, s). write_hand(hand(N,S,E,W)) :- check_hand(hand(N,S,E,W)), !, format("Give hand I.D. number: ",[]), read_line(Cs), name(ID,Cs), format("This hand is recorded as ~p~n",[ID]), open('eg.pl',append,Stream), format(Stream,"~p :- play_hand(hand(~n",[ID]), write_suits(N,S,E,W,Stream), flush_output(Stream), close(Stream). write_hand(Hand) :- choose_hand(Hand). write_suits([N1,N2,N3,N4],[S1,S2,S3,S4],[E1,E2,E3,E4],[W1,W2,W3,W4],Stream) :- format(Stream,"[~p,~p,~n~p,~p],~n",[N1,N2,N3,N4]), format(Stream,"[~p,~p,~n~p,~p],~n",[S1,S2,S3,S4]), format(Stream,"[~p,~p,~n~p,~p],~n",[E1,E2,E3,E4]), format(Stream,"[~p,~p,~n~p,~p])).~n~n",[W1,W2,W3,W4]). get_initial(Init, [], Init). get_initial(_,[S|_], Initial) :- name(Initial,[S]). get_cards(Cards,_,_,_) :- read_line(L), cards(Unsorted,L), !, sort(Unsorted,Sorted), reverse(Sorted,Cards). get_cards(_,Initial,Player,Hand) :- format("Illegal card selection~n",[]), make_suit(Initial,Player,Hand). cards([],[]) :- !. cards(Cards,[32|Ls]) :- !, cards(Cards,Ls). cards([VCard|VCards],[L|Ls]) :- name(Card,[L]), value(Card,VCard), cards(VCards,Ls). update(Hands,Cards,Suit,Player,Hands1) :- components(Hands,Player,Hand,Others), replace_suit(Hand,Suit,Cards,Hand1), components(Hands1,Player,Hand1,Others). replace_suit([suit(_,Suit,_)|Rest],Suit,Cards,[suit(L,Suit,Cards)|Rest]) :- !, length(Cards,L). replace_suit([Suit|Suits],SuitName,Cards,[Suit|Suits1]) :- replace_suit(Suits,SuitName,Cards,Suits1). components(hand(N,S,E,W),north,N,[S,E,W]). components(hand(N,S,E,W),south,S,[N,E,W]). components(hand(N,S,E,W),west,W,[N,E,S]). components(hand(N,S,E,W),east,E,[N,W,S]). add_cards(Hand,[Card|Cards],Suit,Hand1) :- add_card(Hand,card(Suit,Card),NewHand), add_cards(NewHand,Cards,Suit,Hand1). add_cards(Hand1,[],_,Hand1). check_hand(hand(N,S,E,W)) :- merge(N,S,E,W,_). merge([suit(_,Suit,Cards1)|Rest1],[suit(_,_,Cards2)|Rest2], [suit(_,_,Cards3)|Rest3],[suit(_,_,Cards4)|Rest4], [suit(L,Suit,Cards)|Rest]) :- merge_suit(Suit,Cards1,Cards2,Cards3,Cards4,Cards), length(Cards,L), merge(Rest1,Rest2,Rest3,Rest4,Rest). merge([],[],[],[],[]). merge_suit(Suit,C1,C2,C3,C4,C) :- merge(Suit,C1,C2,C12), merge(Suit,C3,C4,C34), merge(Suit,C12,C34,C). merge(Suit,[X|_],[X|_],_) :- !, format("Illegal Hand. The ~p of ~p appears twice~n",[X,Suit]), fail. merge(Suit,[X|Xs],[Y|Ys],[X|Zs]) :- X > Y, !, merge(Suit,Xs,[Y|Ys],Zs). merge(Suit,[X|Xs],[Y|Ys],[Y|Zs]) :- Y > X, !, merge(Suit,[X|Xs],Ys,Zs). merge(_,Xs,[],Xs) :- !. merge(_,[],Ys,Ys). /* ================================================================== */ /* facts.pl */ /* */ /* Miscellaneous Bridge Facts */ /* */ /* Author - Yossi Nygate */ /* Last Modified - October 30, 1988. */ /* ================================================================== */ /* Predicates list : predicate name number of arguments -------------- ------------------- suits 1 suit_initial 2 player_initial 2 next_play 2 pack 1 */ suits([spades,hearts,diamonds,clubs]). suit_initial(spades,s). suit_initial(diamonds,d). suit_initial(hearts,h). suit_initial(clubs,c). suit_initial(notrumps,n). player_initial(north,n). player_initial(south,s). player_initial(east,e). player_initial(west,w). next_play(south,west). next_play(west,north). next_play(north,east). next_play(east,south). next_suit(spades, hearts). next_suit(hearts, diamonds). next_suit(diamonds, clubs). next_suit(clubs, spades). pack([suit(13,spades,[14,13,12,11,10,9,8,7,6,5,4,3,2]), suit(13,hearts,[14,13,12,11,10,9,8,7,6,5,4,3,2]), suit(13,diamonds,[14,13,12,11,10,9,8,7,6,5,4,3,2]), suit(13,clubs,[14,13,12,11,10,9,8,7,6,5,4,3,2])]). value('A',14) :- !. value('K',13) :- !. value('Q',12) :- !. value('J',11) :- !. value('T',10) :- !. value('a',14) :- !. value('k',13) :- !. value('q',12) :- !. value('j',11) :- !. value('t',10) :- !. value(Value,Value) :- integer(Value), Value >=2. portray(north) :- !,write('North'). portray(south) :- !,write('South'). portray(west) :- !,write('West'). portray(east) :- !,write('East'). portray(spades) :- !, write('Spades'). portray(hearts) :- !, write('Hearts'). portray(diamonds) :- !, write('Diamonds'). portray(clubs) :- !, write('Clubs'). portray(14) :- write('A'). portray(13) :- write('K'). portray(12) :- write('Q'). portray(11) :- write('J'). portray(10) :- write('T'). portray(N) :- integer(N), N < 10, write(N). portray(N) :- not(integer(N)), write(N). ux :- unix(shell). ns :- nospyall. db :- debug. ndb :- nodebug. br :- reconsult(bridge). an :- reconsult(analysis). sy :- reconsult(synthesis). pl :- reconsult(planning). ex :- reconsult(exec_mon). tr :- reconsult(trick). rp(N) :- ndb, name('save/trick',Name), name(N,N1), append(Name,N1,NName), name(File,NName), [File]. sp :- save_program(aspen). sp(N) :- save_program(N). tl(N) :- retract_it(trace_lvl(_)), assert(trace_lvl(N)). not(X) :- X,!,fail. not(_). %member(X,[X|_]). %member(X,[_|Ys]) :- member(X,Ys). delete(X,[X|Xs],Xs). delete(X,[X1|Xs],[X1|Xs1]) :- delete(X,Xs,Xs1). recursive_delete(Elem, [List|Lists], [NList|Lists]) :- delete(Elem, List, NList). recursive_delete(Elem, [List|Lists], [List|NLists]) :- recursive_delete(Elem, Lists, NLists). recursive_delete(Elem, List, NList) :- delete(Elem, List, NList). flatten([],[]). flatten([X|Xs],Flattened) :- !, flatten(X,FlattenX), flatten(Xs,FlattenXs), append(FlattenX,FlattenXs,Flattened). flatten(X,[X]). reverse(Xs,Ys) :- reverse(Xs,[],Ys). reverse([X|Xs],Revs,Ys) :- reverse(Xs,[X|Revs],Ys). reverse([],Ys,Ys). %append([],Ys,Ys). %append([X|Xs],Ys,[X|Zs]) :- append(Xs,Ys,Zs). merge([],Xs,Xs) :- !. merge(Xs,[],Xs) :- !. merge([X|Xs],[Y|Ys],[X|Zs]) :- X > Y, !, merge(Xs,[Y|Ys],Zs). merge([X|Xs],[Y|Ys],[Y|Zs]) :- merge([X|Xs],Ys,Zs). max(A, B, A) :- A >= B, !. max(_, B, B). min(A, B, B) :- A >= B, !. min(A, _, A). abs(X,X) :- X > 0, !. abs(X,Y) :- Y is X * -1. read_atom(Atom) :- read_line(Line), name(Atom, Line). % Now a built-in in Sicstus 4 %read_line(Line) :- %get0(C), %read_line(C, Line). % %read_line(10, []) :- !. % %read_line(C, [C|Cs]) :- %get0(C2), %read_line(C2, Cs). /* order plan to play in right sequence for now suit with most tricks first */ hi_lvl_plans([],[]) :- !. hi_lvl_plans([(Prob,Plan)|Plans],HLP) :- hi_lvl_plan(Plan,HLP), requirements(Prob,HLP), assert_other_plans(Plans). /* hi_lvl_plans([_|Plans],HLP) :- hi_lvl_plans(Plans,HLP). */ assert_other_plans([Plan|Plans]) :- assert(other_plans(Plan)), assert_other_plans(Plans). assert_other_plans([]). hi_lvl_plan([Suit],[Suit]) :- !. hi_lvl_plan(Plan,[Suit|Suits]) :- best_suit(Plan, Suit, RPlan), hi_lvl_plan(RPlan, Suits). best_suit([Suit], Suit, []) :- !. best_suit([Suit|Suits], Suit, Suits) :- best_suit(Suits, Suit1, _), arg(3, Suit, Tricks), functor(Suit,S,_), functor(Suit1,S1,_), number_of_actions(_, _, S, N), number_of_actions(_, _, S1,N1), arg(3, Suit1, Tricks1), num_tricks(Tricks,Val), num_tricks(Tricks1,Val1), Val + N > Val1 + N1, !. best_suit([Suit|Suits], BestSuit, [Suit|RSuits]) :- best_suit(Suits, BestSuit, RSuits). num_tricks(W1+W2-W3, W) :- W is W1+W2+W3, !. num_tricks(W, W) :- !. decompose_and_splice(Tactics, Dec, Dum, Def1, Def2, contract(_, _, Declarer), Lo_lvl) :- decompose_plan(Tactics, Declarer, Dec, Dum, Def1, Def2, Lo_lvl), (trace_lvl(P), P >= 3, format("Before Splicing ~p~n",[Lo_lvl]); true), flatten(Lo_lvl, Flattened), splice(Flattened, Declarer, DecEnts, DumEnts), format("Entries needed are Dec = ~d Dum = ~d~n",[DecEnts, DumEnts]). %splice_plan(Lo_lvl,Lo_lvl1). decompose_and_splice(_, Dec, Dum, Def1, Def2, contract(_, _, Declarer), Lo_lvl) :- retract_it(plan(_,_)), other_plans((Prob,Plan)), decompose_plan(Plan, Declarer, Dec, Dum, Def1, Def2, Lo_lvl), (trace_lvl(P), P >= 3, format("Before Splicing ~p~n",[Lo_lvl]); true), flatten(Lo_lvl, Flattened), splice(Flattened, Declarer, DecEnts, DumEnts), format("Entries needed are Dec = ~d Dum = ~d~n",[DecEnts, DumEnts]), requirements(Prob,Plan). %splice_plan(Lo_lvl,Lo_lvl1). splice([_], _, 0, 0). /* two finesses might not need any more entries */ splice([finesse(_,_,_),finesse(_,_,P)|Acts], Declarer, DecEnts, DumEnts) :- splice([finesse(_,_,P)|Acts], Declarer, DecEnts, DumEnts). splice([cash(_,_,P1),finesse(_,_,P2)|Acts], Declarer, DecEnts, DumEnts) :- partner(P1,P2), splice([finesse(_,_,P2)|Acts], Declarer, DecEnts, DumEnts). splice([cash(_,_,Declarer),finesse(_,_,Declarer)|Acts], Declarer, DecEnts, DumEnts1) :- splice([finesse(_,_,Declarer)|Acts], Declarer, DecEnts, DumEnts), DumEnts1 is DumEnts + 1. splice([cash(_,_,Dummy), finesse(_,_,Dummy)|Acts], Declarer, DecEnts1, DumEnts) :- partner(Declarer, Dummy), splice([finesse(_,_,Dummy)|Acts], Declarer, DecEnts, DumEnts), DecEnts1 is DecEnts + 1. splice([Act1,Act2|Acts], Declarer, DecEnts1, DumEnts) :- functor(Act1, Func1,_), Func1 \== cash, arg(3,Act2,Declarer), splice([Act2|Acts], Declarer, DecEnts, DumEnts), DecEnts1 is DecEnts + 1. splice([Act1,Act2|Acts], Declarer, DecEnts, DumEnts1) :- functor(Act1, Func1,_), Func1 \== cash, arg(3,Act2,Dummy), partner(Declarer, Dummy), splice([Act2|Acts], Declarer, DecEnts, DumEnts), DumEnts1 is DumEnts + 1. splice([_,Act|Acts], Declarer, DecEnts, DumEnts) :- splice([Act|Acts], Declarer, DecEnts, DumEnts). splice_plan(Lo_lvl,Lo_lvl) :- !. splice_plan(Lo_lvl,RLo_lvl) :- /* format("Decomposed Plan before Splicing:~n",[]), write_plan(Lo_lvl), */ fail, splice_plan(Lo_lvl, [], Lo_lvl1), reverse(Lo_lvl1,RLo_lvl). splice_plan(Lo_lvl, _) :- !, format("Unable to Splice Plan - not enough entries:~n",[]), write_plan(Lo_lvl), fail. splice_plan([], Sofar, Sofar). splice_plan([Tactic,finesse(Num,Suit,Player)|Lo_lvl], Sofar, Lo_lvl1) :- arg(3,Tactic,Player), delete(Tactic1,Lo_lvl,Lo_lvls), arg(2,Tactic1, Suit1), arg(3,Tactic1, Player1), Player \== Player1, Suit1 \== Suit, !, splice_plan(Lo_lvls, [finesse(Num,Suit,Player),Tactic1,Tactic|Sofar],Lo_lvl1). splice_plan([Tactic|Lo_lvl], Sofar, Lo_lvl1) :- splice_plan(Lo_lvl, [Tactic|Sofar], Lo_lvl1). decompose_plan([], _, _, _, _, _, []) :- !. decompose_plan([STactic|STactics], Declarer, Dec, Dum, Def1, Def2, Decomposed) :- functor(STactic,Suit,_), get_suit(Dec, Suit, DecCards), get_suit(Dum, Suit, DumCards), get_suit(Def1, Suit, Def1Cards), get_suit(Def2, Suit, Def2Cards), merge(Def1Cards, Def2Cards, Def), arg(1,STactic,Tactic), arg(3,STactic,Winners), decompose_tactic1(Suit, Tactic, Winners, Declarer, DecCards, DumCards, Def, Lo_lvl), decompose_plan(STactics, Declarer, Dec, Dum, Def1, Def2, Lo_lvls), append([Lo_lvl],Lo_lvls,Decomposed), !. safety_play(cash, Suit, DecCards, [_|DumCards], Declarer, [cash(1, Suit, Dummy)], DecCards1, DumCards, 1) :- length(DecCards, L1), length([_|DumCards], L2), 9 is L1 + L2, %here, analysis(Suit, Analysis), member(sim_fin_dum(_,_,_,_,_,_),Analysis), member(sim_fin_dec(_,_,_,_,_,_),Analysis), member(entries(1,2),Analysis), !, partner(Declarer,Dummy), delete_lowest(DecCards,DecCards1). safety_play(cash, Suit, [_|DecCards], DumCards, Declarer, [cash(1, Suit, Declarer)], DecCards, DumCards1, 1) :- length([_|DecCards], L1), length(DumCards, L2), 9 is L1 + L2, analysis(Suit, Analysis), member(sim_fin_dum(_,_,_,_,_,_),Analysis), member(sim_fin_dec(_,_,_,_,_,_),Analysis), member(entries(2,1),Analysis), !, delete_lowest(DumCards,DumCards1). safety_play(cash, Suit, DecCards, [_|DumCards], Declarer, [cash(1, Suit, Dummy)], DecCards1, DumCards, 1) :- length(DecCards, L1), length([_|DumCards], L2), 9 is L1 + L2, analysis(Suit, Analysis), member(dbl2_fin_dec(_,_,_,_,_,_),Analysis), member(entries(1,2),Analysis), !, partner(Declarer,Dummy), delete_lowest(DecCards,DecCards1). safety_play(cash, Suit, [_|DecCards], DumCards, Declarer, [cash(1, Suit, Declarer)], DecCards, DumCards1, 1) :- length([_|DecCards], L1), length(DumCards, L2), 9 is L1 + L2, analysis(Suit, Analysis), member(dbl2_fin_dum(_,_,_,_,_,_),Analysis), member(entries(1,2),Analysis), !, delete_lowest(DumCards,DumCards1). /* Generalized Safety Play for something like A,10,x,x vs K,Q,x,x */ safety_play(cash, Suit, DecCards, [_|DumCards], Declarer, [cash(1, Suit, Dummy)], DecCards1, DumCards, 1) :- analysis(Suit, Analysis), member(sim_fin_dec(_,_,_,_,_,_),Analysis), member(entries(_,N),Analysis), !, N > 0, partner(Declarer,Dummy), delete_lowest(DecCards,DecCards1). safety_play(cash, Suit, [_|DecCards], DumCards, Declarer, [cash(1, Suit, Declarer)], DecCards, DumCards1, 1) :- analysis(Suit, Analysis), member(sim_fin_dum(_,_,_,_,_,_),Analysis), member(entries(N,_),Analysis), !, N > 0, delete_lowest(DumCards,DumCards1). decompose_tactic1(Suit, Tactic, Winners, Declarer, DecCards, DumCards, [Highest|DefCards], Lo_lvl) :- length(DecCards, L1), length(DumCards, L2), length([Highest|DefCards], L3), 13 is L1 + L2 + L3, safety_play(Tactic, Suit, DecCards, DumCards, Declarer, Lo_lvl1, DecCards1, DumCards1, Num), !, Winners1 is Winners - Num, decompose_tactic(Suit, Tactic, Winners1, Declarer, DecCards1, DumCards1, Highest, Lo_lvls), append(Lo_lvl1,Lo_lvls,Lo_lvl). decompose_tactic1(Suit, Tactic, Winners, Declarer, DecCards, DumCards, [Highest|_], Lo_lvl) :- decompose_tactic(Suit, Tactic, Winners, Declarer, DecCards, DumCards, Highest, Lo_lvl). decompose_tactic1(Suit, Tactic, Winners, Declarer, DecCards, DumCards, [], Lo_lvl) :- decompose_tactic(Suit, Tactic, Winners, Declarer, DecCards, DumCards, 0, Lo_lvl). decompose_tactic(_, _, 0, _, _, _, _, []). decompose_tactic(Suit, cash, Winners, Declarer, DecCards, [], _, Tactics) :- !, length(DecCards, L), decompose(cash, Winners, Suit, Declarer, L, 0, Tactics). decompose_tactic(Suit, cash, Winners, Declarer, [], DumCards, _, Tactics) :- !, length(DumCards, L), decompose(cash, Winners, Suit, Declarer, 0, L, Tactics). decompose_tactic(Suit,cash,Winners,Declarer, [Dec1|DecCards],[Dum1|DumCards], DefHighest, [cash(1,Suit,Declarer)|Tactics]):- ( ( Dec1 > DefHighest, Dum1 > DefHighest, length(DecCards,L1), length(DumCards,L2), L1 < L2 ); ( Dec1 > DefHighest, Dum1 < DefHighest ); ( Dec1 < DefHighest, Dum1 < DefHighest, Dec1 > Dum1 ) ), !, delete_highest([Dec1|DecCards], DecCards1), delete_lowest([Dum1|DumCards], DumCards1), Winners1 is Winners - 1, decompose_tactic(Suit, cash, Winners1, Declarer, DecCards1, DumCards1, DefHighest, Tactics). decompose_tactic(Suit,cash,Winners,Declarer, DecCards,DumCards, DefHighest, [cash(1,Suit,Dummy)|Tactics]):- partner(Declarer, Dummy), delete_highest(DumCards, DumCards1), delete_lowest(DecCards, DecCards1), Winners1 is Winners - 1, decompose_tactic(Suit, cash, Winners1, Declarer, DecCards1, DumCards1, DefHighest, Tactics). decompose_tactic(Suit, develop, 0 + Winners - Losers, Declarer, DecCards, DumCards, _, Tactics) :- !, Num is Winners + Losers, length(DecCards, L1), length(DumCards, L2), decompose(develop, Num, Suit, Declarer, L1, L2, Tactics). /* Only duck if number of potential winners > number of losers */ decompose_tactic(Suit, develop, W1 + W2 - Losers, Declarer, DecCards, DumCards, DefHighest, Tactics):- W1 + W2 > Losers, !, length(DecCards, L1), length(DumCards, L2), ( L1 < L2, number_higher([DefHighest], DecCards, Cash1), decompose_tactic(Suit, cash, Cash1, Declarer, DecCards, DumCards, DefHighest, Tactics1), delete_played(DecCards, Cash1, DefHighest, DecCards1), delete_played(DumCards, Cash1, 999, DumCards1) ; ( L1 > L2, number_higher([DefHighest], DumCards, Cash1), decompose_tactic(Suit, cash, Cash1, Declarer, DecCards, DumCards, DefHighest, Tactics1), delete_played(DecCards, Cash1, 999, DecCards1), delete_played(DumCards, Cash1, DefHighest, DumCards1) ; Cash1 = 0, Tactics1 = [], DecCards1 = DecCards, DumCards1 = DumCards ) ), NL1 is L1 - Cash1, NL2 is L2 - Cash1, decompose(duck, Losers, Suit, Declarer, NL1, NL2, Tactics2), delete_lowest(Losers, DecCards1, DecCards2), delete_lowest(Losers, DumCards1, DumCards2), Cash is W1 + W2 - Cash1, decompose_tactic(Suit, cash, Cash, Declarer, DecCards2, DumCards2, DefHighest, Tactics3), append(Tactics1, Tactics2, Temp), append(Temp, Tactics3, Tactics). decompose_tactic(Suit, develop, W1 + W2 - Losers, Declarer, DecCards, DumCards, DefHighest, Tactics):- !, decompose_tactic(Suit, cash, W1, Declarer, DecCards, DumCards, DefHighest, Tactics1), delete_winners(DecCards, DefHighest, DecCards1), delete_winners(DumCards, DefHighest, DumCards1), decompose_tactic(Suit, develop, 0 + W2 - Losers, Declarer, DecCards1, DumCards1, _, Tactics2), append(Tactics1, Tactics2, Tactics). decompose_tactic(Suit, sim_fin_dec, Winners, Declarer, DecCards, DumCards, DefHighest, Tactic) :- decompose_finesse(Suit, Winners, Declarer, DecCards, DumCards, DefHighest, Tactic). decompose_tactic(Suit,dbl1_fin_dec, Winners, Declarer, _,_, _, Tactics) :- !, W1 is Winners - 1, decompose(finesse, 2, Suit, Declarer, Tactic1), decompose(cash, W1, Suit, Declarer, Tactic2), append(Tactic1, Tactic2, Tactics). decompose_tactic(Suit,dbl2_fin_dec, Winners, Declarer, DecCards,DumCards, _, Tactics) :- decompose_tactic(Suit,dbl1_fin_dec, Winners, Declarer, DecCards,DumCards, _, Tactics). decompose_tactic(Suit,dbl2_fin_dum, Winners, Declarer, DecCards,DumCards, _, Tactics) :- decompose_tactic(Suit,dbl1_fin_dum, Winners, Declarer, DecCards,DumCards, _, Tactics). decompose_tactic(Suit,dbl2_dfin_dec, Winners, Declarer, DecCards,DumCards, _, Tactics) :- decompose_tactic(Suit,dbl1_dfin_dec, Winners, Declarer, DecCards,DumCards, _, Tactics). decompose_tactic(Suit,dbl2_dfin_dum, Winners, Declarer, DecCards,DumCards, _, Tactics) :- decompose_tactic(Suit,dbl1_dfin_dum, Winners, Declarer, DecCards,DumCards, _, Tactics). decompose_tactic(Suit,dbl1_dfin_dec, W1+W2, Declarer, DecCards,DumCards, _, Tactics) :- decompose_tactic(Suit,dbl1_fin_dec, W1, Declarer, DecCards,DumCards, _, Tactic1), decompose(develop, W2, Suit, both, Tactic2), append(Tactic1,Tactic2,Tactics). decompose_tactic(Suit,dbl1_fin_dum, Winners, Declarer, DecCards,DumCards, _, Tactics) :- partner(Declarer,Dummy), decompose_tactic(Suit,dbl1_fin_dec, Winners,Dummy, DumCards,DecCards, _, Tactics). decompose_tactic(Suit,dbl1_dfin_dum, Winners, Declarer, DecCards,DumCards, _, Tactics) :- partner(Declarer,Dummy), decompose_tactic(Suit,dbl1_dfin_dec, Winners,Dummy, DumCards,DecCards, _, Tactics). decompose_tactic(Suit,sim_dfin_dec, W1+W2-L, Declarer, DecCards, DumCards, DefHighest, Tactics) :- decompose_tactic(Suit,sim_fin_dec, W1, Declarer, DecCards,DumCards, DefHighest, Tactic1), %here, Num is W2 + L, length(DecCards, L1), length(DumCards, L2), NL1 is L1 - W1, NL2 is L2 - W1, decompose(develop, Num, Suit, Declarer, NL1, NL2, Tactic2), append(Tactic1,Tactic2,Tactics). decompose_tactic(Suit,sim_dfin_dum, Winners, Declarer, DecCards, DumCards, DefHighest, Tactics) :- partner(Declarer,Dummy), decompose_tactic(Suit,sim_dfin_dec, Winners,Dummy, DumCards,DecCards, DefHighest, Tactics). decompose_tactic(Suit,sim_fin_dum, Winners, Declarer, DecCards, DumCards, DefHighest, Tactics) :- partner(Declarer,Dummy), decompose_finesse(Suit, Winners, Dummy, DumCards, DecCards, DefHighest, Tactics). decompose_tactic(Suit, rev_fin_dum, Winners,Declarer, DecCards,DumCards, DefHighest, Tactics) :- decompose_tactic(Suit, sim_fin_dum, Winners,Declarer, DecCards,DumCards, DefHighest, Tactics). decompose_tactic(Suit, rev_fin_dec, Winners, Declarer, DecCards, DumCards, DefHighest, Tactics) :- decompose_tactic(Suit, sim_fin_dec, Winners, Declarer, DecCards, DumCards, DefHighest, Tactics). decompose_finesse(Suit, Winners, Declarer, DecCards, DumCards, DefHighest, Tactic) :- tops(DecCards, DefHighest, Tops_Dec), tops(DumCards, DefHighest, Tops_Dum), length(DumCards,LDum), length(DecCards,LDec), partner(Declarer,Dummy), %Cash dummy's winner if declarer has more or the same number of cards */ ( LDec >= LDum, decompose(cash, Tops_Dum, Suit, Dummy, Tactic1), decompose(cash, Tops_Dec, Suit, Declarer, Tactic3), Tactic4 = [] ; decompose(cash, Tops_Dec, Suit, Declarer, Tactic3), decompose(cash, Tops_Dum, Suit, Dummy, Tactic4), Tactic1 = [] ), length(Tactic1, Cashed1), length(Tactic3, Cashed3), length(Tactic4, Cashed4), Cashed is Cashed1 + Cashed3 + Cashed4, %Finesse the cards Fin is Winners - Tops_Dec - Tops_Dum, Low_Dum is LDum - Tops_Dum, min(Fin, Low_Dum, Fin1), decompose(finesse, Fin1, Suit, Declarer, Tactic2), Remainder is Winners - Fin1 - Cashed, Rest_Dec is LDec - Fin1 - Cashed, Rest_Dum is LDum - Fin1 - Cashed, decompose(cash, Remainder, Suit, Declarer, Rest_Dec, Rest_Dum, Tactic5), append(Tactic1, Tactic2, Temp1), append(Tactic3, Tactic4, Temp2), append(Temp1, Temp2, Temp), append(Temp,Tactic5, Tactic). decompose(_, 0, _, _, _, _, []) :- !. decompose(HLT, Num, Suit, _, L, L, Tactic) :- !, decompose(HLT, Num, Suit, both, Tactic). decompose(HLT, Num, Suit, _, L1, L2, Tactic) :- Num < L1, Num < L2, !, decompose(HLT, Num, Suit, both, Tactic). decompose(HLT, Num, Suit, Declarer, L1, L2, Tactic) :- L1 > L2, !, decompose(HLT, L2, Suit, both, Tactic1), length(Tactic1, Len), N is Num - Len, decompose(HLT, N, Suit, Declarer, Tactic2), append(Tactic1, Tactic2, Tactic). decompose(HLT, Num, Suit, Declarer, L1, _, Tactic) :- decompose(HLT, L1, Suit, both, Tactic1), length(Tactic1, Len), N is Num - Len, partner(Declarer,Dummy), decompose(HLT, N, Suit, Dummy, Tactic2), append(Tactic1, Tactic2, Tactic). decompose(_,N,_,_,[]) :- N =< 0, !. decompose(Tactic, Winners, Suit, Player,[Decompose|Decomposed]) :- !, Winners1 is Winners - 1, functor(Decompose,Tactic,3), arg(1,Decompose,1), arg(2,Decompose,Suit), arg(3,Decompose,Player), decompose(Tactic,Winners1,Suit,Player,Decomposed). delete_played(Cards, 0, _, Cards) :- !. delete_played([C|Cards], Tops, Highest, Cards1) :- C > Highest, !, Tops1 is Tops - 1, delete_played(Cards, Tops1, Highest, Cards1). delete_played(Cards, Tops, Highest, Cards1) :- delete_lowest(Cards, NCards), Tops1 is Tops - 1, delete_played(NCards, Tops1, Highest, Cards1). delete_lowest(1, Cards, Cards1) :- delete_lowest(Cards,Cards1), !. delete_lowest(2, Cards, Cards1) :- !, delete_2lowest(Cards,Cards1), !. delete_lowest(N, Cards, Cards1) :- append(Cards1,List,Cards), length(List,N),!. delete_lowest(_, _, []). delete_winners([C|Cards], High, Cards1) :- C > High, !, delete_winners(Cards, High, Cards1). delete_winners(Cards, _, Cards). /* if def is on lead and finesse with winners/entries in both hands then choose finesse tactic in this suit*/ choose_tactic_suit(Suit, Tactics, Tactic, Tactics1) :- recursive_delete(Tactic, Tactics, Tactics1), arg(2, Tactic, Suit), functor(Tactic,finesse,_), analysis(Suit,Analysis), member(entries(1,1),Analysis), !, format("Executing Tactic: ~p ~n",[Tactic]). /* else if def is on lead then choose first tactic in their suit*/ choose_tactic_suit(Suit, Tactics, Tactic, Tactics1) :- recursive_delete(Tactic, Tactics, Tactics1), arg(2, Tactic, Suit), format("Executing Tactic: ~p ~n",[Tactic]). choose_tactic_suit(Suit, _, duck(1,Suit,both)) :- format("Executing Tactic: ~p ~n",[duck(1,Suit,both)]). /* if declarer is on lead then choose first legal tactic */ /* we must be in the other hand for a finesse or duck with void opposite */ choose_tactic(Leader,Tactics,Tactic, Tactics1) :- recursive_delete(Tactic, Tactics, Tactics1), ( functor(Tactic, duck, Leader) ; functor(Tactic,finesse,_), arg(3,Tactic,Player), partner(Leader,Player) ), format("Executing Tactic: ~p ~n",[Tactic]). /* For all other tactics we can be in any hand */ choose_tactic(_,Tactics, Tactic, Tactics1) :- recursive_delete(Tactic, Tactics, Tactics1), %functor(Tactic,cash,_); ( functor(Tactic, duck,_); functor(Tactic, develop,_) ), format("Executing Tactic: ~p ~n",[Tactic]). /* tactic_card(Tactic, Contract, Player, Cards, DecSuit1, DecSuit2, DefSuit,Card), Player is who is playing, and Cards are cards that have been played DecSuit1 is the hand to play, DecSuit2 is partner's Presume we are in the right hand and tactic is applicable */ /* play winner from only hand, then shortest hand or duck if both hands have winners and equal length then third hand wins The anyone case is not guaranteed to always be executable */ /* Only 1 player has winner */ tactic_card(cash(_, Suit, anyone), _, _, _, [Card|_], [Card1|_], DefSuit, card(Suit,Card)) :- defenders_highest(DefSuit,H), Card > H, Card1 < H. /* play winner from shorter hand */ tactic_card(cash(_,Suit,anyone), _, _, _, [Card|DecSuit1], [Card1|DecSuit2], DefSuit, card(Suit,Card)) :- defenders_highest(DefSuit,H), Card > H, Card1 > H, length(DecSuit1, L1), length(DecSuit2, L2), L1 < L2. /* play winner in 3/4 hand */ tactic_card(cash(_,Suit,anyone), _, _, [_,_|_], [Card|DecSuit1], [Card1|DecSuit2], DefSuit, card(Suit,Card)) :- defenders_highest(DefSuit,H), Card > H, Card1 > H, length(DecSuit1, L), length(DecSuit2, L). /* else play small */ tactic_card(cash(_,Suit,anyone), _, _, _, DecSuit1, _, _, card(Suit,Card)) :- append(_,[Card],DecSuit1). /* If winner has been chosen */ /* Got a free finesse on opening lead tactic_card(cash(_, Suit, Player), _, Partner, [_], [H1|DecSuit1], [H2|DecSuit2], [Highest|DefSuit] ,card(Suit,HNW1)) :- here, partner(Player, Partner), H1 > Highest, H2 > Highest, highest_non_winner(DecSuit1, Highest, HNW1), number_higher([HNW1], [Highest|DefSuit], 1). */ tactic_card(cash(_,Suit,Player), _, Player, [C1,_,C3], DecSuit1, _, _,card(Suit,Card)) :- defenders_highest(Suit, C1, C3, C), win_cheaply(DecSuit1,C,Card). tactic_card(cash(_,Suit,Player), _, Player, _, [Card|_], _, _,card(Suit,Card)) :- !. tactic_card(cash(_,Suit,_), _, _, _, DecSuit1, _, _,card(Suit,Card)) :- append(_,[Card],DecSuit1). tactic_card(cash(_,Suit,_), _, _, _, [Card|_], _, _,card(Suit,Card)) :- !. tactic_card(cash(_,Suit,_), _, _, _, DecSuit1, _, _,card(Suit,Card)) :- append(_,[Card],DecSuit1). tactic_card(duck(_,Suit,_), _, _, _, DecSuit1, _, _,card(Suit,Card)) :- append(_,[Card],DecSuit1). /* In fourth seat play small if Defenders win trick */ tactic_card(develop(_,Suit,_), _, _, [C1,C2,C3], [Card1|DecSuit1], _, _, card(Suit,Card)) :- ( ( higher(Suit, C1, card(Suit,Card1)), higher(Suit, C1, C2) ) ; ( higher(Suit, C3, card(Suit,Card1)), higher(Suit, C3, C2) ) ), !, append(_,[Card],[Card1|DecSuit1]). /* In fourth seat play small if Partner won the trick */ tactic_card(develop(_,Suit,_), _, _, [C1,C2,C3], [Card1|DecSuit1], _, _, card(Suit,Card)) :- higher(Suit,C2,C1), higher(Suit,C2,C3), !, append(_,[Card],[Card1|DecSuit1]). /* else win cheaply */ tactic_card(develop(_,Suit,_), _, _, [C1,_,C3], [Card1|DecSuit1], _, _, card(Suit,Card)) :- defenders_highest(Suit, C1, C3, C), win_cheaply([Card1|DecSuit1],C,Card). /* In third seat play small if Defenders win trick */ tactic_card(develop(_,Suit,_), _, _, [C1,C2], [Card1|DecSuit1], _, _, card(Suit,Card)) :- higher(Suit, C2, card(Suit,Card1)), higher(Suit, C2, C1), !, append(_,[Card],[Card1|DecSuit1]). /* In third seat play highest if Defender and Partner play small */ tactic_card(develop(_,Suit,_), _, _, [card(Suit,C1),_], [Card1|_], _, Def, card(Suit,Card1)) :- number_higher([Card1], Def, NH1), number_higher([C1], Def, NH2), NH1 < NH2, !. /* else play small */ tactic_card(develop(_,Suit,_), _, _, [_,_], [Card1|DecSuit1], _, _, card(Suit,Card)) :- append(_,[Card],[Card1|DecSuit1]). /* In second seat play small if Defenders win trick */ tactic_card(develop(_,Suit,_), _, _, [C1], [Card1|DecSuit1], [Card2|_], _, card(Suit,Card)) :- higher(Suit, C1, card(Suit,Card1)), higher(Suit, C1, card(Suit,Card2)), !, append(_,[Card],[Card1|DecSuit1]). tactic_card(develop(_,Suit,_), _, _, [C1], [Card1|DecSuit1], [], _, card(Suit,Card)) :- higher(Suit, C1, card(Suit,Card1)), !, append(_,[Card],[Card1|DecSuit1]). /* Play high if hnw greater than partners */ tactic_card(develop(_,Suit,_), _, _, [_], [Card1|_], DecSuit2, Def, card(Suit,Card1)) :- number_higher([Card1], Def, NH1), number_higher(DecSuit2, Def, NH2), NH1 < NH2, !. /* else play lowest */ tactic_card(develop(_,Suit,_), _, _, [_], [Card1|DecSuit1], _, _, card(Suit,Card)) :- !, append(_,[Card],[Card1|DecSuit1]). /* In first seat play hnw if have greater than partner */ tactic_card(develop(_,Suit,_), _, _, [], [Card1|_], DecSuit2, Def, card(Suit,Card1)) :- number_higher([Card1], Def, NH1), number_higher(DecSuit2, Def, NH2), NH1 < NH2, !. /* else play lowest */ tactic_card(develop(_,Suit,_), _, _, [], [Card1|DecSuit1], _, _, card(Suit,Card)) :- append(_,[Card],[Card1|DecSuit1]). tactic_card(finesse(_,Suit,Player), _, ToPlay, Played, [Card1|DecSuit1], [Card2|DecSuit2], [Highest|DefSuit], Cards) :- max(Card1, Card2, Max), Max > Highest, !, ftactic_card(finesse(_,Suit,Player), _, ToPlay, Played, [Card1|DecSuit1], [Card2|DecSuit2], [Highest|DefSuit], Cards). tactic_card(finesse(_,Suit,Player), _, ToPlay, Played, [Card1|DecSuit1], [Card2|DecSuit2], [Highest|DefSuit], Cards) :- rtactic_card(finesse(_,Suit,Player), _, ToPlay, Played, [Card1|DecSuit1], [Card2|DecSuit2], [Highest|DefSuit], Cards). /* 1 reg finesse 4th Seat - partner won, so duck */ ftactic_card(finesse(_,Suit,_), _, _, [C1,C2,C3], DecSuit, _, _, card(Suit,Card)) :- higher(Suit, C2, C1), higher(Suit,C2, C3), append(_,[Card],DecSuit). /* 2 reg finesse 4th Seat - win as cheap as possible */ ftactic_card(finesse(_,Suit,_), _, _, [C1,_,C3], DecSuit, _, _, card(Suit,Card)) :- defenders_highest(Suit, C1, C3, C), win_cheaply(DecSuit,C,Card). /* 3 reg finesse 1st Seat - play hnw if finesse card only in this hand */ ftactic_card(finesse(_, Suit, Player), _, Partner, [], DecSuit1, DecSuit2, [Highest|DefSuit], card(Suit,HNW1)) :- partner(Player, Partner), highest_non_winner(DecSuit1,Highest,HNW1), highest_non_winner(DecSuit2,Highest,HNW2), number_higher([HNW1],[Highest|DefSuit], N1), number_higher([HNW2],[Highest|DefSuit], N2), N1 < N2, !. /* 4 reg finesse 1st Seat - play hnw if both hands have finesse cards but have enough finesse cards to lead hnw and save communication */ ftactic_card(finesse(_, Suit, Player), _, Partner, [], DecSuit1, DecSuit2, [H1,H2|_], card(Suit,HNW1)) :- partner(Player, Partner), %here, highest_non_winner(DecSuit1, H1, HNW1), highest_non_winner(DecSuit2, H1, HNW2), HNW1 > H2, HNW2 > H2, number_between(DecSuit1, H1, H2, N1), number_between(DecSuit2, H1, H2, N2), number_of_actions(_, 1, Suit, Actions), plan((_,Plan),_), member(HLT,Plan), functor(HLT, Suit, _), arg(3,HLT,Potential), winners(Suit, Winners), val(Potential, No_of_Tricks), N1 + N2 >= No_of_Tricks - Winners - Actions, !. /* 5 else reg finesse 1st Seat - play small */ ftactic_card(finesse(_,Suit,Player), _, Partner, [], DecSuit, _, _, card(Suit,LCard)) :- partner(Player, Partner), append(_,[LCard],DecSuit). /* 6 reg finesse any but 1st Seat - play high if finesse card played */ ftactic_card(finesse(_, Suit,Player), _, Player, [card(Suit,Card)|_], [Card1|DecSuit1], DecSuit2, [Highest|_], card(Suit,Card1)) :- highest_non_winner([Card1|DecSuit1], Highest, HNW1), highest_non_winner(DecSuit2, Highest, HNW2), HNW1 < Card, HNW2 < Card, Card1 > Card, !. /* 7 reg finesse 2st Seat - play hnw if finesse card only in this hand and led low*/ ftactic_card(finesse(_,Suit,_), _, _, [card(Suit,Card)], DecSuit1, DecSuit2, [Highest|DefSuit], card(Suit,HNW1)) :- highest_non_winner(DecSuit1,Highest,HNW1), highest_non_winner(DecSuit2,Highest,HNW2), number_higher([HNW1],[Highest|DefSuit], N1), number_higher([HNW2],[Highest|DefSuit], N2), HNW1 > Card, N1 < N2. /* 8 reg finesse 2nd Seat - play hnw if both hands have finesse cards, led low but have enough finesse cards to play hnw and save communication */ ftactic_card(finesse(_, Suit, Player), _, Partner, [card(Suit,Card)], DecSuit1, DecSuit2, [H1,H2|_], card(Suit,HNW1)) :- partner(Player, Partner), %here, highest_non_winner(DecSuit1, H1, HNW1), highest_non_winner(DecSuit2, H1, HNW2), HNW1 > Card, HNW1 > H2, HNW2 > H2, number_between(DecSuit1, H1, H2, N1), number_between(DecSuit2, H1, H2, N2), number_of_actions(_, 1, Suit, Actions), plan((_,Plan),_), member(HLT,Plan), functor(HLT, Suit, _), arg(3,HLT,Potential), winners(Suit, Winners), val(Potential, No_of_Tricks), N1 + N2 >= No_of_Tricks - Winners - Actions, !. /* 9 reg finesse 2st Seat - else if led low play low */ ftactic_card(finesse(_, Suit,_), _, _, [_], DecSuit, _, _, card(Suit,LCard)) :- append(_,[LCard],DecSuit). /* 10 reg finesse 3rd Seat - play high if defender does not follow */ ftactic_card(finesse(_, Suit,Player), _, Player, [card(Suit1,_),_], [Card1|_], _, _, card(Suit,Card1)) :- Suit1 \== Suit, !, Tactic =.. [Suit, finesse], ( clause(failed(Tactic),_) ; assert(failed(Tactic)) ). /* 11 reg finesse 3rd Seat - play hnw if finesse card in this hand and defender follows low */ ftactic_card(finesse(_,Suit,Player), _, Player, [_, card(Suit,Card)], DecSuit, _, [Highest|DefSuit], card(Suit,HNW1)) :- highest_non_winner(DecSuit,Highest,HNW1), number_higher([HNW1],[Highest|DefSuit], N1), number_higher([Card],[Highest|DefSuit], N2), N1 < N2. /* 12 else partner has played hnw and defender has followed low so play low*/ ftactic_card(finesse(_,Suit,Player), _, Player, [_,_], DecSuit, _, _, card(Suit,Card)) :- append(_, [Card], DecSuit). /*reverse finesse 4rd Seat - partner won so duck */ rtactic_card(finesse(_,Suit,_), _, _, [C1,C2,C3], DecSuit, _, _, card(Suit,Card)) :- higher(Suit, C2, C1), higher(Suit,C2, C3), append(_, [Card], DecSuit). /*reverse finesse 4rd Seat - partner won so win cheapest */ rtactic_card(finesse(_,Suit,_), _, _, [C1,_,C3], DecSuit, _, _, card(Suit,Card)) :- defenders_highest(Suit, C1, C3, C), win_cheaply(DecSuit,C,Card). /*reverse finesse to partner's hand - duck */ rtactic_card(finesse(_, Suit, Player), _, Partner, _, DecSuit1, _, _, card(Suit,Card)) :- partner(Player,Partner), !, append(_,Card,DecSuit1). /*reverse finesse - duck if defender plays high */ rtactic_card(finesse(_,Suit,Player), _, Player, [suit(Suit,Highest)|_], DecSuit, _, [Highest|_], card(Suit,Card)) :- !, append(_,[Card],DecSuit). rtactic_card(finesse(_,Suit,Player), _, Player, [_,_,suit(Suit,Highest)|_], DecSuit, _, [Highest|_], card(Suit,Card)) :- !, append(_,[Card],DecSuit). /*reverse finesse 2nd, 3rd - play high */ rtactic_card(finesse(_,Suit,Player), _, Player, _, [Card1|_], _, _, card(Suit,Card1)) :- !. highest_non_winner([C1|_], C2, C1) :- C1 < C2, !. highest_non_winner([_|Cs], C2, C3) :- highest_non_winner(Cs, C2, C3). higher(Suit, card(Suit, Card1), card(Suit, Card2)) :- Card1 < Card2, !, fail. higher(Suit,card(Suit,_), card(_,_)). defenders_highest(Suit, card(Suit,C1),card(Suit,C2), C1) :- C1 > C2, !. defenders_highest(Suit, card(Suit,_),card(Suit,C2), C2) :- !. defenders_highest(Suit, card(Suit,C1),_, C1) :- !. defenders_highest(Suit, _, card(Suit,C2), C2) :- !. defenders_highest(_, _, _, 0). defenders_highest([H|_], H). defenders_highest([], 0). win_cheaply([Card1], _, Card1) :- !. win_cheaply([Card1,Card2|_],C,Card1) :- Card1 > C, Card2 < C, !. win_cheaply([_,Card2|Cards], C, Card) :- win_cheaply([Card2|Cards], C, Card). %defender_card(Hand,Player,LeadSuit,contract(_,_,Dec),Card) defender_card(Hand, Player, _, contract(_,_,Dec), card(Suit,Card)) :- ( Player = Dec ; partner(Player,Dec) ), plan((_,Plan),_), member(HLT,Plan), functor(HLT,Suit,_), get_suit(Hand, Suit, Cards), length(Cards,L), L > 0, arg(3,HLT,N), number_of_actions(_,1,Suit,N1), L > N + N1, !, append(_,[Card],Cards). defender_card(Hand, _, LeadSuit, _, card(LeadSuit,Card)) :- nonvar(LeadSuit), get_suit(Hand, LeadSuit,[Card]), !. defender_card(Hand,Player,LeadSuit,_,card(SuitName,Value)) :- repeat, format("Choose card from ~p's hand: ",[Player]), read_line(Cs), pick_suit(Cs,LeadSuit,SuitName), pick_card(Cs,Value), in_hand(Hand,Player,SuitName,Value), follow_suit(Hand,SuitName,Value,LeadSuit), !. defender_card(Hand,Player,LeadSuit,Contract,card(SuitName,Value)) :- format("Illegal Card ~n",[]), defender_card(Hand,Player,LeadSuit,Contract,card(SuitName,Value)). check_suits(contract(_,_,Dec), Suit, Hand, Side, Winner, [Learnt|Learned]) :- assert(known(Learnt)), format("Leart ~p~n",[Learnt]), getdeflen(Hand, Dec, Suit, L), Clause =.. [Suit, pos], not(clause(failed(Clause),_)), ( L >= 1, %format("Failed ~p~n",[Clause]), assert(failed(Clause)) ; true ), ( L >= 2, Clause1 =.. [Suit,usual], %format("Failed ~p~n",[Clause1]), assert(failed(Clause1)) ; true ), !, check_suits(contract(_,_,Dec),Suit, Hand, Side, Winner, Learned). check_suits(_, _, _, _, _, _) :- !. check_plan(_, _, defender, _, Action) :- ( Action = dbl1_fin_dec ; Action = dbl1_fin_dum ), !. check_plan(_, Suit, defender, _, Action) :- finesseable(Action), plan(_, Reqs), Req =.. [Suit, finesse], member(Req, Reqs), %assert(failed(Req)), format("Current plan has failed~n",[]), !, fail. check_plan(contract(_,_,Dec), Suit, declarer, _, Action) :- finesseable(Action), plan((_,Plan), Reqs), Req =.. [Suit, finesse], member(Req, Reqs), member(Tactic,Plan), functor(Tactic, Suit, _), arg(1,Tactic, HLT), name(HLT, Name), append(_,[P, L, R], Name), name(Player, [P, L, R]), ( Player = dec, next_play(Next, Dec) ; Player = dum, next_play(Dec, Next) ), Known =.. [Suit, void, Next], clause(known(Known),_), format("Current plan has failed~n",[]), !, fail. check_plan(_, _, _, _, _) :- plan(_, Reqs), member(Req, Reqs), clause(failed(Req),_), format("Current plan has failed~n",[]), !, fail. check_plan(_, _, _, _, _). getdeflen(hand(_,_,Hand1,Hand2),Dec,Suit,L) :- ( Dec = north ; Dec = south ), !, get_suit(Hand1,Suit,Cards1), get_suit(Hand2,Suit,Cards2), length(Cards1,L1), length(Cards2,L2), L is L1 + L2. getdeflen(hand(Hand1,Hand2,_,_), _,Suit,L) :- get_suit(Hand1,Suit,Cards1), get_suit(Hand2,Suit,Cards2), length(Cards1,L1), length(Cards2,L2), L is L1 + L2. hi_lvl_tactic([HLT|_], Suit, HLT) :- functor(HLT, Suit, _), !. hi_lvl_tactic([_|HLTs], Suit, HLT) :- hi_lvl_tactic(HLTs, Suit, HLT). number_of_actions(Action, Win, Suit, N) :- bagof(action(Action, Win, Suit, P), action(Action, Win, Suit, P), Actions), !, length(Actions, N). number_of_actions(_, _, _, 0). assert_action(declarer, Winner) :- retract(action(Tactic, 0, Suit, _)), !, asserta(action(Tactic, 1, Suit, Winner)). assert_action(defender, Winner) :- retract(action(Tactic, 0, Suit, _)), !, asserta(action(Tactic, -1, Suit, Winner)). %change_llp(Plan1, _Leader, WinSuit, Winner, Update, NPlan). change_llp(Plan, _Leader, _, _, [], Plan) :- !. change_llp([], _, _, _, _, []) :- !. change_llp([Tactic|Tactics], _, Suit, _, [Old/New], [NTactic|NTactics]) :- arg(2, Tactic, Suit), functor(Tactic, Old, _), !, functor(NTactic, New, 3), arg(1,NTactic,1), arg(2,NTactic,Suit), arg(3,NTactic,anyone), change_llp(Tactics, _, Suit, _, [Old/New], NTactics). change_llp([Tactic|Tactics], _, Suit, _, Update,[Tactic|NTactics]) :- change_llp(Tactics, _, Suit, _, Update, NTactics). update_llp(LLP, _, _, _, [], _, LLP) :- !. update_llp(LLP, Hand, Suit, Analysis, [New], contract(_,_,Declarer),NLLP) :- partner(Declarer, Dummy), next_play(Declarer, Defender1), next_play(Dummy, Defender2), get_hand(Hand, Declarer, Dec), get_hand(Hand, Dummy, Dum), get_hand(Hand, Defender1, Def1), get_hand(Hand, Defender2, Def2), member(Tactic,Analysis), functor(Tactic,New,_), arg(1,Tactic,Winners), Tactic1 =.. [Suit, New, cert, Winners], decompose_plan([Tactic1], Declarer, Dec, Dum, Def1, Def2, [Lo_Lvl]), update_suit_llp(LLP, Lo_Lvl, LLP1), splice_plan(LLP1, NLLP). /* t(P) :- update_suit_llp( [[cash(1,diamonds,north), cash(1,diamonds,south)], [cash(1,hearts,north)], [cash(1,spades,north)], [cash(1,hearts,south)]], [cash(1,hearts,both),cash(1,hearts,noone)],P). */ update_suit_llp([], _, []). update_suit_llp([Act|Acts], Lo_Lvl, [NAct|NActs]) :- update_a_suit(Act, Lo_Lvl, NAct, Rest), update_suit_llp(Acts, Rest, NActs). update_a_suit([], Rest, [], Rest). update_a_suit([Act|Acts], [NAct|NActs], [NAct|NActs1], Rest) :- arg(2, Act, Suit), arg(2, NAct, Suit), !, update_a_suit(Acts, NActs, NActs1, Rest). update_a_suit([Act|Acts], NActs, [Act|NActs1], Rest) :- update_a_suit(Acts, NActs, NActs1, Rest). update_hlp(Suit,[New]) :- !, plan((Prob,Plan),Reqs), change_hlp(Plan, Suit, New, NPlan), format("Old High Level Plan ~p~n",[Plan]), retract_it(plan(_,_)), format("New High Level Plan ~p~n",[NPlan]), assert(plan((Prob, NPlan), Reqs)), update_actions(Suit). update_hlp(_, _). change_hlp([HLT|HLTs], Suit, New, [HLT1|HLTs]) :- functor(HLT, Suit, _), !, number_of_actions(_, 1, Suit, W), number_of_actions(_, -1, Suit, L), arg(2, HLT, Prob), arg(3, HLT, N1), val(N1,Val), N2 is Val - W - L, HLT1 =.. [Suit, New, Prob, N2]. change_hlp([HLT|HLTs], Suit, New, [HLT|HLTs1]) :- change_hlp(HLTs, Suit, New, HLTs1) . number_between([Card|Cards], H1, H2, N) :- Card > H1, !, number_between(Cards, H1, H2, N). number_between([Card|Cards], H1, H2, N) :- Card < H1, Card > H2, !, number_between(Cards, H1, H2, N1), N is N1 + 1. number_between(_, _, _, 0).