|
@@ -9,6 +9,7 @@ import (
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
"time"
|
|
|
+ "unicode"
|
|
|
)
|
|
|
|
|
|
func StringToANSIColor(colorCode string) string {
|
|
@@ -63,6 +64,10 @@ type PlayCards struct {
|
|
|
NextQuitPanel door.Panel
|
|
|
Calendar door.Panel
|
|
|
DeckPanel Deck
|
|
|
+ Deck []DeckType
|
|
|
+ State []DeckType
|
|
|
+ Off_X int
|
|
|
+ Off_Y int
|
|
|
}
|
|
|
|
|
|
// Adjust date to 2:00 AM
|
|
@@ -475,8 +480,8 @@ func int32toByteArray(i int32) (arr [4]byte) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
-func int64toByteArray(i int64) (arr [4]byte) {
|
|
|
- binary.BigEndian.PutUint64(arr[0:4], uint64(i))
|
|
|
+func int64toByteArray(i int64) (arr [8]byte) {
|
|
|
+ binary.BigEndian.PutUint64(arr[0:8], uint64(i))
|
|
|
return
|
|
|
}
|
|
|
|
|
@@ -490,16 +495,18 @@ func (pc *PlayCards) PlayCards() int {
|
|
|
MX := door.Width
|
|
|
MY := door.Height
|
|
|
|
|
|
- off_x := (MX - game_width) / 2
|
|
|
- off_y := (MY - game_height) / 2
|
|
|
- _ = off_x
|
|
|
+ pc.Off_X = (MX - game_width) / 2
|
|
|
+ pc.Off_Y = (MY - game_height) / 2
|
|
|
+ // _ = off_x
|
|
|
|
|
|
// We can now position things properly centered
|
|
|
pc.SpaceAceTriPeaks.X = (MX - pc.SpaceAceTriPeaks.Width) / 2
|
|
|
- pc.SpaceAceTriPeaks.Y = off_y
|
|
|
- off_y += 3
|
|
|
+ pc.SpaceAceTriPeaks.Y = pc.Off_Y
|
|
|
+ pc.Off_Y += 3
|
|
|
|
|
|
currentDefault := pc.DB.GetSetting("DeckColor", "ALL")
|
|
|
+
|
|
|
+Next_Hand:
|
|
|
deck_color := StringToANSIColor(currentDefault)
|
|
|
|
|
|
pc.DeckPanel.SetBackColor(deck_color)
|
|
@@ -522,10 +529,291 @@ func (pc *PlayCards) PlayCards() int {
|
|
|
}
|
|
|
pd := int64toByteArray(pc.Play_day_t)
|
|
|
seed_seq = append(seed_seq, pd[:]...)
|
|
|
+ // We also need the hand # that we're playing.
|
|
|
+ seed_seq = append(seed_seq, byte(pc.Hand))
|
|
|
|
|
|
result := sha1.Sum(seed_seq)
|
|
|
var seed int64 = int64(binary.BigEndian.Uint64(result[0:8]))
|
|
|
pc.RNG.Seed(seed)
|
|
|
+ pc.Deck = ShuffleCards(pc.RNG, 1)
|
|
|
+ pc.State = MakeCardStates(1)
|
|
|
+ }
|
|
|
+
|
|
|
+ // Position the panels
|
|
|
+ {
|
|
|
+ off_yp := pc.Off_Y + 11
|
|
|
+
|
|
|
+ left_panel_x := CardPos[18].X
|
|
|
+ right_panel_x := CardPos[15].X
|
|
|
+ pc.ScorePanel.X = left_panel_x + pc.Off_X
|
|
|
+ pc.ScorePanel.Y = off_yp
|
|
|
+ pc.StreakPanel.X = right_panel_x + pc.Off_X
|
|
|
+ pc.StreakPanel.Y = off_yp
|
|
|
+ pc.CmdPanel.X = left_panel_x + pc.Off_X
|
|
|
+ pc.CmdPanel.Y = off_yp + 5
|
|
|
+
|
|
|
+ next_off_x := (MX - pc.NextQuitPanel.Width) / 2
|
|
|
+ pc.NextQuitPanel.X = next_off_x
|
|
|
+ pc.NextQuitPanel.Y = CardPos[10].Y + pc.Off_Y
|
|
|
+ }
|
|
|
+
|
|
|
+ var Dealing bool = true
|
|
|
+ var r int = 0
|
|
|
+
|
|
|
+ pc.Redraw(Dealing)
|
|
|
+
|
|
|
+ Dealing = false
|
|
|
+ pc.LeftPanel.Update()
|
|
|
+
|
|
|
+ pc.Door.Write(door.Reset)
|
|
|
+
|
|
|
+ var c *door.Panel
|
|
|
+
|
|
|
+ var in_game bool = true
|
|
|
+ var save_streak bool = false
|
|
|
+ var waiting int = 0
|
|
|
+
|
|
|
+ for in_game {
|
|
|
+ var output string
|
|
|
+
|
|
|
+ output = pc.ScorePanel.Update()
|
|
|
+ if output != "" {
|
|
|
+ pc.Door.Write(output)
|
|
|
+ {
|
|
|
+ // Redisplay Mark / Selected Card
|
|
|
+ Pos := &CardPos[pc.Select_card]
|
|
|
+ c = &pc.DeckPanel.Mark[1]
|
|
|
+ c.X = Pos.X + pc.Off_X
|
|
|
+ c.Y = Pos.Y + pc.Off_Y
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if save_streak {
|
|
|
+ save_streak = false
|
|
|
+ pc.DB.SetSetting("best_streak", strconv.Itoa(pc.Best_streak))
|
|
|
+ }
|
|
|
+
|
|
|
+ waiting = 0
|
|
|
+
|
|
|
+ for waiting < int(door.Inactivity) {
|
|
|
+ r = pc.Door.WaitKey(1, 0)
|
|
|
+ if r == -1 {
|
|
|
+ // TIMEOUT is expected here
|
|
|
+ waiting++
|
|
|
+
|
|
|
+ output = pc.ScorePanel.Update()
|
|
|
+ if output != "" {
|
|
|
+ pc.Door.Write(output)
|
|
|
+ {
|
|
|
+ // Redisplay Mark / Selected Card
|
|
|
+ Pos := &CardPos[pc.Select_card]
|
|
|
+ c = &pc.DeckPanel.Mark[1]
|
|
|
+ c.X = Pos.X + pc.Off_X
|
|
|
+ c.Y = Pos.Y + pc.Off_Y
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if r > 0 {
|
|
|
+ // Not a timeout
|
|
|
+ if r < 0x1000 {
|
|
|
+ // not a function key
|
|
|
+ switch unicode.ToUpper(rune(r)) {
|
|
|
+ case '\x0d':
|
|
|
+ // Next Card
|
|
|
+ if pc.Current_streak > pc.Best_streak {
|
|
|
+ pc.Best_streak = pc.Current_streak
|
|
|
+ save_streak = true
|
|
|
+ pc.Door.Write(pc.StreakPanel.Update())
|
|
|
+ }
|
|
|
+
|
|
|
+ if pc.Play_card < 51 {
|
|
|
+ pc.Play_card++
|
|
|
+ pc.Current_streak = 0
|
|
|
+ pc.Door.Write(pc.StreakPanel.Update())
|
|
|
+ pc.Door.Write(pc.LeftPanel.Update())
|
|
|
+
|
|
|
+ // Deal the next card
|
|
|
+
|
|
|
+ if pc.Play_card == 51 {
|
|
|
+ // out of cards
|
|
|
+ cpos := &CardPos[29]
|
|
|
+ c = &pc.DeckPanel.Backs[0]
|
|
|
+ c.X = cpos.X + pc.Off_X
|
|
|
+ c.Y = cpos.Y + pc.Off_Y
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+ }
|
|
|
+
|
|
|
+ cpos := &CardPos[28]
|
|
|
+ c = &pc.DeckPanel.Cards[pc.Deck[pc.Play_card]]
|
|
|
+ c.X = cpos.X + pc.Off_X
|
|
|
+ c.Y = cpos.Y + pc.Off_Y
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+ }
|
|
|
+
|
|
|
+ case 'R':
|
|
|
+ pc.Redraw(false)
|
|
|
+
|
|
|
+ case 'Q':
|
|
|
+ // Possibly prompt here for [N]ext hand or [Q]uit
|
|
|
+ if pc.Current_streak > pc.Best_streak {
|
|
|
+ pc.Best_streak = pc.Current_streak
|
|
|
+ pc.Door.Write(pc.StreakPanel.Update())
|
|
|
+ }
|
|
|
+
|
|
|
+ pc.NextQuitPanel.Update()
|
|
|
+ pc.Door.Write(pc.NextQuitPanel.Output())
|
|
|
+
|
|
|
+ if pc.State[26] == 2 {
|
|
|
+ pc.Door.Write(door.ColorText("BLACK"))
|
|
|
+ } else {
|
|
|
+ pc.Door.Write(door.Reset)
|
|
|
+ }
|
|
|
+ if pc.Hand < pc.Total_hands {
|
|
|
+ r = pc.Door.GetOneOf("CNQ")
|
|
|
+ } else {
|
|
|
+ r = pc.Door.GetOneOf("CDQ")
|
|
|
+ }
|
|
|
+
|
|
|
+ if r == 'C' {
|
|
|
+ // Continue
|
|
|
+ pc.Redraw(false)
|
|
|
+ } else {
|
|
|
+ if r == 'D' || r == 'Q' {
|
|
|
+ if pc.Score >= 50 {
|
|
|
+ // pc.DB.SaveScore(now, pc.Time_T, .. pc.Score)
|
|
|
+ _ = pc.Score
|
|
|
+ }
|
|
|
+
|
|
|
+ in_game = false
|
|
|
+ } else {
|
|
|
+ if r == 'N' {
|
|
|
+ // pc.DB.SaveScore(...)
|
|
|
+ _ = pc.Score
|
|
|
+ pc.Hand++
|
|
|
+ goto Next_Hand
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
return 0
|
|
|
}
|
|
|
+
|
|
|
+func (pc *PlayCards) Redraw(Dealing bool) {
|
|
|
+ // stars.display()
|
|
|
+ pc.Door.Write(door.Clrscr + door.Reset)
|
|
|
+ pc.Door.Write(pc.SpaceAceTriPeaks.Output())
|
|
|
+
|
|
|
+ var c *door.Panel
|
|
|
+
|
|
|
+ {
|
|
|
+ // Step 1: Draw the deck "source"
|
|
|
+ pos := CardPos[29]
|
|
|
+
|
|
|
+ if pc.Play_card == 51 {
|
|
|
+ // out of cards
|
|
|
+ pos.Level = 0
|
|
|
+ }
|
|
|
+
|
|
|
+ c = &pc.DeckPanel.Backs[pos.Level]
|
|
|
+ c.X = pos.X + pc.Off_X
|
|
|
+ c.Y = pos.Y + pc.Off_Y
|
|
|
+
|
|
|
+ pc.LeftPanel.X = pos.X + pc.Off_X
|
|
|
+ pc.LeftPanel.Y = pos.Y + pc.Off_Y + 3 // const height see deck
|
|
|
+
|
|
|
+ pc.ScorePanel.Update()
|
|
|
+ pc.LeftPanel.Update()
|
|
|
+ pc.StreakPanel.Update()
|
|
|
+ pc.CmdPanel.Update()
|
|
|
+
|
|
|
+ pc.Door.Write(pc.ScorePanel.Output())
|
|
|
+ pc.Door.Write(pc.LeftPanel.Output())
|
|
|
+ pc.Door.Write(pc.StreakPanel.Output())
|
|
|
+ pc.Door.Write(pc.CmdPanel.Output())
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+
|
|
|
+ if Dealing {
|
|
|
+ time.Sleep(time.Second)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var x_max int = 29
|
|
|
+ if Dealing {
|
|
|
+ x_max = 28
|
|
|
+ }
|
|
|
+
|
|
|
+ for x := 0; x < x_max; x++ {
|
|
|
+ pos := CardPos[x]
|
|
|
+ if Dealing {
|
|
|
+ time.Sleep(time.Duration(75) * time.Millisecond)
|
|
|
+ }
|
|
|
+
|
|
|
+ if Dealing {
|
|
|
+ c = &pc.DeckPanel.Backs[pos.Level]
|
|
|
+ c.X = pos.X + pc.Off_X
|
|
|
+ c.Y = pos.Y + pc.Off_Y
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+ } else {
|
|
|
+ switch pc.State[x] {
|
|
|
+ case 0:
|
|
|
+ c = &pc.DeckPanel.Backs[pos.Level]
|
|
|
+ c.X = pos.X + pc.Off_X
|
|
|
+ c.Y = pos.Y + pc.Off_Y
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+ case 1:
|
|
|
+ if x == 28 {
|
|
|
+ c = &pc.DeckPanel.Cards[pc.Deck[pc.Play_card]]
|
|
|
+ } else {
|
|
|
+ c = &pc.DeckPanel.Cards[pc.Deck[x]]
|
|
|
+ }
|
|
|
+ c.X = pos.X + pc.Off_X
|
|
|
+ c.Y = pos.Y + pc.Off_Y
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+ case 2:
|
|
|
+ // no card to draw.
|
|
|
+ case 3:
|
|
|
+ // peak cleared, draw bonus
|
|
|
+ var output string = door.Goto(pos.X+pc.Off_X, pos.Y+pc.Off_Y)
|
|
|
+ output += Bonus()
|
|
|
+ pc.Door.Write(output)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if Dealing {
|
|
|
+ for x := 18; x < 29; x++ {
|
|
|
+ pc.State[x] = 1
|
|
|
+ // CardPos[x] X Y Level
|
|
|
+ Pos := &CardPos[x]
|
|
|
+ time.Sleep(time.Duration(200) * time.Millisecond)
|
|
|
+
|
|
|
+ c = &pc.DeckPanel.Cards[pc.Deck[x]]
|
|
|
+ c.X = Pos.X + pc.Off_X
|
|
|
+ c.Y = Pos.Y + pc.Off_Y
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ {
|
|
|
+ Pos := &CardPos[pc.Select_card]
|
|
|
+ c = &pc.DeckPanel.Mark[1]
|
|
|
+ c.X = Pos.X + pc.Off_X
|
|
|
+ c.Y = Pos.Y + pc.Off_Y
|
|
|
+ pc.Door.Write(c.Output())
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func Bonus() string {
|
|
|
+ return door.ColorText("BOLD YELLOW") + "BONUS"
|
|
|
+}
|