deck.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. package main
  2. import (
  3. "red-green/door"
  4. "strings"
  5. )
  6. type Deck struct {
  7. Cards []door.Panel
  8. Backs []door.Panel
  9. Mark []door.Panel
  10. }
  11. func (d *Deck) SetBackColor(color string) {
  12. for x := 0; x < 5; x++ {
  13. for idx := range d.Backs[x].Lines {
  14. d.Backs[x].Lines[idx].DefaultColor = color
  15. }
  16. }
  17. }
  18. func (d *Deck) Init() {
  19. d.Cards = make([]door.Panel, 52)
  20. for x := 0; x < 52; x++ {
  21. d.Cards[x] = CardOf(x)
  22. }
  23. d.Backs = make([]door.Panel, 5)
  24. for x := 0; x < 5; x++ {
  25. d.Backs[0] = BackOf(x)
  26. }
  27. d.Mark = make([]door.Panel, 2)
  28. d.Mark[0] = MarkOf(0)
  29. d.Mark[1] = MarkOf(1)
  30. }
  31. func CardOf(c int) door.Panel {
  32. suit := GetSuit(c)
  33. rank := GetRank(c)
  34. var is_red bool = suit < 2
  35. var color string
  36. if is_red {
  37. color = door.ColorText("RED ON WHITE")
  38. } else {
  39. color = door.ColorText("BLACK ON WHITE")
  40. }
  41. p := door.Panel{
  42. X: 0,
  43. Y: 0,
  44. Width: 5}
  45. r := RankSymbol(rank)
  46. s := SuitSymbol(suit)
  47. p.Lines = append(p.Lines,
  48. door.Line{Text: string(r) + string(s) + " ",
  49. DefaultColor: color})
  50. p.Lines = append(p.Lines,
  51. door.Line{Text: " " + string(s) + " ",
  52. DefaultColor: color})
  53. p.Lines = append(p.Lines,
  54. door.Line{Text: " " + string(s) + string(r),
  55. DefaultColor: color})
  56. return p
  57. }
  58. func BackOf(level int) door.Panel {
  59. p := door.Panel{
  60. X: 0,
  61. Y: 0,
  62. Width: 5,
  63. }
  64. for x := 0; x < 3; x++ {
  65. p.Lines = append(p.Lines,
  66. door.Line{Text: strings.Repeat(string(BackSymbol(level)), 5)})
  67. }
  68. return p
  69. }
  70. func MarkOf(c int) door.Panel {
  71. p := door.Panel{Width: 1}
  72. color := door.ColorText("BLUE ON WHITE")
  73. var m rune
  74. if c == 0 {
  75. m = ' '
  76. } else {
  77. if door.Unicode {
  78. m = '\u25a0'
  79. } else {
  80. m = '\xfe'
  81. }
  82. }
  83. p.Lines = append(p.Lines,
  84. door.Line{Text: string(m),
  85. DefaultColor: color})
  86. return p
  87. }
  88. func RankSymbol(c int) rune {
  89. const symbols = "A23456789TJQK"
  90. return rune(symbols[c])
  91. }
  92. func SuitSymbol(c int) rune {
  93. if door.Unicode {
  94. switch c {
  95. case 0:
  96. return '\u2665'
  97. case 1:
  98. return '\u2666'
  99. case 2:
  100. return '\u2663'
  101. case 3:
  102. return '\u2660'
  103. }
  104. } else {
  105. if door.Full_CP437 {
  106. switch c {
  107. case 0:
  108. return '\x03'
  109. case 1:
  110. return '\x04'
  111. case 2:
  112. return '\x05'
  113. case 3:
  114. return '\x06'
  115. }
  116. } else {
  117. switch c {
  118. case 0:
  119. return '*'
  120. case 1:
  121. return '^'
  122. case 2:
  123. return '%'
  124. case 3:
  125. return '$'
  126. }
  127. }
  128. }
  129. return '?'
  130. }
  131. func BackSymbol(level int) rune {
  132. if level == 0 {
  133. return ' '
  134. }
  135. if door.Unicode {
  136. switch level {
  137. case 1:
  138. return '\u2591'
  139. case 2:
  140. return '\u2592'
  141. case 3:
  142. return '\u2593'
  143. case 4:
  144. return '\u2588'
  145. }
  146. } else {
  147. switch level {
  148. case 1:
  149. return '\xb0'
  150. case 2:
  151. return '\xb1'
  152. case 3:
  153. return '\xb2'
  154. case 4:
  155. return '\xdb'
  156. }
  157. }
  158. return '?'
  159. }
  160. func GetRank(c int) int {
  161. return (c % 52) % 13
  162. }
  163. func GetSuit(c int) int {
  164. return (c % 52) / 13
  165. }
  166. func GetDeck(c int) int {
  167. return c / 52
  168. }
  169. type Pos struct {
  170. X int
  171. Y int
  172. Level int
  173. }
  174. func CalcCardPos(pos int) Pos {
  175. var result Pos
  176. const space = 3
  177. const height = 3
  178. if pos == 28 {
  179. result = CalcCardPos(23)
  180. result.Y += height + 1
  181. result.Level--
  182. return result
  183. } else {
  184. if pos == 29 {
  185. result = CalcCardPos(22)
  186. result.Y += height + 1
  187. result.Level--
  188. return result
  189. }
  190. }
  191. const CARD_WIDTH = 5
  192. var HALF_WIDTH int = 3
  193. HALF_WIDTH += space / 2
  194. const between = CARD_WIDTH + space
  195. if pos < 3 {
  196. result.Level = 1
  197. result.Y = (result.Level-1)*(height-1) + 1
  198. result.X = pos*(between*3) + between + HALF_WIDTH + space
  199. return result
  200. } else {
  201. pos -= 3
  202. }
  203. if pos < 6 {
  204. result.Level = 2
  205. result.Y = (result.Level-1)*(height-1) + 1
  206. group := pos / 2
  207. result.X = pos*between + (group * between) + CARD_WIDTH + space*2
  208. return result
  209. } else {
  210. pos -= 6
  211. }
  212. if pos < 9 {
  213. result.Level = 3
  214. result.Y = (result.Level-1)*(height-1) + 1
  215. result.X = pos*between + HALF_WIDTH + space
  216. return result
  217. } else {
  218. pos -= 9
  219. }
  220. if pos < 10 {
  221. result.Level = 4
  222. result.Y = (result.Level-1)*(height-1) + 1
  223. result.X = pos*between + space
  224. return result
  225. }
  226. // failure
  227. result.Level = -1
  228. result.X = -1
  229. result.Y = -1
  230. return result
  231. }
  232. // 0-29
  233. var CardPos []Pos
  234. var blocks [][]int
  235. func init() {
  236. CardPos = make([]Pos, 30)
  237. for x := 0; x < 30; x++ {
  238. CardPos[x] = CalcCardPos(x)
  239. }
  240. blocks = [][]int{
  241. {3, 4},
  242. {5, 6},
  243. {7, 8}, // end row 1
  244. {9, 10},
  245. {10, 11},
  246. {12, 13},
  247. {13, 14},
  248. {15, 16},
  249. {16, 17},
  250. {18, 19}, // end row 2
  251. {19, 20},
  252. {20, 21},
  253. {21, 22},
  254. {22, 23},
  255. {23, 24},
  256. {24, 25},
  257. {25, 26},
  258. {26, 27},
  259. }
  260. }
  261. // Which card(s) are unblocked by this card?
  262. func Unblocks(card int) []int {
  263. var result []int
  264. for idx := range blocks {
  265. if blocks[idx][0] == card || blocks[idx][1] == card {
  266. result = append(result, idx)
  267. }
  268. }
  269. return result
  270. }
  271. func CanPlay(card1 int, card2 int) bool {
  272. rank1 := GetRank(card1)
  273. rank2 := GetRank(card2)
  274. if (rank1+1)%13 == rank2 {
  275. return true
  276. }
  277. if rank1 == 0 {
  278. rank1 += 13
  279. }
  280. if rank1-1 == rank2 {
  281. return true
  282. }
  283. return false
  284. }