deck.go 5.9 KB

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