planet.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. )
  6. type PlanetType uint8
  7. func (p PlanetType) String() string {
  8. switch p {
  9. case EarthLike:
  10. return "Earth-Like"
  11. case Mountain:
  12. return "Mountain"
  13. case Ocean:
  14. return "Oceanic"
  15. case Volcanic:
  16. return "Volcanic"
  17. case Glacial:
  18. return "Glacial"
  19. default:
  20. return ""
  21. }
  22. }
  23. func (p PlanetType) Symbol() string {
  24. switch p {
  25. case EarthLike:
  26. return "E"
  27. case Mountain:
  28. return "M"
  29. case Ocean:
  30. return "O"
  31. case Volcanic:
  32. return "V"
  33. case Glacial:
  34. return "G"
  35. default:
  36. return ""
  37. }
  38. }
  39. func (p PlanetType) ProductionOre() int {
  40. switch p {
  41. case EarthLike:
  42. return 6
  43. case Mountain:
  44. return 4
  45. case Ocean:
  46. return 8
  47. case Volcanic:
  48. return 3
  49. case Glacial:
  50. return 10
  51. default:
  52. return -1
  53. }
  54. }
  55. func (p PlanetType) ProductionOrg() int {
  56. switch p {
  57. case EarthLike:
  58. return 5
  59. case Mountain:
  60. return 8
  61. case Ocean:
  62. return 3
  63. case Volcanic:
  64. return -1
  65. case Glacial:
  66. return -1
  67. default:
  68. return -1
  69. }
  70. }
  71. func (p PlanetType) ProductionEqu() int {
  72. switch p {
  73. case EarthLike:
  74. return 8
  75. case Mountain:
  76. return 6
  77. case Ocean:
  78. return 7
  79. case Volcanic:
  80. return -1
  81. case Glacial:
  82. return 10
  83. default:
  84. return -1
  85. }
  86. }
  87. func (p PlanetType) ProductionFig() int {
  88. switch p {
  89. case EarthLike:
  90. return 10
  91. case Mountain:
  92. return 7
  93. case Ocean:
  94. return 4
  95. case Volcanic, Glacial:
  96. return 12
  97. default:
  98. return -1
  99. }
  100. }
  101. func (p PlanetType) ProductionShield() int {
  102. switch p {
  103. case EarthLike:
  104. return 25
  105. case Mountain:
  106. return 20
  107. case Ocean:
  108. return 28
  109. case Volcanic:
  110. return 29
  111. case Glacial:
  112. return 30
  113. default:
  114. return -1
  115. }
  116. }
  117. const ( // Production: The Ratio is 1:X where X is the number of population designated (This excludes Fighters and Shields, which are total population)
  118. EarthLike PlanetType = iota // Production: Ore=1:6, Org=1:5, Equ=1:8, Fig=1:10, Shields=1:25
  119. Mountain // Production: Ore=1:4, Org=1:8, Equ=1:6, Fig=1:7, Shields=1:20
  120. Ocean // Production: Ore=1:8, Org=1:3, Equ=1:6, Fig=1:4, Shields=1:28
  121. Volcanic // Production: Ore=1:3, Org=NA, Equ=NA, Fig=1:12, Shields=1:29
  122. Glacial // Production: Ore=1:10, Org=NA, Equ=1:10, Fig=1:12, Shields=1:30
  123. )
  124. type Planet struct {
  125. ID ID
  126. Name string
  127. Owner ID
  128. CorpOwned bool
  129. Type PlanetType
  130. CitadelLvl uint16 // Lvl1 Unlocks Fighter Defense and Bank, Lvl2 Unlocks Planetary Cannon, Lvl3 Unlocks Production for Shields, Lvl4 Unlocks Teleport and TeleportShip, Lvl5 Unlocks Warp
  131. TeleportDist uint64 // Beam the player to another ship
  132. TeleportShipDist uint64 // Beam the player in the current ship
  133. WarpDist uint64 // Move the planet
  134. Credits uint64
  135. Shields uint64
  136. // Planetary Cannon Settings
  137. CannonSector uint8 // Percentage of fuel Ore too consume per shot when a non-corp or hostile ship enters the sector (1 ore to 5 damage)
  138. CannonLanding uint8 // Percentage of fuel Ore too consume per shot when a non-corp or hostile ship attempts to land on the planet (1 ore to 10 damage)
  139. // Planetary Defense (Fighter) Settings
  140. FighterLanding uint8 // Percentage of fighters too attack a non-corp or hostile ship when they attempt to land on the planet (fighter odds 1:2, essentially double damage)
  141. // Inventory
  142. Population uint64 // Population in supposed 1,000s
  143. Ore uint64 // Per Ton
  144. MaxOre uint64
  145. Org uint64
  146. MaxOrg uint64
  147. Equ uint64
  148. MaxEqu uint64
  149. Fighters uint64 // Per Unit
  150. // Production Settings
  151. ProductOre uint64 // Population placed for fuel Ore production (based on planet type)
  152. ProductOrg uint64 // Organics production
  153. ProductEqu uint64 // Equipment production
  154. }
  155. func (p *Planet) Produce() string {
  156. out := ""
  157. if p.Type.ProductionOre() != -1 {
  158. ore := p.ProductOre / uint64(p.Type.ProductionOre())
  159. if p.Ore+ore > p.MaxOre {
  160. over := p.MaxOre - (p.Ore + ore)
  161. out += fmt.Sprintf("Ore Produced: %d (%d over)", ore, over)
  162. p.Ore += ore - over
  163. } else {
  164. out += fmt.Sprintf("Ore Produced: %d", ore)
  165. p.Ore += ore
  166. }
  167. }
  168. if p.Type.ProductionOrg() != -1 {
  169. org := p.ProductOrg / uint64(p.Type.ProductionOrg())
  170. if len(out) != 0 {
  171. out += "\r\n"
  172. }
  173. if p.Org+org > p.MaxOrg {
  174. over := p.MaxOrg - (p.Org + org)
  175. out += fmt.Sprintf("Organics Produced: %d (%d over)", org, over)
  176. p.Org += org - over
  177. } else {
  178. out += fmt.Sprintf("Organics Produced: %d", org)
  179. p.Org += org
  180. }
  181. }
  182. if p.Type.ProductionEqu() != -1 {
  183. equ := p.ProductEqu / uint64(p.Type.ProductionEqu())
  184. if len(out) != 0 {
  185. out += "\r\n"
  186. }
  187. if p.Equ+equ > p.MaxEqu {
  188. over := p.MaxEqu - (p.Equ + equ)
  189. out += fmt.Sprintf("Equipment Produced: %d (%d over)", equ, over)
  190. p.Equ += equ - over
  191. } else {
  192. out += fmt.Sprintf("Equipment Produced: %d", equ)
  193. p.Equ += equ
  194. }
  195. }
  196. if p.Type.ProductionFig() != -1 {
  197. amt := p.Population / uint64(p.Type.ProductionFig())
  198. if len(out) != 0 {
  199. out += "\r\n"
  200. }
  201. out += fmt.Sprintf("Fighters Produced: %d", amt)
  202. p.Fighters += amt
  203. }
  204. if p.Type.ProductionShield() != -1 {
  205. amt := p.Population / uint64(p.Type.ProductionShield())
  206. if len(out) != 0 {
  207. out += "\r\n"
  208. }
  209. out += fmt.Sprintf("Shields Produced: %d", amt)
  210. p.Shields += amt
  211. }
  212. // TODO: Refine Population growth and declines
  213. // Right now it's a 1d20 anything higher than 12 growth, lower than is decline
  214. // Also the amount grown or declined is random of the same base math (out of ever 100 pop, so best to keep your planets at even 100s and nothing will ever happen!?!)
  215. if p.Population >= 100 && rand.Intn(21)+1 >= 12 {
  216. perc := int64(p.Population % 100)
  217. amt := uint64(rand.Int63n(perc + 1))
  218. if amt == 0 {
  219. out += "\r\n"
  220. return out
  221. }
  222. if len(out) != 0 {
  223. out += "\r\n"
  224. }
  225. out += fmt.Sprintf("Population Growth: %d", amt)
  226. p.Population += amt
  227. } else if p.Population >= 100 {
  228. perc := int64(p.Population % 100)
  229. amt := uint64(rand.Int63n(perc + 1))
  230. if amt == 0 {
  231. out += "\r\n"
  232. return out
  233. }
  234. if len(out) != 0 {
  235. out += "\r\n"
  236. }
  237. if p.Population < amt {
  238. amt = p.Population
  239. }
  240. out += fmt.Sprintf("Population Decline: %d", amt)
  241. p.Population -= amt
  242. if p.Population == 0 {
  243. out += "\r\nNo Population!"
  244. }
  245. }
  246. out += "\r\n"
  247. return out
  248. }