浏览代码

ft: 调整

master
SisMaker 1 个月前
父节点
当前提交
da7dde52e3
共有 1 个文件被更改,包括 148 次插入60 次删除
  1. +148
    -60
      src/ai_core.erl

+ 148
- 60
src/ai_core.erl 查看文件

@ -263,7 +263,19 @@ generate_leading_plays(Cards) ->
%%
generate_following_plays(Cards, {Type, Value, _} = LastPlay) ->
ValidPlays = find_greater_plays(Cards, Type, Value),
Components = analyze_components(Cards),
ValidPlays = case Type of
?CARD_TYPE_SINGLE -> find_greater_singles(Components, Value);
?CARD_TYPE_PAIR -> find_greater_pairs(Components, Value);
?CARD_TYPE_THREE -> find_greater_triples(Components, Value);
?CARD_TYPE_THREE_ONE -> find_greater_three_one(Components, Value);
?CARD_TYPE_THREE_TWO -> find_greater_three_two(Components, Value);
?CARD_TYPE_STRAIGHT -> find_greater_straight(Components, Value);
?CARD_TYPE_STRAIGHT_PAIR -> find_greater_straight_pair(Components, Value);
?CARD_TYPE_PLANE -> find_greater_plane(Components, Value);
?CARD_TYPE_BOMB -> find_greater_bomb(Components, Value);
_ -> []
end,
BombPlays = find_bomb_plays(Cards),
RocketPlay = find_rocket_play(Cards),
@ -440,6 +452,120 @@ generate_three_two(Triples, Pairs) ->
{PairValue, PairCards} <- Pairs,
PairValue =/= TripleValue].
%%
score_play_potential(Play, LastPlay) ->
{Type, Value, Cards} = Play,
BaseScore = case Type of
?CARD_TYPE_ROCKET -> 1.0;
?CARD_TYPE_BOMB -> 0.9;
?CARD_TYPE_STRAIGHT -> 0.8;
?CARD_TYPE_STRAIGHT_PAIR -> 0.75;
?CARD_TYPE_PLANE -> 0.7;
?CARD_TYPE_THREE_TWO -> 0.6;
?CARD_TYPE_THREE_ONE -> 0.5;
?CARD_TYPE_THREE -> 0.4;
?CARD_TYPE_PAIR -> 0.3;
?CARD_TYPE_SINGLE -> 0.2
end,
%
ValueFactor = Value / ?CARD_VALUE_BIG_JOKER,
%
CountFactor = length(Cards) / 10,
%
BaseScore * (1 + ValueFactor) * (1 + CountFactor).
%%
%%
group_cards_by_value(Cards) ->
lists:foldl(fun(Card, Acc) ->
{Value, _} = Card,
maps:update_with(Value, fun(List) -> [Card | List] end, [Card], Acc)
end, #{}, Cards).
%%
find_sequences(GroupedCards) ->
Values = lists:sort(maps:keys(GroupedCards)),
find_sequences(Values, GroupedCards, []).
find_sequences([], _, Acc) -> Acc;
find_sequences([V | Rest], GroupedCards, Acc) ->
case find_sequence_starting_at(V, Rest, GroupedCards) of
{Seq, NewRest} when length(Seq) >= 5 ->
Cards = lists:flatten([maps:get(Value, GroupedCards) || Value <- Seq]),
find_sequences(NewRest, GroupedCards, [{V, Cards} | Acc]);
{_, NewRest} ->
find_sequences(NewRest, GroupedCards, Acc)
end.
find_sequence_starting_at(Start, Rest, _) when Start >= ?CARD_VALUE_2 ->
{[], Rest}; % 2
find_sequence_starting_at(Start, Rest, GroupedCards) ->
find_sequence_starting_at(Start, Rest, GroupedCards, [Start]).
find_sequence_starting_at(_, [], _, Acc) ->
{lists:reverse(Acc), []};
find_sequence_starting_at(Prev, [Next | Rest], GroupedCards, Acc) ->
case Next of
Next when Next =:= Prev + 1, Next < ?CARD_VALUE_2 ->
find_sequence_starting_at(Next, Rest, GroupedCards, [Next | Acc]);
_ ->
{lists:reverse(Acc), [Next | Rest]}
end.
%%
filter_candidates(Plays, Context) ->
%
%
case Context#play_context.game_stage of
end_game when Context#play_context.cards_remaining =< 4 ->
%
[Play || Play = {_, _, Cards} <- Plays, length(Cards) =:= Context#play_context.cards_remaining];
_ ->
Plays
end.
%%
get_last_play(GameState) ->
%
%
maps:get(last_play, GameState, none).
%%
count_greater_cards(Cards, LastPlay) ->
case LastPlay of
none -> length(Cards);
{Type, Value, _} ->
Components = analyze_components(Cards),
length(find_greater_plays(Cards, Type, Value))
end.
%%
evaluate_position(AIState) ->
%
%
case AIState#ai_state.role of
dizhu -> 0.7;
nongmin -> 0.5
end.
%%
evaluate_control(AIState) ->
%
%
ControlCards = count_control_cards(AIState#ai_state.hand_cards),
TotalCards = length(AIState#ai_state.hand_cards),
ControlCards / max(1, TotalCards).
%%
count_total_remaining_cards(GameState) ->
%
%
maps:get(total_remaining, GameState, 54).
%%
find_greater_plays(Cards, Type, MinValue) ->
Components = analyze_components(Cards),
@ -591,69 +717,31 @@ find_consecutive_triple_sequence(Value, _, [{NextValue, NextCards} | Rest], Acc)
find_consecutive_triple_sequence(_, _, Rest, Acc) ->
{lists:flatten(lists:reverse(Acc)), Rest}.
%%
calculate_early_tempo({Type, Value, _}, _Context) ->
%%
calculate_early_tempo(Play, Context) ->
{Type, _, Cards} = Play,
case Type of
?CARD_TYPE_SINGLE when Value < ?CARD_VALUE_2 -> 0.8;
?CARD_TYPE_PAIR when Value < ?CARD_VALUE_2 -> 0.7;
?CARD_TYPE_STRAIGHT -> 0.9;
?CARD_TYPE_STRAIGHT_PAIR -> 0.85;
_ -> 0.5
end.
calculate_mid_tempo({Type, Value, _}, _Context) ->
case Type of
?CARD_TYPE_THREE_ONE -> 0.8;
?CARD_TYPE_THREE_TWO -> 0.85;
?CARD_TYPE_PLANE -> 0.9;
?CARD_TYPE_BOMB -> 0.7;
?CARD_TYPE_SINGLE when Context#play_context.cards_remaining > 10 -> 0.3;
?CARD_TYPE_PAIR when Context#play_context.cards_remaining > 10 -> 0.5;
?CARD_TYPE_STRAIGHT -> 0.8;
_ -> 0.6
end.
calculate_end_tempo({Type, Value, _}, Context) ->
CardsLeft = Context#play_context.cards_remaining,
%%
calculate_mid_tempo(Play, Context) ->
{Type, _, Cards} = Play,
case Type of
?CARD_TYPE_BOMB -> 0.9;
?CARD_TYPE_ROCKET -> 1.0;
_ when CardsLeft =< 4 -> 0.95;
_ -> 0.7
end.
%%
filter_candidates(Plays, Context) ->
case Context#play_context.game_stage of
early_game ->
filter_early_game_plays(Plays, Context);
mid_game ->
filter_mid_game_plays(Plays, Context);
end_game ->
filter_end_game_plays(Plays, Context)
end.
filter_early_game_plays(Plays, _Context) ->
%
[Play || {Type, Value, _} = Play <- Plays,
Type =/= ?CARD_TYPE_BOMB orelse Value >= ?CARD_VALUE_2].
filter_mid_game_plays(Plays, Context) ->
% 使
case Context#play_context.control_factor < 0.5 of
true -> Plays;
false ->
[Play || {Type, _, _} = Play <- Plays,
Type =/= ?CARD_TYPE_BOMB]
?CARD_TYPE_SINGLE when Context#play_context.cards_remaining > 5 -> 0.4;
?CARD_TYPE_PAIR when Context#play_context.cards_remaining > 5 -> 0.6;
?CARD_TYPE_STRAIGHT -> 0.7;
_ -> 0.5
end.
filter_end_game_plays(Plays, _Context) ->
% 使
Plays.
%%
group_cards_by_value(Cards) ->
lists:foldl(fun(Card, Acc) ->
{Value, _} = Card,
maps:update_with(Value,
fun(List) -> [Card|List] end,
[Card],
Acc)
end, maps:new(), Cards).
%%
calculate_end_tempo(Play, Context) ->
{_, _, Cards} = Play,
case length(Cards) of
L when L =:= Context#play_context.cards_remaining -> 1.0;
L when L > Context#play_context.cards_remaining / 2 -> 0.8;
_ -> 0.6
end.

正在加载...
取消
保存