deck.go 5.8 KB

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