deck.go 5.4 KB

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