Advertisement
antonsavov

Untitled

Mar 6th, 2017
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 61.77 KB | None | 0 0
  1. local VERSION = '0.8.6 - updated rewards and goals'
  2. os.loadAPI('tracker')
  3. os.loadAPI('json')
  4.  
  5. print("Starting 20.000 Blocks")
  6.  
  7. DEBUG_MODE = false
  8. local monitor = peripheral.wrap("right")
  9. local ox,oy,oz = commands.getBlockPosition()
  10.  
  11. CITY_VERSION = 1 -- this denotes which iteration of the map is current. When the map is full, i.e. all buildzones have been played we replace it with an empty one and increase the city vesrion with 1
  12. SPAWN_VILLAGER = false
  13. DO_GRID = true
  14. GRID_HOLE_CHANCE = 0
  15. NUMBER_OF_BUILDZONES = 6
  16. NUMBER_OF_VOCAB = 10
  17. GAME_LENGTH = 600
  18. VOCAB_WIDTH = 27
  19. VOCAB_HEIGHT = 19
  20. BUILDZONE_WIDTH = 62 -- the actual zone width is 63 blocks, but for some reason due to how minecraft handles relative coordinates this has to be 62
  21. BUILDZONE_FLOOR_HEIGHT = -1
  22. HOMECOMER_TYPE = "Pig"
  23. HOMECOMER_VALUE = 90 --90 is for pig
  24. SPAWN = {
  25. x=12110,
  26. y=57,
  27. z=-1777,
  28. a1=90,
  29. a2=0
  30. }
  31. FIRSTZONE= {
  32. x=11685,
  33. y=57,
  34. z=-1869
  35. }
  36. WAITZONE = {
  37. x=12093,
  38. y=56,
  39. z=-1779,
  40. w=5,
  41. l=5
  42. }
  43. --this is the block at ~-4 ~ ~-4 from the corner of the shape zone
  44. --i.e., (the one with the grammar shape in it) of the vocab that is closest to zero
  45. FIRSTVOCAB= {
  46. x=0,
  47. y=57,
  48. z=5
  49. }
  50. VICTORY_HEIGHT = 30
  51. VICTORY_TOTAL = 50
  52. VICTORY_SPECIFIC = {name='garden',count=101}
  53.  
  54.  
  55. WOOL_PER_EMERALD = 64
  56. PICKAXE_USES = 40
  57.  
  58. BLOCKS = {
  59. CAMP_FLOOR = {block='minecraft:sandstone',data=0},
  60. CONSTRUCTION = {block='minecraft:diamond_ore',data=0},
  61. RING = {block='minecraft:diamond_ore',data=0},
  62. DETECT = {block='minecraft:red_sandstone',data=0},
  63. DETECT_DEAD = {block='minecraft:obsidian',data=0},
  64. VOCAB_DETECT = {block="minecraft:quartz_block",data=0},
  65. VOCAB_REPLACE = {block="minecraft:coal_block",data=0},
  66. VICTORY_MARKER = {block="minecraft:emerald_block",data=0},
  67. PLUG = {block="minecraft:lapis_ore",data=0},
  68. PHVFLOOR = {block="minecraft:stone_slab",data=3},
  69. BUILDING_HOUSE = {block="minecraft:wool",data=0},
  70. BUILDING_GARDEN = {block="minecraft:wool",data=13},
  71. BUILDING_WATER = {block="minecraft:wool",data=1},
  72. _matWhiteSmooth ={block="mincreaft:stained_hardened_clay",data=0},
  73. _matWhiteSmooth2 = {block="minecraft:brick_block",data=0},
  74. _matYellowSmooth = {block="minecraft:stained_hardened_clay",data=4},
  75. _matPinkSmooth = {block="minecraft:stained_hardened_clay",data=6},
  76. _matBlueSmooth = {block="minecraft:stained_hardened_clay",data=9},
  77. _matPurpleSmooth = {block="minecraft:stained_hardened_clay",data=10},
  78. _matWhiteTextured = {block="minecraft:planks",data=4},
  79. _matYellowTextured = {block="minecraft:planks",data=1},
  80. _matPinkTextured = {block="minecraft:planks",data=0},
  81. _matBlueTextured = {block="minecraft:planks",data=2},
  82. _matPurpleTextured = {block="minecraft:planks",data=5},
  83. }
  84.  
  85. --contains a list of all posible Buildzones (build a bit later)
  86. LOCS = {}
  87.  
  88. if DEBUG_MODE then
  89. GAME_LENGTH = 12000
  90. NUMBER_OF_BUILDZONES = 1
  91. end
  92.  
  93. -- see if the file exists
  94. function file_exists(file)
  95. local f = fs.open(file, "rb")
  96. if f then f:close() end
  97. return f ~= nil
  98. end
  99.  
  100. --creates a grid of absolute references (0,0) (1,0)
  101. function buildGrid(w,h)
  102. local grid = readGridFromFile()
  103. if grid then
  104. -- grid was read from teh file successfully
  105. else
  106. --generate file from scratch
  107. for z=0,h-1 do
  108. for x=0,w-1 do
  109. table.insert(grid,{x=x,z=z,played=false})
  110. end
  111. end
  112. end
  113. return grid
  114. end
  115.  
  116. function readGridFromFile()
  117. local result = nil
  118. fs.makeDir("/records")
  119. local filename = "/records/_buildzones-list.yaml"
  120.  
  121. if file_exists(filename) then
  122. ---read from file
  123. result = json.decodeFromFile(filename)
  124. end
  125. return result
  126. end
  127.  
  128. function writeGridToFile()
  129. fs.makeDir("/records")
  130. local filename = "/records/_buildzones-list.yaml"
  131.  
  132. local file = fs.open(filename,"w")
  133. file.write(json.encodePretty(LOCS))
  134. file.close()
  135. end
  136.  
  137. --sets where and how big the PHV area is
  138. --second number is along the long edge of PHV starting at the spawn side
  139. --first number is along the short edge of PHV starting from the park side
  140. if DEBUG_MODE then
  141. FIRSTZONE= {
  142. x=5,
  143. y=57,
  144. z=-7
  145. }
  146.  
  147. LOCS = buildGrid(1,3)
  148. else
  149. LOCS = buildGrid(11,27)
  150. end
  151.  
  152. --call these to return a proper minecraft item string including adventure mode properties
  153. function houseBlock(quant)
  154. text = BLOCKS.BUILDING_HOUSE.block..' '..quant..' '..BLOCKS.BUILDING_HOUSE.data..' {display:{Name:"Urban Resource",Lore:[Place this against a Detector to build denser, more urban buildings]},CanPlaceOn:["'..BLOCKS.BUILDING_HOUSE.block..'","'..BLOCKS.PLUG.block..'","'..BLOCKS.DETECT.block..'"]}'
  155. return text
  156. end
  157.  
  158.  
  159. function gardenBlock(quant)
  160. text = BLOCKS.BUILDING_GARDEN.block..' '..quant..' '..BLOCKS.BUILDING_GARDEN.data..' {display:{Name:"Nature Resource",Lore:[Place this against a Detector to build greener, more open buildings]},CanPlaceOn:["'..BLOCKS.BUILDING_HOUSE.block..'","'..BLOCKS.PLUG.block..'","'..BLOCKS.DETECT.block..'"]}'
  161. return text
  162. end
  163.  
  164. STARTING_ITEMS = {
  165. houseBlock(30), gardenBlock(30),
  166. 'stone_pickaxe 1 '..131-PICKAXE_USES..' {CanDestroy:["'..BLOCKS.BUILDING_HOUSE.block..'"],display:{Name:"Pickaxe",Lore:[Use this to remove up to '..PICKAXE_USES..' pieces of construction material]}}'
  167.  
  168. }
  169.  
  170.  
  171.  
  172. DEFAULT_NAME = 'BUILDING'
  173. --[[
  174. VOCAB_NAMES = {
  175. 'freestand-house',
  176. 'freestand-house',
  177. 'freestand-house',
  178. 'freestand-house',
  179. 'dbl-ext-house',
  180. 'dbl-ext-house',
  181. 'dbl-ext-house',
  182. 'dbl-ext-house',
  183. 'bridge-house',
  184. 'bridge-house',
  185. 'bridge-garden',
  186. 'bridge-garden',
  187. 'ext-house',
  188. 'ext-house',
  189. 'ext-house',
  190. 'ext-house',
  191. 'riser-1',
  192. 'riser-2',
  193. 'city-garden',
  194. 'city-plaza',
  195. 'dbl-ext-garden',
  196. 'dbl-ext-garden',
  197. 'dbl-ext-garden',
  198. 'dbl-ext-garden',
  199. 'ext-garden',
  200. 'ext-garden',
  201. 'ext-garden',
  202. 'ext-garden',
  203. 'corner-garden',
  204. 'corner-garden',
  205. 'corner-garden',
  206. 'corner-garden',
  207. 'corner-house',
  208. 'corner-house',
  209. 'corner-house',
  210. 'corner-house',
  211. 'freestand-garden',
  212. 'freestand-garden',
  213. 'freestand-garden',
  214. 'freestand-garden'
  215. }
  216. --]]
  217.  
  218.  
  219. ----------------------------------------------------------------------------------------------------------------
  220. -- the data structure below represents the catalogue of vocabularies as built in minecraft
  221. -- id - is unique for each vocab, starting from 1 going to 40 currently
  222. -- column and row - represent the "physical" location of the vocab model in the catalogue in the minecraft world
  223. -- nameEN and name DE - are names for english and german. for now english names must not have spaces, use dashes (-) instead
  224. -- typeEN and typeDE - are the type names, also in english and german such as tech&science spaces
  225. -- height - is how many blocks is this structure tall
  226. -- slots - is how many potential detector stones is this structure occupying as a building, ex. 2 for houses, 3 for corner extenstions, 0 for plazas
  227. -- green - is true or false and is used for easier calculation of the GREENEST GOAL - we dont use this field now and can be removed
  228. -- greenSlots - is how many slots are green and is used for easier calculation of the GREENEST GOAL
  229. VOCABS_DATA = {
  230. -- urban houses
  231. {id=1, column=1, row=1,nameEN="SINGLE-FAMILY-HOUSE",nameDE="EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=false, greenSlots=0, rewardUrban=false, rewardCount=4},
  232. {id=2, column=1, row=2,nameEN="SINGLE-FAMILY-HOUSE",nameDE="EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=false, greenSlots=0, rewardUrban=false, rewardCount=4},
  233. {id=3, column=1, row=3,nameEN="SINGLE-FAMILY-HOUSE",nameDE="EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=false, greenSlots=0, rewardUrban=false, rewardCount=4},
  234. {id=4, column=1, row=4,nameEN="SINGLE-FAMILY-HOUSE",nameDE="EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=false, greenSlots=0, rewardUrban=false, rewardCount=4},
  235. -- urban businesses
  236. {id=5, column=2, row=1,nameEN="GYM",nameDE="FITNESSSTUDIO", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=false, greenSlots=0, rewardUrban=false, rewardCount=8},
  237. {id=6, column=2, row=2,nameEN="OFFICE-BUILDING",nameDE="BÜROGEBÄUDE", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=false, greenSlots=0, rewardUrban=false, rewardCount=8},
  238. {id=7, column=2, row=3,nameEN="HOTEL",nameDE="HOTEL", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=false, greenSlots=0, rewardUrban=false, rewardCount=8},
  239. {id=8, column=2, row=4 ,nameEN="BANK",nameDE="BANK", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=false, greenSlots=0, rewardUrban=false, rewardCount=8},
  240. -- urban tech&science spaces
  241. {id=9, column=3, row=1,nameEN="LIBRARY",nameDE="BIBLIOTHEK", typeEN="TECH & SCIENCE SPACES",typeDE="WISSENSCHAFTSGEBÄUDE",height=16, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=10},
  242. {id=10, column=3, row=2,nameEN="FABLAB",nameDE="INNOVATIONSZENTRUM", typeEN="TECH & SCIENCE SPACES",typeDE="WISSENSCHAFTSGEBÄUDE",height=16, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=10},
  243. -- green tech&science spaces
  244. {id=11, column=3, row=3,nameEN="AQUAPONIC-GREENHOUSE",nameDE="AQUAPONIK-GEWÄCHSHAUS", typeEN="TECH & SCIENCE SPACES",typeDE="WISSENSCHAFTSGEBÄUDE",height=16, slots=1, green=true, greenSlots=1, rewardUrban=true, rewardCount=10},
  245. {id=12, column=3, row=4,nameEN="SCIENCE-BRIDGE",nameDE="WISSENSCHAFTSBRÜCKE", typeEN="TECH & SCIENCE SPACES",typeDE="WISSENSCHAFTSGEBÄUDE",height=16, slots=1, green=true, greenSlots=1, rewardUrban=true, rewardCount=10},
  246. -- urban house extensions
  247. {id=13, column=4, row=1,nameEN="HOUSE-EXTENSION",nameDE="HAUSERWEITERUNG", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=10, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=6},
  248. {id=14, column=4, row=2,nameEN="HOUSE-EXTENSION",nameDE="HAUSERWEITERUNG", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=10, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=6},
  249. {id=15, column=4, row=3,nameEN="HOUSE-EXTENSION",nameDE="HAUSERWEITERUNG", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=10, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=6},
  250. {id=16, column=4, row=4,nameEN="HOUSE-EXTENSION",nameDE="HAUSERWEITERUNG", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=10, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=6},
  251. --risers
  252. {id=17, column=5, row=1,nameEN="DOUBLE-FLOOR-RISER",nameDE="VERSCHIEBUNG-ZWEI-HOCH", typeEN="RISERS",typeDE="VERTIKALE VERSCHIEBUNGEN",height=0, slots=0, green=false, greenSlots=0, rewardUrban=true, rewardCount=8},
  253. {id=18, column=5, row=2,nameEN="SINGLE-FLOOR-RISER",nameDE="VERSCHIEBUNG-EINEN-HOCH", typeEN="RISERS",typeDE="VERTIKALE VERSCHIEBUNGEN",height=0, slots=0, green=false, greenSlots=0, rewardUrban=true, rewardCount=6},
  254. --plazas
  255. {id=19, column=5, row=3,nameEN="CITY-PLAZA",nameDE="STÄDTISCHER PLATZ", typeEN="PLAZAS",typeDE="PLÄTZE",height=0, slots=0, green=false, greenSlots=0, rewardUrban=false, rewardCount=2},
  256. {id=20, column=5, row=4,nameEN="PARK-PLAZA",nameDE="GRÜNER PLATZ", typeEN="PLAZAS",typeDE="PLÄTZE",height=0, slots=0, green=true, greenSlots=1, rewardUrban=true, rewardCount=2},
  257. --green businesses
  258. {id=21, column=6, row=1,nameEN="GREEN-GYM",nameDE="GRÜNES FITNESSSTUDIO", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=true, greenSlots=5, rewardUrban=true, rewardCount=8},
  259. {id=22, column=6, row=2,nameEN="GREEN-OFFICE-BUILDING",nameDE="GRÜNES BÜROGEBÄUDE", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=true, greenSlots=5, rewardUrban=true, rewardCount=8},
  260. {id=23, column=6, row=3,nameEN="GREEN-HOTEL",nameDE="GRÜNES HOTEL", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=true, greenSlots=5, rewardUrban=true, rewardCount=8},
  261. {id=24, column=6, row=4,nameEN="GREEN-BANK",nameDE="GRÜNES BANK", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=true, greenSlots=5, rewardUrban=true, rewardCount=8},
  262. ---green private garden extensions
  263. {id=25, column=7, row=1,nameEN="HOUSE-GARDEN",nameDE="PRIVATGARTEN", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=0, slots=0, green=true, greenSlots=1, rewardUrban=true, rewardCount=6},
  264. {id=26, column=7, row=2,nameEN="HOUSE-GARDEN",nameDE="PRIVATGARTEN", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=0, slots=0, green=true, greenSlots=1, rewardUrban=true, rewardCount=6},
  265. {id=27, column=7, row=3,nameEN="HOUSE-GARDEN",nameDE="PRIVATGARTEN", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=0, slots=0, green=true, greenSlots=1, rewardUrban=true, rewardCount=6},
  266. {id=28, column=7, row=4,nameEN="HOUSE-GARDEN",nameDE="PRIVATGARTEN", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=0, slots=0, green=true, greenSlots=1, rewardUrban=true, rewardCount=6},
  267. ---green gathering spaces
  268. {id=29, column=8, row=1,nameEN="OPEN-АIR-CINEMA",nameDE="FREILUFTKINO", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=true, greenSlots=3, rewardUrban=true, rewardCount=9},
  269. {id=30, column=8, row=2,nameEN="OPEN-AIR-SWIMMING-POOL",nameDE="FREIBAD", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=true, greenSlots=3, rewardUrban=true, rewardCount=9},
  270. {id=31, column=8, row=3,nameEN="GREEN-CAFE",nameDE="GRÜNES CAFÉ", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=true, greenSlots=3, rewardUrban=true, rewardCount=9},
  271. {id=32, column=8, row=4,nameEN="PALM-TREE-HOUSE",nameDE="PALMENGARTEN", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=true, greenSlots=3, rewardUrban=true, rewardCount=9},
  272. ----urban gathering spaces
  273. {id=33, column=9, row=1,nameEN="CINEMA",nameDE="KINO", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=false, greenSlots=0, rewardUrban=false, rewardCount=9},
  274. {id=34, column=9, row=2,nameEN="CONFERENCE-HALL",nameDE="KONFERENZHALLE", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=false, greenSlots=0, rewardUrban=false, rewardCount=9},
  275. {id=35, column=9, row=3,nameEN="CAFÉ",nameDE="CAFÉ", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=false, greenSlots=0, rewardUrban=false, rewardCount=9},
  276. {id=36, column=9, row=4,nameEN="ART-GALLERY",nameDE="KUNSTGALERIE", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=false, greenSlots=0, rewardUrban=false, rewardCount=9},
  277. ---green-roof houses
  278. {id=37, column=10, row=1,nameEN="GREEN-ROOF-HOUSE",nameDE="GRÜNES EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=true, greenSlots=2, rewardUrban=true, rewardCount=4},
  279. {id=38, column=10, row=2,nameEN="GREEN-ROOF-HOUSE",nameDE="GRÜNES EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=true, greenSlots=2, rewardUrban=true, rewardCount=4},
  280. {id=39, column=10, row=3,nameEN="GREEN-ROOF-HOUSE",nameDE="GRÜNES EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=true, greenSlots=2, rewardUrban=true, rewardCount=4},
  281. {id=40, column=10, row=4,nameEN="GREEN-ROOF-HOUSE",nameDE="GRÜNES EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=true, greenSlots=2, rewardUrban=true, rewardCount=4},
  282. }
  283.  
  284.  
  285. DEFAULT_REWARD = houseBlock(4)
  286.  
  287. REWARDS = {}
  288. --[[
  289. --Urban singlehouse rewards (costs 4 house, -2+2 activators)
  290. REWARDS[1] = gardenBlock(4)
  291. REWARDS[2] = gardenBlock(4)
  292. REWARDS[3] = gardenBlock(4)
  293. REWARDS[4] = gardenBlock(4)
  294. --Urban businesses rewards (costs 6 house, -2+1 activators)
  295. REWARDS[5] = gardenBlock(8)
  296. REWARDS[6] = gardenBlock(8)
  297. REWARDS[7] = gardenBlock(8)
  298. REWARDS[8] = gardenBlock(8)
  299. --Urban Tech&Science Spaces bridge rewards (costs 6 house, -3+2 activators)
  300. REWARDS[9] = gardenBlock(10)
  301. REWARDS[10] = gardenBlock(10)
  302. --Green Tech&Science Spaces garden bridge (costs 6 garden, -3+2 activators)
  303. REWARDS[11] = houseBlock(10)
  304. REWARDS[12] = houseBlock(10)
  305. --House extension rewards (costs 4 house, 1 activators)
  306. REWARDS[13] = gardenBlock(6)
  307. REWARDS[14] = gardenBlock(6)
  308. REWARDS[15] = gardenBlock(6)
  309. REWARDS[16] = gardenBlock(6)
  310. --riser 2 (costs 12 house)
  311. REWARDS[17] = houseBlock(6)
  312. --riser 1 (costs 8 house)
  313. REWARDS[18] = houseBlock(4)
  314. --plaza city (costs 4 house, -1 activator)
  315. REWARDS[19] = gardenBlock(2)
  316. --plaza park (costs 4 garden, -1 activator)
  317. REWARDS[20] = houseBlock(2)
  318. --green businesses (costs 6 garden, -2+1 activators)
  319. REWARDS[21] = houseBlock(8)
  320. REWARDS[22] = houseBlock(8)
  321. REWARDS[23] = houseBlock(8)
  322. REWARDS[24] = houseBlock(8)
  323. --extension-private garden rewards (costs 3 garden, -1 activators)
  324. REWARDS[25] = houseBlock(6)
  325. REWARDS[26] = houseBlock(6)
  326. REWARDS[27] = houseBlock(6)
  327. REWARDS[28] = houseBlock(6)
  328. --L-shaped green gathering places (costs 6 garden, -3+3 activators)
  329. REWARDS[29] = houseBlock(9)
  330. REWARDS[30] = houseBlock(9)
  331. REWARDS[31] = houseBlock(9)
  332. REWARDS[32] = houseBlock(9)
  333. --L-shaped urban gathering places (costs 6 house, -3+3 activators)
  334. REWARDS[33] = gardenBlock(9)
  335. REWARDS[34] = gardenBlock(9)
  336. REWARDS[35] = gardenBlock(9)
  337. REWARDS[36] = gardenBlock(9)
  338. --green-roof houses (costs 4 garden, -2+2 activators)
  339. REWARDS[37] = houseBlock(4)
  340. REWARDS[38] = houseBlock(4)
  341. REWARDS[39] = houseBlock(4)
  342. REWARDS[40] = houseBlock(4)
  343. --]]
  344.  
  345. --constructor for player object so that data structure is consistant
  346. function newPlayerData(name,x,y,z)
  347. local p = {
  348. name = name,
  349. x=x,
  350. y=y,
  351. z=z
  352. }
  353. return p
  354. end
  355.  
  356. --return a list of all players in the game world as player objects
  357. local function getAllPos(selector)
  358. local result, message = commands.tp("@a["..selector.."]","~ ~ ~")
  359. local names = {}
  360. if result == true then
  361. for i,result in ipairs(message) do
  362. local wordpattern = "[^, ]+"
  363. local numberpattern = "[%-% ]%d+[%.]%d+"
  364. local words,numbers = {},{}
  365.  
  366. for word in string.gmatch(result, wordpattern) do
  367. table.insert(words,word)
  368. end
  369.  
  370. for number in string.gmatch(result, numberpattern) do table.insert(numbers,number) end
  371.  
  372. local coords = {
  373. x = math.floor(numbers[1]),
  374. y = math.floor(numbers[2]),
  375. z = math.floor(numbers[3])
  376. }
  377. local name = words[2]
  378. table.insert(names,newPlayerData(name,coords.x,coords.y,coords.z))
  379. --print("Player Found - getAllPos")
  380. end
  381. end
  382. return names
  383. end
  384.  
  385. --sort table by random
  386. local function shuffleTable( t )
  387. local rand = math.random
  388. assert( t, "shuffleTable() expected a table, got nil" )
  389. local iterations = #t
  390. local j
  391.  
  392. for i = iterations, 2, -1 do
  393. j = rand(i)
  394. t[i], t[j] = t[j], t[i]
  395. end
  396. end
  397.  
  398. --returns a list of player objects containing all players who are standing on the given block, and who also are in the given selection
  399. local function getAllOnBlockType(block,selector)
  400. local result, message = commands.exec("execute @a["..selector.."] ~ ~ ~ detect ~ ~-1 ~ "..block.." -1 tp @p[r=1] ~ ~ ~")
  401. local names = {}
  402. if result == true then
  403. for i,result in ipairs(message) do
  404. local wordpattern = "[^, ]+"
  405. local numberpattern = "[%-% ]%d+[%.]%d+"
  406. local words,numbers = {},{}
  407.  
  408. for word in string.gmatch(result, wordpattern) do table.insert(words,word) end
  409. for number in string.gmatch(result, numberpattern) do table.insert(numbers,number) end
  410.  
  411. if numbers[1] and numbers[2] and numbers[3] then
  412. local coords = {
  413. x = math.floor(numbers[1]),
  414. y = math.floor(numbers[2]),
  415. z = math.floor(numbers[3])
  416. }
  417. local name = words[2]
  418. table.insert(names,newPlayerData(name,coords.x,coords.y,coords.z))
  419. print("Found a player - getOnBlock")
  420. else
  421. print("Error: Coordinate Numbers were missing")
  422. end
  423. end
  424. end
  425. return names
  426. end
  427.  
  428. --gives a player a HOMECOMER egg with their name on it. Removes all spawn eggs first
  429. local function giveHomecomer(name)
  430. commands.clear(name,'spawn_egg')
  431.  
  432. commands.give(name,'spawn_egg 1 '..HOMECOMER_VALUE..' {CanPlaceOn:["'..BLOCKS.PHVFLOOR.block..'","'..BLOCKS.CAMP_FLOOR.block..'","'..BLOCKS._matWhiteSmooth.block..'","'..BLOCKS._matWhiteSmooth2.block..'","'..BLOCKS._matYellowSmooth.block..'","'..BLOCKS._matPinkSmooth.block..'","'..BLOCKS._matBlueSmooth.block..'","'..BLOCKS._matPurpleSmooth.block..'","'..BLOCKS._matWhiteTextured.block..'","'..BLOCKS._matYellowTextured.block..'","'..BLOCKS._matPinkTextured.block..'","'..BLOCKS._matBlueTextured.block..'","'..BLOCKS._matPurpleTextured.block..'"],display:{Name:"HOMECOMER - '..name..'",Lore:[Use this on the floor to return to spawn]}}')
  433. end
  434.  
  435. --returns a list of HOMECOMER entities and their names
  436. local function getHomecomers()
  437. local result, message = commands.exec("execute @e[type="..HOMECOMER_TYPE.."] ~ ~ ~ tp @e[r=1] ~ ~ ~")
  438. local names = {}
  439. if result == true then
  440. for i,result in ipairs(message) do
  441. local wordpattern = "[^, ]+"
  442. local numberpattern = "[%-% ]%d+[%.]%d+"
  443. local words,numbers = {},{}
  444.  
  445. for word in string.gmatch(result, wordpattern) do table.insert(words,word) print(word) end
  446. for number in string.gmatch(result, numberpattern) do table.insert(numbers,number) end
  447.  
  448. if numbers[1] and numbers[2] and numbers[3] then
  449. local coords = {
  450. x = math.floor(numbers[1]),
  451. y = math.floor(numbers[2]),
  452. z = math.floor(numbers[3])
  453. }
  454. local name = words[4]
  455. table.insert(names,newPlayerData(name,coords.x,coords.y,coords.z))
  456. print("Found a player - getOnBlock "..name)
  457. else
  458. print("Error: Coordinate Numbers were missing")
  459. end
  460. end
  461. end
  462. return names
  463. end
  464.  
  465. local function removePlayerFromKew(game,playername)
  466. for _,kew in pairs(game.queues) do
  467. for index, player in ipairs(kew.playerlist) do
  468. if player.name == playername then
  469. table.remove(kew.playerlist,index)
  470. end
  471. end
  472. if #kew.playerlist == 0 and kew.phase == 2 then
  473. --game can be ended as no players are left
  474. kew.timer = 0
  475. end
  476. end
  477. end
  478.  
  479. local function movePlayerToSpawn(playername)
  480. respawnPlayer(playername)
  481. commands.async.tp(playername,SPAWN.x,SPAWN.y,SPAWN.z,SPAWN.a1,SPAWN.a2)
  482. commands.async.tellraw(playername,'["",{"text":"You used your HOMECOMER and TELEPORTED BACK TO SPAWN","color":"white"}]')
  483. commands.async.tellraw(playername,'["",{"text":"Du hast den HEIMKEHRER benutzt um dich zurück zum Anfang zu teleportieren.","color":"gold"}]')
  484. end
  485.  
  486. --takes a list of homecomers and deals with all those players, moving them back to spawn and removing them from game
  487. --also gives them a new homecomer
  488. local function dealWithHomecomers(game, homecomers)
  489. for _,homecomer in pairs(homecomers) do
  490. --remove player from current game if in game
  491. removePlayerFromKew(game,homecomer.name)
  492. --teleport them back to spawn
  493. movePlayerToSpawn(homecomer.name)
  494. --give a new homecomer
  495. giveHomecomer(homecomer.name)
  496. --particle effects
  497. --teleport message
  498. end
  499. --kill all homecomers
  500. if #homecomers>0 then
  501. commands.tp("@e[type="..HOMECOMER_TYPE.."]",100000,200,100000)
  502. commands.kill("@e[type="..HOMECOMER_TYPE.."]")
  503. os.sleep(#homecomers*0.2)
  504. end
  505. end
  506.  
  507.  
  508.  
  509.  
  510. --creates a villager with special items
  511. local function spawnVillager(x,y,z)
  512. commands.summon("Villager",x,y,z,'{Invulnerable:1,CustomName:Wool_Seller,Profession:2,Career:1,CareerLevel:6,Offers:{Recipes:[ {buy:{id:emerald,Count:1},sell:{id:wool,Count:'..WOOL_PER_EMERALD..',tag:{CanPlaceOn:["minecraft:diamond_block","minecraft:clay","minecraft:wool","minecraft:stained_hardened_clay"]}}}, {buy:{id:emerald,Count:1},sell:{id:stone_pickaxe,Count:1,Damage:'..131-PICKAXE_USES..',tag:{CanDestroy:["minecraft:wool"]}}} ]}}')
  513. end
  514.  
  515.  
  516. --displays a time as experience points to a selection of players
  517. local function displayTime(selector,minutes,seconds)
  518. --commands.title("@a["..selector.."]","subtitle",'{text:"Time left: '..minutes..":"..seconds..'",color:red,bold:false,underlined:false,italic:false,strikethrough:false,obfuscated:false}')
  519. commands.async.xp("-1000000L","@a["..selector.."]")
  520. local secondstot = (minutes * 60) + seconds
  521. commands.async.xp(tostring(secondstot).."L","@a["..selector.."]")
  522. end
  523.  
  524. --displays a title to a selection of players
  525. local function displayTitle(selector,text)
  526. commands.async.title("@a["..selector.."]","title",'{text:"'..text..'"}')
  527. end
  528.  
  529. --simply runs displayTitle on a list of players
  530. local function displayTitleToGroup(playerlist,text)
  531. for i,player in ipairs(playerlist) do
  532. displayTitle("name="..player.name,text)
  533. end
  534. end
  535.  
  536. --simply runs displayTime on a list of players
  537. local function displayTimeToGroup(playerlist,minutes,seconds)
  538. for i,player in ipairs(playerlist) do
  539. displayTime("name="..player.name,minutes,seconds)
  540. end
  541. end
  542.  
  543. --teleports a list of players to an exact place and sends them a message about it
  544. local function teleportToPoint(x,y,z,playerlist,clear,textEN, textDE)
  545. for i,player in ipairs(playerlist) do
  546. player.x = x
  547. player.y = y
  548. player.z = z
  549. commands.async.gamemode(2,player.name)
  550. if clear then
  551. commands.async.clear(player.name,"wool")
  552. commands.async.clear(player.name,"stone_pickaxe")
  553. end
  554. commands.tp("@a[name="..player.name.."]",x,y,z)
  555. commands.async.tellraw(player.name,'["",{"text":"'..textEN..'","color":"white"}]')
  556. commands.async.tellraw(player.name,'["",{"text":"'..textDE..'","color":"gold"}]')
  557. end
  558. end
  559.  
  560. --teleports a list of players to a given buildzone
  561. local function teleportToZone(buildzone,playerlist,textEN, textDE)
  562. teleportToPoint(buildzone.x+2+(buildzone.w/2),buildzone.y+5,buildzone.z+2+(buildzone.w/2),playerlist,true,textEN, textDE)
  563.  
  564. end
  565.  
  566. --gives the same list of items to a list of players
  567. local function giveItems(playerlist,itemlist)
  568. local given = 0
  569. for i,player in ipairs(playerlist) do
  570. --commands.async.clear(player.name)
  571. for j,item in ipairs(itemlist) do
  572. commands.async.give("@a[name="..player.name.."]",item)
  573. given = given +1
  574. end
  575. giveHomecomer(player.name)
  576. end
  577. return given
  578. end
  579.  
  580. --a multi builder which uses the vocab constructor to create sets of vocab
  581. local function makeVocabZones(quant,w)
  582. local x,y,z = FIRSTVOCAB.x, FIRSTVOCAB.y, FIRSTVOCAB.z
  583. local result = {}
  584. local id = 1
  585. for i=0,quant-1 do
  586. for k=0,3 do
  587. local zpos = i-4
  588. local ypos = k
  589. --print("vocab at X")
  590. --print(x-(2*w)-6)
  591. --print("and Z")
  592. --print(z+((w+1)*zpos))
  593. local nextVocab = newVocabZone(
  594. x-(2*w)-6,y+(ypos*(VOCAB_HEIGHT+3)),
  595. z+((w+1)*zpos),
  596. w,
  597. id,
  598. REWARDS[id] or DEFAULT_REWARD,
  599. VOCABS_DATA[id].nameEN or DEFAULT_NAME,
  600. VOCABS_DATA[id].nameDE or DEFAULT_NAME,
  601. VOCABS_DATA[id].typeEN,
  602. VOCABS_DATA[id].typeDE,
  603. VOCABS_DATA[id].height,
  604. VOCABS_DATA[id].slots,
  605. VOCABS_DATA[id].green,
  606. VOCABS_DATA[id].greenSlots,
  607. VOCABS_DATA[id].rewardUrban,
  608. VOCABS_DATA[id].rewardCount
  609. )
  610. table.insert(result,nextVocab)
  611. id = id +1
  612. end
  613. end
  614. return result
  615. end
  616.  
  617. --finds the next free location(or buildzone) for a new game in a given area.
  618. --giving force as True will mean it overrides the first location no matter what
  619. local function findNextLoc(width,zones,force)
  620. local x,y,z,locid = 0,0,0,1
  621. for i,loc in ipairs(LOCS) do
  622. locid = i
  623. x,y,z = FIRSTZONE.x+(loc.x*(width+1)),FIRSTZONE.y,FIRSTZONE.z+(-loc.z*(width+1)) -- these are the coordinates of this LOC in the minecraft world
  624. print("testing for available zone at: "..x..", "..y..", "..z)
  625. print("which is at grid cell at: "..loc.x..", "..loc.z)
  626. --local result,message = commands.testforblock(x,y+BUILDZONE_FLOOR_HEIGHT,z,"minecraft:air") -- this was used for the testing based on the minecraft model
  627. local result = true
  628. if loc.played then
  629. result = false
  630. print("zone has been played")
  631. end
  632. --print("testing done")
  633. --force the first zone to be selected unless it is taken in the "zones" parameter
  634. if force then result = true end
  635. --checks if the zone is already in the list of unavailable zones passed as parameter
  636. local zonefree = true
  637. for i,zone in ipairs(zones) do
  638. if zone.x == x and zone.z == z then
  639. zonefree = false
  640. end
  641. end
  642. --print("next position free is ",loc.x*width,oy,loc.z*width)
  643. --if result then print("true") else print("false") end
  644. if result and zonefree then
  645. --print("using loc: ",loc.x,loc.z)
  646. return x,y,z,locid --returns the coordinates of the new zone, plus its id in the LOCS table
  647. end
  648. end
  649. return nil,nil,nil, nil --returns empty if no zone is available
  650.  
  651. end
  652.  
  653. --relocates a buildzone to a new coordinate safely
  654. --avoids overlapping with other buildzones
  655. function moveBuildzone(buildzone,zones)
  656. local x,y,z,locid = findNextLoc(buildzone.w,zones)
  657. if x and y and z and locid then
  658. print("moved buildzone from "..buildzone.x..","..buildzone.z.." to "..x..","..y)
  659. local w = buildzone.w
  660. buildzone.x,buildzone.y,buildzone.z = x,y+BUILDZONE_FLOOR_HEIGHT,z
  661. buildzone.locid = locid --reassign the location id corresponding to the LOCS item for the grid cell of the moved zone
  662. buildzone.selector = "x="..x..",y="..tostring(y-1)..",z="..z..",dx="..w..",dy=256,dz="..w
  663. buildzone.structures = {} --a list of all vocabularies which have been contructed
  664. else
  665. print("buildzone at "..buildzone.x..","..buildzone.z.." stayed where it is")
  666. end
  667. end
  668.  
  669. --multi builder to create sets of buildzones using the buildzone constructor
  670. local function makeBuildzones(quant,vocab,width,height)
  671. local result = {}
  672. for i=1,quant do
  673. --print("locating available slot")
  674. local x,y,z,locid = findNextLoc(width,result)
  675. if x and y and z and locid then
  676. --print("made new buildzone at",x,y,z)
  677. table.insert(result,newBuildZone(x,y+height,z,width,vocab,locid))
  678. else
  679. --print("failed to make new buildzone")
  680. end
  681. end
  682.  
  683. local remaining = NUMBER_OF_BUILDZONES - #result
  684. --print("doing this remaining thing")
  685. for i=1, remaining do
  686. local x,y,z,locid = findNextLoc(width,result,true)
  687. if x and y and z and locid then
  688. --print("forced new buildzone at",x,y,z)
  689. table.insert(result,newBuildZone(x,y+height,z,width,vocab, locid))
  690. else
  691. print("failed to force new buildzone")
  692. end
  693. end
  694.  
  695.  
  696. return result
  697. end
  698.  
  699. --vocab constructor. Enforces some data structure
  700. function newVocabZone(x,y,z,w,id, reward,nameEN, nameDE, typeEN, typeDE, height, slots,green,greenSlots, rewardUrban, rewardCount)
  701. local nvz = {}
  702. nvz.x ,nvz.y ,nvz.z ,nvz.w = x,y,z,w
  703.  
  704. nvz.cx = nvz.x - nvz.w - 2
  705. nvz.cy = nvz.y
  706. nvz.cz = nvz.z
  707. nvz.nameEN = nameEN
  708. nvz.reward = reward
  709. --- new stuff
  710. nvz.id = id
  711. nvz.nameDE = nameDE
  712. nvz.typeEN = typeEN
  713. nvz.typeDE = typeDE
  714. nvz.height = height
  715. nvz.slots = slots
  716. nvz.green = green
  717. nvz.greenSlots = greenSlots
  718. nvz.rewardUrban = rewardUrban
  719. nvz.rewardCount = rewardCount
  720.  
  721. return nvz
  722.  
  723. end
  724.  
  725. --buildzone constructor. Enforces some data structure
  726. function newBuildZone(x,y,z,w,vocabZones,locid)
  727. local nbz = {}
  728. nbz.x ,nbz.y ,nbz.z ,nbz.w = x,y,z,w
  729. nbz.selector = "x="..x..",y="..(y-5)..",z="..z..",dx="..w..",dy=256,dz="..w
  730. nbz.structures = {} --a list of all vocabularies names which have been contructed
  731. nbz.buildings = {} --a list of all vocabularies with full data (x,y,z,id,name) which have been contructed
  732. nbz.filledSlots = 0 --to count how many slots have been filled with buildings. the matrix is 7x7x20 slots. one slot is 9x9x9 blocks big
  733. nbz.greenSlots = 0 --to count how many of the slots are green. the matrix is 7x7x20 slots. one slot is 9x9x9 blocks big
  734. nbz.variety = {} -- this stores how many buildings of each type are there. it is indexed on vocab.id and the value is the number of buildings from type vocab.id
  735. nbz.waitingForCheck = {}
  736. nbz.highest = 0
  737. nbz.vocab = vocabZones
  738. nbz.locid = locid
  739.  
  740. return nbz
  741. end
  742.  
  743. --kew constructor. Enforces some data structure
  744. function newQueue(buildzone,maxplayers)
  745. local q = {}
  746. q.timer = 1
  747. q.phase = 1
  748.  
  749. q.victory = false
  750. q.phases = {
  751. {
  752. name = "Selecting Players",
  753. length = 25,
  754. displaylength = 15
  755. },
  756. {
  757. name = "Game In Progress",
  758. length = GAME_LENGTH,
  759. displaylength = 70
  760. },
  761. {
  762. name = "Round Complete",
  763. length = 35,
  764. displaylength = 5
  765. }
  766. }
  767. q.playerlist = {}
  768. q.maxplayers = maxplayers
  769. q.buildzone = buildzone
  770.  
  771. return q
  772. end
  773.  
  774.  
  775. --creates a ring of blocks using coordinates
  776. function fillRing(x,y,z,w,block)
  777. commands.fill(x,y,z,x+w,y,z,block)
  778. commands.fill(x+w,y,z,x+w,y,z+w,block)
  779. commands.fill(x,y,z+w,x+w,y,z+w,block)
  780. commands.fill(x,y,z+w,x,y,z,block)
  781. end
  782.  
  783. function setup()
  784. print("debug: starting setup function.")
  785. local game = {}
  786. game.vocab = {}
  787. game.builds = {}
  788. game.queues = {}
  789. game.waitlist = {}
  790. game.spawn = SPAWN
  791. game.lastClock = os.clock()
  792. game.nowTime = os.clock()
  793.  
  794. --generate vocab rewards
  795. for i=1,#VOCABS_DATA do
  796. if VOCABS_DATA[i].rewardUrban then
  797. REWARDS[i] = houseBlock(VOCABS_DATA[i].rewardCount)
  798. else
  799. REWARDS[i] = gardenBlock(VOCABS_DATA[i].rewardCount)
  800. end
  801. end
  802.  
  803. --kill all villagers
  804. commands.exec("kill @e[type=Villager]")
  805.  
  806. --buildzone and vocabzone creation
  807. print("debug-setup: making vocab zones.")
  808. game.vocab = makeVocabZones(NUMBER_OF_VOCAB,VOCAB_WIDTH)
  809. print("debug-setup: making building zones.")
  810. game.builds = makeBuildzones(NUMBER_OF_BUILDZONES,game.vocab,BUILDZONE_WIDTH,BUILDZONE_FLOOR_HEIGHT)
  811.  
  812. for i,build in ipairs(game.builds) do
  813. table.insert(game.queues,newQueue(build,4))
  814. end
  815. print("debug-setup: testing for properly setup vocabs.")
  816. for i,vz in ipairs(game.vocab) do
  817. local x,y,z,w = vz.x,vz.y,vz.z,vz.w
  818. local cx,cy,cz = vz.cx,vz.cy,vz.cz
  819.  
  820. local detector, message1 = commands.testforblock(x+(math.floor(w/2)),y,z+(math.floor(w/2)),BLOCKS.DETECT.block)
  821. local blocker, message2 = commands.testforblock(x+(math.floor(w/2)),y,z+(math.floor(w/2)),BLOCKS.DETECT_DEAD.block)
  822. if not (detector or blocker) then
  823. for nx=0,2 do
  824. for nz=0,2 do
  825. commands.setblock(x+(nx*9)+4,y-1,z+(nz*9)+4,BLOCKS.VOCAB_REPLACE.block)
  826. commands.setblock(cx+(nx*9)+4,cy-1,cz+(nz*9)+4,BLOCKS.VOCAB_DETECT.block)
  827. end
  828. end
  829. commands.setblock(x+(math.floor(w/2)),y,z+(math.floor(w/2)),BLOCKS.DETECT_DEAD.block)
  830.  
  831. end
  832.  
  833. end
  834.  
  835. print("debug-setup: adding scoreboards.")
  836. --[[
  837. for i, name in ipairs(VOCAB_NAMES) do
  838. commands.scoreboard("objectives","add",name,"dummy")
  839. end
  840. --]]
  841.  
  842. print(#VOCABS_DATA)
  843. for i=1,#VOCABS_DATA do
  844. commands.scoreboard("objectives","add","building_"..i,"dummy")
  845. end
  846.  
  847. commands.gamerule("doDaylightCycle",false)
  848. commands.gamerule("keepInventory",true)
  849. commands.gamerule("doTileDrops",false)
  850. commands.gamerule("logAdminCommands",false)
  851. commands.gamerule("commandBlockOutput",false)
  852. commands.time("set",6000)
  853. commands.scoreboard("objectives","add","highscores","dummy","Best Neighbourhoods")
  854. commands.scoreboard("objectives","add","VillagerLife","dummy")
  855. commands.scoreboard("objectives","add","built","dummy", "Structures Built")
  856. commands.scoreboard("objectives","add","highest","dummy", "Personal Highest")
  857. commands.scoreboard("objectives","add","played","dummy","Games Played")
  858.  
  859. commands.title("@a","times",0,30,30) -- what does this do?
  860.  
  861. math.randomseed( os.time() )
  862. commands.scoreboard("objectives","setdisplay","sidebar","highscores")
  863. commands.scoreboard("objectives","setdisplay","list","played")
  864.  
  865. print("time is: "..os.time())
  866. print( "time is: "..textutils.formatTime( os.time(), false ) )
  867. print("day is: "..os.day())
  868. print("computer clock is: "..os.clock())
  869.  
  870. if DEBUG_MODE then
  871. for i,build in ipairs(game.builds) do
  872. build.phase = 2
  873. build.timer = 500
  874. end
  875. end
  876.  
  877. print("Computer Co-ordinates ",ox,oy,oz)
  878. print("20.000 Blocks Active!")
  879.  
  880. return game
  881. end
  882.  
  883. function checkForHomecomers(game)
  884. --execute on all homecomers
  885. local homecomers = getHomecomers()
  886. dealWithHomecomers(game,homecomers)
  887. end
  888.  
  889. --main game loop
  890. --runs the game object through each of these update steps in order
  891. function update(game)
  892. local elapsed = updateClock(game)
  893. --update players
  894. checkPlayers(game)
  895. doTimerUpdates(game,elapsed)
  896. doPhaseUpdates(game)
  897. doPhaseEnds(game)
  898. checkBoundaries(game)
  899. checkForHomecomers(game)
  900. if #game.waitlist > 0 then allocateWaiters(game) end
  901. end
  902.  
  903. --calculates elapsed time during a game tick
  904. function updateClock(game)
  905. game.nowTime = os.clock()
  906. local elapsed = game.nowTime - game.lastClock
  907. game.lastClock = game.nowTime
  908. return elapsed
  909. end
  910.  
  911. --updates all kews in the game object based on elapsed time
  912. function doTimerUpdates(game,elapsed)
  913. for i,kew in ipairs(game.queues) do
  914. kew.timer = kew.timer - elapsed
  915. end
  916. end
  917.  
  918. --check players are inside their buildzone and move them back if not
  919. function checkBoundaries(game)
  920. for i,kew in ipairs(game.queues) do
  921. if kew.phase ==2 then
  922. --boundaries
  923. local x_min = kew.buildzone.x
  924. local x_max = kew.buildzone.x+kew.buildzone.w
  925. local z_min = kew.buildzone.z
  926. local z_max = kew.buildzone.z+kew.buildzone.w
  927.  
  928. local toBeCorrected = {}
  929.  
  930. for j,player in ipairs(kew.playerlist) do
  931. local listOfOne = getAllPos('m=2,name='..player.name)
  932. if listOfOne and listOfOne[1] then
  933. player.x = listOfOne[1].x
  934. player.y = listOfOne[1].y
  935. player.z = listOfOne[1].z
  936. local changed = false
  937. if player.x > x_max then
  938. changed = true
  939. player.x = x_max-2
  940. end
  941. if player.x < x_min then
  942. changed = true
  943. player.x = x_min+2
  944. end
  945. if player.z > z_max then
  946. changed = true
  947. player.z = z_max-2
  948. end
  949. if player.z < z_min then
  950. changed = true
  951. player.z = z_min+2
  952. end
  953. if changed then teleportToPoint(player.x,kew.buildzone.y,player.z,{player},false,"TELEPORTED BACK TO GAME: Please stay inside the building zone or use HOMECOMER to leave the game!", "Zurück ins Spiel teleportiert: Bitte bleib innerhalb des Baufeldes oder nutze den HEIMKEHRER um das Spiel zu verlassen!") end
  954. end
  955. end
  956. end
  957. end
  958. end
  959.  
  960.  
  961. --here you can set the logic which determines if a buildzone was valuable.
  962. --Return true if it is crap and should be replaced
  963. function checkIfBuildzoneIsCrap(buildzone)
  964. if #buildzone.structures < 5 then
  965. print("Buildzone was crap")
  966. return true
  967. end
  968. print("Buildzone was ok")
  969. return false
  970. end
  971.  
  972.  
  973. --Everything that happens after a buildzone was completed
  974. --due to time limit.
  975. function cleanAfterVictory(buildzone)
  976. commands.async.setblock(buildzone.x,buildzone.y,buildzone.z,BLOCKS.VICTORY_MARKER.block)
  977. fillRing(buildzone.x,buildzone.y,buildzone.z,buildzone.w,"minecraft:air",0,"replace",BLOCKS.CONSTRUCTION.block,BLOCKS.CONSTRUCTION.data)
  978. for h=0,256-buildzone.y do
  979. commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air 0","replace",BLOCKS.DETECT.block,BLOCKS.DETECT.data)
  980. commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air 0","replace",BLOCKS.PLUG.block,BLOCKS.PLUG.data)
  981. commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air 0","replace",BLOCKS.BUILDING_GARDEN.block,BLOCKS.BUILDING_GARDEN.data)
  982. commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air 0","replace",BLOCKS.BUILDING_HOUSE.block,BLOCKS.BUILDING_HOUSE.data)
  983. end
  984. commands.async.fill(buildzone.x,buildzone.y-1,buildzone.z,buildzone.x+buildzone.w,buildzone.y-1,buildzone.z+buildzone.w,BLOCKS.CAMP_FLOOR.block,BLOCKS.CAMP_FLOOR.data,"replace",BLOCKS.PLUG.block,BLOCKS.PLUG.data)
  985. commands.async.fill(buildzone.x,buildzone.y,buildzone.z,buildzone.x+buildzone.w,buildzone.y,buildzone.z+buildzone.w,BLOCKS.PHVFLOOR.block,BLOCKS.PHVFLOOR.data,"replace","minecraft:air","0")
  986.  
  987. local wasCrap = checkIfBuildzoneIsCrap(buildzone)
  988. if wasCrap then
  989. --mark this buildzone for replacement
  990. commands.async.setblock(buildzone.x,buildzone.y,buildzone.z,"minecraft:air")
  991. else
  992. --need to find the LOCS item corresponding to this buildzone
  993. --change the flag to played=true
  994. LOCS[buildzone.locid].played = true
  995. --and write the LOCS object to the json file
  996. writeGridToFile()
  997. end
  998. end
  999.  
  1000. --these happen every tick and require the game object
  1001. --updates are performed on each Queue (kew) and within each
  1002. --of those on each buildzone.
  1003. function doPhaseUpdates(game)
  1004. for i,kew in ipairs(game.queues) do
  1005.  
  1006. local minutes = string.format("%02d",math.floor(kew.timer/60))
  1007. local seconds = string.format("%02d",math.floor(kew.timer - (minutes*60)))
  1008. if kew.timer <= 0 then
  1009. minutes = "00"
  1010. seconds = "00"
  1011. end
  1012.  
  1013. if kew.phase == 1 then
  1014. --waiting phase
  1015. if #kew.playerlist == kew.maxplayers and kew.timer > 5 then kew.timer = 5 end
  1016. if not DEBUG_MODE and #kew.playerlist == 0 then kew.timer = kew.phases[1].length end
  1017.  
  1018. displayTitleToGroup(kew.playerlist,"Game starting!")
  1019. displayTimeToGroup(kew.playerlist,minutes,seconds)
  1020. --show countdown
  1021. elseif kew.phase == 2 then
  1022. --playing phase
  1023. if #kew.playerlist == 0 then timer = 0 end -- finish if all players quit
  1024. -- do vocab logic
  1025. local victory = updatePlayedZone(kew.buildzone) --currently victory updatePlayedZone returns always false
  1026. --
  1027. displayTimeToGroup(kew.playerlist,minutes,seconds)
  1028.  
  1029. elseif kew.phase == 3 then
  1030. --end phase
  1031. displayTitleToGroup(kew.playerlist,"Use HOMECOMER to return")
  1032. --displayTimeToGroup(kew.playerlist,minutes,seconds)
  1033.  
  1034.  
  1035. end
  1036. end
  1037. end
  1038.  
  1039. --this runs after a buildzone is completed
  1040. --it should tally structure types and set scoreboard highscores
  1041. --it also rewards all participants with more played score
  1042. function processHighscores(kew)
  1043. local buildzone = kew.buildzone
  1044.  
  1045.  
  1046.  
  1047. --add score to players who finished this game
  1048. for _,player in ipairs(kew.playerlist) do
  1049. commands.async.scoreboard("players","add",player.name,"played",1)
  1050. end
  1051. end
  1052.  
  1053. --function to export a buildzone detail once it is complete
  1054. --requires a kew so it can access the playerlist
  1055. local function exportKewData(kew)
  1056. local buildzone = kew.buildzone
  1057. local saved = {}
  1058. saved.position =
  1059. {
  1060. x=buildzone.x,
  1061. y=buildzone.y,
  1062. z=buildzone.z
  1063. }
  1064. local timestamp = math.floor(os.clock())
  1065. --saved.timeCompleted = timestamp
  1066. saved.players = {}
  1067. for _, player in ipairs(kew.playerlist) do
  1068. table.insert(saved.players,player.name)
  1069. end
  1070. --saved.structures = buildzone.structures
  1071. saved.buildings = buildzone.buildings
  1072. saved.totals = tracker.tallyTable(buildzone.structures)
  1073. --saved.highest = buildzone.highest
  1074. saved.stats = {
  1075. cityVersion = CITY_VERSION,
  1076. height = buildzone.highest,
  1077. densityIndex = math.floor(100*buildzone.filledSlots/49), -- the density index is made from built area (filledSlots) over the ground area (7x7 slots = 49)
  1078. greenIndex = math.floor(100*buildzone.greenSlots/49), --the green index is made from green area (greenSlots) over the ground area (7x7 slots = 49)
  1079. variety = tablelength(buildzone.variety),
  1080. timeCompleted = timestamp,
  1081. gameLength = GAME_LENGTH
  1082. }
  1083.  
  1084. fs.makeDir("/records")
  1085.  
  1086. local file = fs.open("/records/"..timestamp.."at"..buildzone.x.."_"..buildzone.z..".yaml","w")
  1087. file.write(json.encodePretty(saved))
  1088. file.close()
  1089. end
  1090.  
  1091. --this code runs ONCE at the end of each phase
  1092. --what actually happens is specific to which phase the
  1093. --particular kew is in.
  1094. function doPhaseEnds(game)
  1095. for i,kew in ipairs(game.queues) do
  1096. if kew.timer <= 0 then
  1097. if kew.phase == 1 then
  1098. --waiting phase ends goto play phase
  1099.  
  1100. moveBuildzone(kew.buildzone,game.builds)
  1101. teleportToZone(kew.buildzone,kew.playerlist,"Your game has started! BUILD A HOUSE!", "Das Spiel hat begonnen! BAUE EIN HAUS!")--teleport selected players
  1102. cleanBuildzone(kew.buildzone)
  1103. prepareBuildzone(kew.buildzone)--prepare build zone
  1104. giveItems(kew.playerlist,STARTING_ITEMS) --give starting items
  1105. displayTitle(kew.buildzone.selector,"BUILD!")
  1106. kew.victory = false
  1107. --displayTime(kew.buildzone.selector,0,0)
  1108. kew.phase = 2
  1109. kew.timer = kew.phases[2].length
  1110. elseif kew.phase == 2 then
  1111. --playing phase ends goto end phase
  1112. processHighscores(kew)
  1113. exportKewData(kew)
  1114. cleanAfterVictory(kew.buildzone)
  1115. kew.phase = 3
  1116. --displayTime(kew.buildzone.selector,0,0)
  1117. kew.timer = kew.phases[3].length
  1118. elseif kew.phase == 3 then
  1119. --end phase ends goto waiting phase
  1120. removePlayersFromKew(game,kew)
  1121. kew.phase = 1
  1122. --displayTime(kew.buildzone.selector,0,0)
  1123. kew.timer = kew.phases[1].length
  1124. end
  1125. end
  1126. end
  1127. end
  1128.  
  1129.  
  1130. --Replaces everything that is needed to start the game. Does not rebuild the floor, or clear anything away.
  1131. --based on the settings it creates a full grid, or a partial grid, or no grid
  1132. --it also places the ring, although this is disabled for now
  1133. function prepareBuildzone(buildzone)
  1134. local bz = buildzone
  1135. local x,y,z,w = bz.x,bz.y,bz.z,bz.w
  1136. commands.fill(x,y-1,z,x+w,y-1,z+w,BLOCKS.CAMP_FLOOR) --place the white grid accross the full buildzone as a base
  1137. fillRing(buildzone.x,buildzone.y,buildzone.z,buildzone.w,BLOCKS.CONSTRUCTION.block) --this draws the construction stripe around the buildzone
  1138. --create the grid of detectors surrounded by plus plugs
  1139. if DO_GRID then
  1140. for x=0,6 do
  1141. for z=0,6 do
  1142. local rand = math.random()*100
  1143. --local result, text = commands.testforblock(bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+4,BLOCKS.CAMP_FLOOR.block)
  1144. if rand > GRID_HOLE_CHANCE then --and result then
  1145. commands.async.setblock(bz.x+(x*9)+4,bz.y,bz.z+(z*9)+4,BLOCKS.DETECT.block,BLOCKS.DETECT.data,"replace","minecraft:air")
  1146. commands.async.fill(bz.x+(x*9)+1,bz.y-1,bz.z+(z*9)+4,bz.x+(x*9)+7,bz.y-1,bz.z+(z*9)+4,BLOCKS.PLUG.block)
  1147. commands.async.fill(bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+1,bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+7,BLOCKS.PLUG.block)
  1148. --commands.async.setblock(bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+4,BLOCKS.CAMP_FLOOR.block)
  1149. end
  1150. end
  1151. end
  1152. end
  1153. commands.async.setblock(buildzone.x,buildzone.y,buildzone.z,BLOCKS.CONSTRUCTION.block)
  1154. end
  1155.  
  1156. --deletes everything inside the buildzone
  1157. function cleanBuildzone(buildzone)
  1158. print("Cleaning buildzone")
  1159. for h=0,VICTORY_HEIGHT+20 do
  1160. commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air")
  1161. end
  1162. end
  1163.  
  1164. --[[
  1165. --moves all players assigned to the queue into the waiting area for the provided game.
  1166. --It also changes them to Adventure mode and clears their inventory
  1167. function respawnPlayers(game,kew)
  1168. teleportToPoint(game.spawn.x,game.spawn.y,game.spawn.z,kew.playerlist,true,"TELEPORTED: Your game ended so you have been returned to the Spawn Point", "DE: TELEPORTED: Your game ended so you have been returned to the Spawn Point") --put players back in spawn area
  1169. for i,player in ipairs(kew.playerlist) do
  1170. --table.insert(game.waitlist,player)
  1171. respawnPlayer(player,"")
  1172. end
  1173. kew.playerlist = {}
  1174. end
  1175. --]]
  1176.  
  1177. function removePlayersFromKew(game,kew)
  1178. for _, player in ipairs(kew.playerlist) do
  1179. --commands.tell(player.name,"Your game is over. Use your Heimkehrer to return to spawn")
  1180. -- announce success in English
  1181. commands.async.tellraw(player.name,'["",{"text":"TIME OUT! GAME COMPLETE! Use your HOMECOMER to return to spawn.","color":"white"}]')
  1182. -- announce success in German
  1183. commands.async.tellraw(player.name,'["",{"text":"ENDE! SPIEL ABGESCHLOSSEN! Nutze den HEIMKEHRER um zum Anfang zurück zu kehren.","color":"gold"}]')
  1184. end
  1185. kew.playerlist = {}
  1186. end
  1187.  
  1188. function respawnPlayer(playername,message)
  1189. commands.tell(playername,message)
  1190. commands.async.gamemode(2,playername)
  1191. commands.async.clear(playername,"minecraft:wool")
  1192. commands.async.clear(playername,"minecraft:stone_pickaxe")
  1193. end
  1194.  
  1195. function checkForPlayerInBuildzone(player,buildzone)
  1196. local result,message = commands.testfor('@a[name='..player.name..','..buildzone.selector..']')
  1197. return result
  1198. end
  1199.  
  1200. function checkForPlayerInWaitzone(player)
  1201. local selector = "x="..WAITZONE.x..",y="..WAITZONE.y..",z="..WAITZONE.z..",dx="..WAITZONE.w..",dy=256,dz="..WAITZONE.l
  1202. local result,message = commands.testfor('@a[name='..player.name..','..selector..']')
  1203. return result
  1204. end
  1205.  
  1206. function checkPlayers(game)
  1207. local selector = "x="..WAITZONE.x..",y="..WAITZONE.y..",z="..WAITZONE.z..",dx="..WAITZONE.w..",dy=256,dz="..WAITZONE.l
  1208. local loggedIn = getAllPos('m=2,'..selector)
  1209. --refresh waitlist
  1210. game.waitlist = loggedIn
  1211. --check currently playing players
  1212. for l,kew in ipairs(game.queues) do
  1213. for i,builder in ipairs(kew.playerlist) do
  1214. local isPlaying = checkForPlayerInBuildzone(builder,kew.buildzone)
  1215. --remove players who are already in kews from the waitlist
  1216. for j, player in ipairs(loggedIn) do
  1217. if player.name == builder.name then
  1218. table.remove(loggedIn,j)
  1219. end
  1220. end
  1221. --if the game is in progress and the player is not found then remove them from the gamekew
  1222. if not isPlaying and kew.phase == 2 then
  1223. --table.remove(kew.playerlist,i)
  1224. --print("Removed "..builder.name.." from game in progress")
  1225. end
  1226. end
  1227. end
  1228. end
  1229.  
  1230. --adds players who wait in the orange room to slots in waiting buildzones
  1231. function allocateWaiters(game)
  1232. --find free slots
  1233. local freeslots = {}
  1234. for i, kew in ipairs(game.queues) do
  1235. if kew.phase == 1 and #kew.playerlist < kew.maxplayers then
  1236. local slots = kew.maxplayers - #kew.playerlist
  1237. for j=1,slots do
  1238. table.insert(freeslots,kew)
  1239. end
  1240. end
  1241. end
  1242.  
  1243. --RE-ENABLE SECOND SHUFFLETABLE IF YOU WANT RANDOM PLAYER MATCHUPS
  1244. shuffleTable(game.waitlist)
  1245. --shuffleTable(freeslots)
  1246.  
  1247. while #freeslots > 0 and #game.waitlist > 0 do
  1248. local player = table.remove(game.waitlist,1)
  1249. local freeslot = table.remove(freeslots,1).playerlist
  1250. table.insert(freeslot,player)
  1251. end
  1252. end
  1253.  
  1254. --PARTICLE FUNCTIONS
  1255. --particles shown to player while their shape is being checked for match
  1256. function searchParticle(x,y,z)
  1257. commands.async.particle("fireworksSpark",x,y,z,0.01,3,0.01,0.01,100)
  1258. end
  1259. -- particles shown to player on successful vocab match
  1260. function successParticle(x,y,z)
  1261. commands.async.particle("happyVillager",x,y,z,2,2,2,1,1000)
  1262. commands.async.playsound("random.levelup","@a",x,y,z,1,1.2)
  1263. end
  1264. --- particles shown to player on failed vocab match
  1265. function failParticle(x,y,z)
  1266. commands.async.particle("reddust",x,y,z,0.1,0.1,1.5,1,200)
  1267. commands.async.particle("reddust",x,y,z,1.5,0.1,0.1,1,200)
  1268. commands.async.playsound("random.bowhit","@a",x,y,z,1,0.8)
  1269. end
  1270.  
  1271. --makes sure that incoming check requests dont exist already
  1272. function addToChecklist(player,buildzone)
  1273. for _, detector in ipairs(buildzone.waitingForCheck) do
  1274. if detector.x == player.x and detector.y == player.y and detector.z == player.z then
  1275. return false
  1276. end
  1277. end
  1278. table.insert(buildzone.waitingForCheck,player)
  1279. return true
  1280. end
  1281.  
  1282. --removes all barrier blocks from a buildzone which are used to carve space in vocabs
  1283. function cleanBarriers(buildzone)
  1284. for h=0,200 do
  1285. commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air",0,"replace","minecraft:barrier")
  1286. end
  1287. end
  1288.  
  1289. --The main chunk of code which deals with stepping on detector blocks and reading the vocab
  1290. function updatePlayedZone(buildzone)
  1291. local victory = false
  1292. local buildzoneSelector = buildzone.selector
  1293. --get all players on diamond, add them to the list of things to check
  1294. local detectLocations = getAllOnBlockType(BLOCKS.DETECT.block,buildzoneSelector)
  1295. for _, player in ipairs(detectLocations) do
  1296. addToChecklist(player,buildzone)
  1297. end
  1298.  
  1299. --DEAL WITH THE DETECTOR AT THE TOP OF THE LIST IF THERE IS ONE
  1300. if #buildzone.waitingForCheck > 0 then
  1301. --DO PARTICLE EFFECTS IF A DETECTING BLOCK THAT IS DETECTING
  1302. for i,loc in ipairs(buildzone.waitingForCheck) do
  1303. searchParticle(loc.x,loc.y+1,loc.z)
  1304. end
  1305. local totalResult = false
  1306. local checked = table.remove(buildzone.waitingForCheck,1)
  1307. local x,y,z,name = checked.x,checked.y,checked.z,checked.name
  1308. for i,vocab in pairs(buildzone.vocab) do
  1309. local result,message = commands.testforblocks( vocab.x, vocab.y, vocab.z, vocab.x+vocab.w, vocab.y+VOCAB_HEIGHT, vocab.z+vocab.w, x-math.floor(vocab.w/2), y-1, z-math.floor(vocab.w/2),"masked")
  1310. if result then
  1311. --clone in the correct vocab
  1312. local cloneres,clonemes = commands.clone( vocab.cx, vocab.cy, vocab.cz, vocab.cx+vocab.w, vocab.cy+VOCAB_HEIGHT, vocab.cz+vocab.w, x-math.floor(vocab.w/2), y-1, z-math.floor(vocab.w/2),"masked")
  1313. if DEBUG_MODE then
  1314. print(clonemes[1])
  1315. end
  1316. commands.async.give(name,vocab.reward)
  1317. -- announce vocab success in English
  1318. local rewardType = 'nature'
  1319. local rewardTypeDE = 'grüne'
  1320. if vocab.rewardUrban then
  1321. rewardType = 'urban'
  1322. rewardTypeDE = 'urbane'
  1323. end
  1324. --print(vocab.typeEN)
  1325. --print(vocab.nameEN)
  1326. --print(vocab.height)
  1327. --print(vocab.slots)
  1328. --print(vocab.greenSlots)
  1329. --print(vocab.rewardCount)
  1330. --print(rewardType)
  1331. commands.async.tellraw(name,'["",{"text":"You built a '..vocab.nameEN.. ' ('..vocab.typeEN..'), which is '..vocab.height..'m tall and gives '..vocab.slots..' density pts, '..vocab.greenSlots..' green pts and '..vocab.rewardCount..'x '..rewardType..' resource!","color":"white"}]')
  1332. -- announce vocab success in German
  1333. commands.async.tellraw(name,'["",{"text":"Du hast ein '..vocab.typeDE..' | '..vocab.nameDE.. ' gebaut, das '..vocab.height..' Meter hoch ist und dir '..vocab.slots..' Punkte für die Dichte einbringt, jedoch '..vocab.greenSlots..' Punkte für Grünflächen und '..vocab.rewardCount..' '..rewardTypeDE..' Ressourcen!","color":"gold"}]')
  1334. --clear out barrier blocks
  1335. cleanBarriers(buildzone)
  1336.  
  1337. --ADD THE NEW STRUCTURE TO THE RECORDS
  1338. table.insert(buildzone.structures,vocab.nameEN) ---CHANGE HERE to make it record the place of the vocab too x, y, z and vocab id
  1339. local building = {id=vocab.id,xpos=x,ypos=y,zpos=z,name=vocab.nameEN,time=os.clock(),player=name}
  1340. table.insert(buildzone.buildings, building)
  1341. --if vocab.green then
  1342. buildzone.greenSlots = buildzone.greenSlots + vocab.greenSlots
  1343. --end
  1344. buildzone.filledSlots = buildzone.filledSlots + vocab.slots
  1345. local newHeight = y + vocab.height - buildzone.y-1 -- the Y coordinate of the highest block above the ground. Our world has its ground at 55 which is in buildzone.y, subtracting 1 to compensate for player height
  1346. if newHeight > buildzone.highest then
  1347. buildzone.highest = newHeight
  1348. end
  1349. -- count variety
  1350. print("adding variety: "..vocab.id)
  1351. local varietyId = vocab.id -- we use a variety id instead of the vocab id because vocab id 1,2,3,4 for example are all houses so it is the same variety
  1352. --we add only one type of house, one type of green house, one type of garden and one type of extension and we skip the two risers
  1353. if vocab.id == 2 or vocab.id == 3 or vocab.id == 4 then varietyId = 1 end-- only one type for the 4 different orientations of the house
  1354. if vocab.id == 14 or vocab.id == 15 or vocab.id == 16 then varietyId = 13 end-- only one type for the 4 different orientations of the house extension
  1355. if vocab.id == 26 or vocab.id == 27 or vocab.id == 28 then varietyId = 25 end-- only one type for the 4 different orientations of the house garden extension
  1356. if vocab.id == 38 or vocab.id == 39 or vocab.id == 40 then varietyId = 37 end-- only one type for the 4 different orientations of the green roof house
  1357. if varietyId ~= 17 and varietyId ~= 18 then --skip the two riser as they ar enot buildings
  1358. if buildzone.variety[varietyId] then
  1359. print("increasing existing item")
  1360. buildzone.variety[varietyId] = buildzone.variety[varietyId] + 1
  1361. else
  1362. print("adding new item")
  1363. buildzone.variety[varietyId] = 1
  1364. end
  1365. end
  1366.  
  1367. --- CHECK FOR PERSONAL RECORDS
  1368. --- check if the new structure is the highest
  1369. --- CHANGE here to live detect the contribution of the new structure to the 4 goals and update them
  1370.  
  1371. local personalbest = tracker.getScore(name,"highest")
  1372. if personalbest.count < newHeight then
  1373. --commands.async.tell(name,"You just topped your personal record for highest structure!")
  1374. commands.async.scoreboard("players","add",name,"highest",1)
  1375. -- announce success in English
  1376. commands.async.tellraw(name,'["",{"text":"You just topped your personal record for highest neighbourhood!","color":"white"}]')
  1377. -- announce success in German
  1378. commands.async.tellraw(name,'["",{"text":"Du hast soeben deinen persönlichen Rekord für die höchste Nachbarschaft gebrochen!","color":"gold"}]')
  1379. end
  1380.  
  1381. ---
  1382. ---
  1383. -- CHECK if placing the current structure would result in beating a server-wide record on the 4 goals
  1384. --calculate total slots - FOR GOAL "DENSEST NEIGHBOURHOOD"
  1385. local most = tracker.getScore("Densest_[points]","highscores")
  1386. local Kint = math.floor(100 * buildzone.filledSlots / 49) -- Kint is the density index made from built area (filledSlots) over ground area (7x7 slots = 49)
  1387. if Kint > most.count then
  1388. commands.async.scoreboard("players","set","Densest_[points]","highscores",Kint)
  1389. -- announce success in English
  1390. commands.async.tellraw("@a",'["",{"text":"Great! '..name.. ' just topped the record for the DENSEST NEIGHBOURHOOD!","color":"white"}]')
  1391. -- announce success in German
  1392. commands.async.tellraw("@a",'["",{"text":"Sehr gut! '..name.. ' hat einen neuen Rekord für die DICHTESTE NACHBARSCHAFT aufgestellt!","color":"gold"}]')
  1393. --commands.async.say("@a","The record for the Densest Neighbourhood has been topped!")
  1394. end
  1395.  
  1396. -- FOR THE GOAL "MOST DIVERSE NEIGHBOURHOOD"
  1397. -- here we need to count how many varieties of buildings there are
  1398. --local structures = tracker.tallyTable(buildzone.structures) -- this counts the variety of buildings in a game
  1399. local mostDiverse = tracker.getScore("Most-Diverse_[out-of-26]","highscores")
  1400. local typeCount = tablelength(buildzone.variety)
  1401. print("variety count is: "..typeCount)
  1402. if typeCount > mostDiverse.count then
  1403. commands.async.scoreboard("players","set","Most-Diverse_[out-of-26]","highscores", typeCount)
  1404. -- announce success in English
  1405. commands.async.tellraw("@a",'["",{"text":"Wow! '..name.. ' just topped the record for the MOST DIVERSE NEIGHBOURHOOD!","color":"white"}]')
  1406. -- announce success in German
  1407. commands.async.tellraw("@a",'["",{"text":"Wow! '..name.. ' hat soeben einen neuen Rekord für die VIELSEITIGSTE NACHBARSCHAFT aufgestellt!","color":"gold"}]')
  1408. --commands.async.say("@a","The record for the Most Diverse Neighbourhood has been topped!")
  1409. end
  1410.  
  1411. -- FOR THE GOAL "GREENEST NEIGHBOURHOOD"
  1412. -- here we need to count the number of green vocabs
  1413. local greenest = tracker.getScore("Greenest_[points]","highscores")
  1414. local Gint = math.floor(100*buildzone.greenSlots/49) --Gint is the green index, made from green area (greenSlots) over ground area (7x7 slots = 49)
  1415. if Gint > greenest.count then
  1416. commands.async.scoreboard("players","set","Greenest_[points]","highscores",Gint)
  1417. -- announce success in English
  1418. commands.async.tellraw("@a",'["",{"text":"Awesome! '..name.. ' just topped the record for the GREENEST NEIGHBOURHOOD!","color":"white"}]')
  1419. -- announce success in German
  1420. commands.async.tellraw("@a",'["",{"text":"Klasse! '..name.. ' hat einen neuen Rekord für die GRÜNSTE NACHBARSCHAFT aufgestellt!","color":"gold"}]')
  1421. ---commands.async.say("@a","The record for the Densest Neighbourhood has been topped!")
  1422. end
  1423.  
  1424. --calculate highest placement -- FOR THE GOAL "TALLEST NEIGHBOURHOOD"
  1425. local highest = tracker.getScore("Tallest_[meters]","highscores")
  1426. if buildzone.highest > highest.count then
  1427. commands.async.scoreboard("players","set","Tallest_[meters]","highscores",buildzone.highest)
  1428. -- announce success in English
  1429. commands.async.tellraw("@a",'["",{"text":"Incredible! '..name..' just topped the record for TALLEST NEIGHBOURHOOD!","color":"white"}]')
  1430. -- announce success in German
  1431. commands.async.tellraw("@a",'["",{"text":"Unglaublich! '..name..' hat einen neuen Rekord für die HÖCHSTE NACHBARSCHAFT aufgestellt!","color":"gold"}]')
  1432. --commands.async.say("@a","The record for the Tallest Negihbourhood has been topped!")
  1433. end
  1434.  
  1435.  
  1436. --increase the "how many structures did i build" score for the building player
  1437. commands.async.scoreboard("players","add",name,"built",1)
  1438. commands.async.scoreboard("players","add",name,"building_"..vocab.id,1)
  1439.  
  1440. totalResult = true
  1441. break
  1442.  
  1443. end
  1444. end
  1445. if totalResult then
  1446. --yey win, do a happy time
  1447. successParticle(x,y,z)
  1448. else
  1449. --no vocab found so do a fail particle
  1450. --announce in English
  1451. commands.async.tellraw(name,'["",{"text":"The shape you have built does not match any shape in the catalogue, try a different one.","color":"red"}]')
  1452. -- announce in German
  1453. commands.async.tellraw(name,'["",{"text":"Die Kombination, die du gebaut hast passt leider zu keinem Gebäude, versuche es mit einer anderen Form.","color":"gold"}]')
  1454. failParticle(x,y-1,z)
  1455. end
  1456. end
  1457. return victory
  1458. end
  1459.  
  1460. -- returns how many items are in a table/list
  1461. function tablelength(T)
  1462. local count = 0
  1463. for _ in pairs(T) do count = count + 1 end
  1464. return count
  1465. end
  1466.  
  1467. --Display game information on the monitor
  1468. function debugDisplay(game)
  1469. monitor.clear()
  1470. if blink then
  1471. monitor.setCursorPos(1,1)
  1472. monitor.setTextColor(colors.red)
  1473. monitor.write("Running")
  1474. monitor.setTextColor(colors.white)
  1475. redstone.setOutput("top",true)
  1476. blink = false
  1477. else
  1478. redstone.setOutput("top",false)
  1479. blink = true
  1480. end
  1481. local line = 2
  1482.  
  1483. for i,kew in ipairs(game.queues) do
  1484. monitor.setCursorPos(1,line)
  1485. local minutes = string.format("%02d",math.floor(kew.timer/60))
  1486. local seconds = string.format("%02d",math.floor(kew.timer - (minutes*60)))
  1487. monitor.write("Buildzone "..i.." | Phase: "..kew.phase.." | Time: "..minutes..":"..seconds)
  1488. monitor.setCursorPos(1,line+1)
  1489. for i,player in ipairs(kew.playerlist) do
  1490. monitor.write(player.name.." ")
  1491. end
  1492. line = line +2
  1493. end
  1494.  
  1495. monitor.setCursorPos(1,10)
  1496. for i,player in ipairs(game.waitlist) do
  1497. monitor.write(player.name.." ")
  1498. end
  1499. end
  1500.  
  1501. --BEGIN RUNTIME CODE
  1502. local blink = true
  1503. local game = setup()
  1504. while true do
  1505. update(game)
  1506. if monitor then debugDisplay(game) end
  1507. commands.async.weather("clear",10000)
  1508.  
  1509. local resetbutton = redstone.getInput("left")
  1510. if resetbutton then
  1511. print("reset!")
  1512. for i,kew in ipairs(game.queues) do
  1513. if kew.phase == 2 then
  1514. kew.timer = 5
  1515. end
  1516. end
  1517. end
  1518. sleep(2)
  1519. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement