guandan.dev

guandan.dev

https://git.tonybtw.com/guandan.dev.git git://git.tonybtw.com/guandan.dev.git
3,669 bytes raw
1
package game
2
3
type Game_Phase int
4
5
const (
6
	Phase_Waiting Game_Phase = iota
7
	Phase_Deal
8
	Phase_Play
9
	Phase_Tribute
10
	Phase_End
11
)
12
13
type Tribute_Info struct {
14
	From_Seat int
15
	To_Seat   int
16
	Done      bool
17
}
18
19
type Game_State struct {
20
	Phase          Game_Phase
21
	Level          Rank
22
	Team_Levels    [2]int
23
	Hands          [4][]Card
24
	Current_Turn   int
25
	Current_Lead   Combination
26
	Lead_Player    int
27
	Pass_Count     int
28
	Finish_Order   []int
29
	Tributes       []Tribute_Info
30
	Tribute_Leader int
31
}
32
33
func New_Game_State() *Game_State {
34
	return &Game_State{
35
		Phase:        Phase_Waiting,
36
		Level:        Rank_Two,
37
		Team_Levels:  [2]int{0, 0},
38
		Finish_Order: make([]int, 0, 4),
39
	}
40
}
41
42
func (g *Game_State) Get_Cards_By_Id(seat int, ids []int) []Card {
43
	id_set := make(map[int]bool)
44
	for _, id := range ids {
45
		id_set[id] = true
46
	}
47
48
	var cards []Card
49
	for _, card := range g.Hands[seat] {
50
		if id_set[card.Id] {
51
			cards = append(cards, card)
52
			delete(id_set, card.Id)
53
		}
54
	}
55
56
	if len(id_set) > 0 {
57
		return nil
58
	}
59
60
	return cards
61
}
62
63
func (g *Game_State) Get_Card_By_Id(seat int, id int) *Card {
64
	for i := range g.Hands[seat] {
65
		if g.Hands[seat][i].Id == id {
66
			return &g.Hands[seat][i]
67
		}
68
	}
69
	return nil
70
}
71
72
func (g *Game_State) Remove_Cards(seat int, ids []int) {
73
	id_set := make(map[int]bool)
74
	for _, id := range ids {
75
		id_set[id] = true
76
	}
77
78
	var remaining []Card
79
	for _, card := range g.Hands[seat] {
80
		if !id_set[card.Id] {
81
			remaining = append(remaining, card)
82
		}
83
	}
84
	g.Hands[seat] = remaining
85
}
86
87
func (g *Game_State) Setup_Tributes() {
88
	g.Tributes = nil
89
90
	if len(g.Finish_Order) < 2 {
91
		return
92
	}
93
94
	first := g.Finish_Order[0]
95
	winning_team := first % 2
96
97
	var last_loser int = -1
98
	var second_last_loser int = -1
99
100
	for i := 3; i >= 0; i-- {
101
		seat := -1
102
		if i < len(g.Finish_Order) {
103
			seat = g.Finish_Order[i]
104
		} else {
105
			for s := 0; s < 4; s++ {
106
				found := false
107
				for _, f := range g.Finish_Order {
108
					if f == s {
109
						found = true
110
						break
111
					}
112
				}
113
				if !found {
114
					seat = s
115
					break
116
				}
117
			}
118
		}
119
120
		if seat%2 != winning_team {
121
			if last_loser == -1 {
122
				last_loser = seat
123
			} else if second_last_loser == -1 {
124
				second_last_loser = seat
125
				break
126
			}
127
		}
128
	}
129
130
	first_winner := g.Finish_Order[0]
131
	var second_winner int = -1
132
	for _, seat := range g.Finish_Order {
133
		if seat%2 == winning_team && seat != first_winner {
134
			second_winner = seat
135
			break
136
		}
137
	}
138
139
	if last_loser != -1 {
140
		g.Tributes = append(g.Tributes, Tribute_Info{
141
			From_Seat: last_loser,
142
			To_Seat:   first_winner,
143
		})
144
	}
145
146
	if g.is_double_win() && second_last_loser != -1 && second_winner != -1 {
147
		g.Tributes = append(g.Tributes, Tribute_Info{
148
			From_Seat: second_last_loser,
149
			To_Seat:   second_winner,
150
		})
151
	}
152
153
	g.Tribute_Leader = first_winner
154
}
155
156
func (g *Game_State) is_double_win() bool {
157
	if len(g.Finish_Order) < 2 {
158
		return false
159
	}
160
	return g.Finish_Order[0]%2 == g.Finish_Order[1]%2
161
}
162
163
func (g *Game_State) Get_Tribute_Info(seat int) *Tribute_Info {
164
	for i := range g.Tributes {
165
		if g.Tributes[i].From_Seat == seat && !g.Tributes[i].Done {
166
			return &g.Tributes[i]
167
		}
168
	}
169
	return nil
170
}
171
172
func (g *Game_State) Mark_Tribute_Done(seat int) {
173
	for i := range g.Tributes {
174
		if g.Tributes[i].From_Seat == seat {
175
			g.Tributes[i].Done = true
176
			break
177
		}
178
	}
179
}
180
181
func (g *Game_State) All_Tributes_Done() bool {
182
	for _, t := range g.Tributes {
183
		if !t.Done {
184
			return false
185
		}
186
	}
187
	return true
188
}
189
190
func (g *Game_State) Reset_Hand() {
191
	g.Current_Lead = Combination{Type: Comb_Invalid}
192
	g.Lead_Player = 0
193
	g.Pass_Count = 0
194
	g.Finish_Order = g.Finish_Order[:0]
195
	g.Tributes = nil
196
197
	winning_team := g.Tribute_Leader % 2
198
	g.Level = Rank(g.Team_Levels[winning_team])
199
}