This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Syli's profile picture

TamaTurtle

Started by Syli, 11 December 2012 - 06:12 AM
Syli #1
Posted 11 December 2012 - 07:12 AM
Hallo

Iam pretty new to Lua and to ComputerCraft in General, to learn it better, i made a Tamagotchi like turtle, at the moment the Code is really messy, but i work on this just since 2 days, every day a few hours. There are few hardcoded Settings wich i want to seperate, aswell as some messy code in Generel.

As i started Programming on this Tamagotchi Turtle i just got a few Goals!
Run Automaticly (OK)
|_creating a start script wich not depends on a specific folder (to hide it eventually (like /disk/.randomFolderName)
|__I want the option to hide it, so i can sell it on my Server for Resources
|___Serial Key Aktivation to switch between Demo and Fullversion (NOT IN YET)
Load/Safe Data on a disk(OK)
Rednet Server Client Scripts(some sort of okay, but messy like hell
|_Rednet Comunication(OK)
|_Rednet Reconnect(NOT IN YET)
Tamagotchi like "Gameplay"
|_ name him (NOT IN YET)
|_ he needs to eat (OK)
|_ he needs to play with someone(NOT IN YET)
|_ he will grow/level over time and get new needs (NOT IN YET)
|_ Highscore (OK)
|_ He can die if nobody cares about him(OK)
|_ Random Movement, without diging (some sort of Okay, but messy)
Use Obejects (eh, no, but i use APIs :/ <– this part is realy messy)

so the most things are okay next thing i go into is classes, i hope to clean up the code with that, atm its just APIs and more like a proof of concept. But eventually i got feedback for this, so i can improve the program, but i talked to much here are the messy code:

Starting:
Spoiler1. ) put a diskdrive with the floppy down
2. ) put down a Computer, next to the diskdrive and attach the Rednet Modem (before you start the computer)
3. ) put down a Wirless Turtle next to the Disk Drive, and give him some sticks in slot 1
3. ) Reboot the turtle or the Computer if there is just the Console


if the Turtle dies, you need to replace him again to the diskdrive, and reboot the computer!

code as ZIP
Spoiler[attachment=758:2.zip]

folder structure:
Spoiler
/disk/startup
/disk/.startup.file
/disk/tama/client
/disk/tama/cMovement
/disk/tama/server
/disk/tama/settings
/disk/tama/shared
/disk/tama
/disk/tamaHighScore
/disk/tamaTable

/disk/startup
Spoiler
fs.delete("startup")
fs.copy("disk/.startup.file", "startup")
shell.run("startup")

/disk/.startup.file
Spoiler
path = "/disk"
exeFile = "tama"
running = false

files = { }
files = fs.list(path)

for i in pairs(files) do
  if files[i] ~= "startup" and files[i] ~= ".startup.file" then
	execute = path .. "/" .. files[i] .. "/" .. exeFile
	if fs.exists(execute) then
	  arg = path .. "/" .. files[i] .. "/"
	  shell.run(execute, arg)
	  running  = true
	end
  end
end

if running == false then
  print("Files Occurupted...")
  os.shutdown()
end

/disk/tama/client
Spoiler
-- Client File for the TamaTurtle!
function init()
  print("Loading Server Protocols...")
  os.loadAPI(settings.getRootPath() .. "shared")
  shared.init()
  print("Loading Server Protocols done...")
end


function startClientHandshake()
  local run = true
  while run do
	shared.sendBroadcast("TT_PING")
	local senderId, msg, distance = rednet.receive(6)
	if msg == "TT_HANDSHAKE" then
	  settings.setPartnerId(senderId)
	  shared.send("TT_HANDSHAKE_CONFIRMED")
	  run = false
	  return true
	end
  end
end

function waitForLastSavedTamaTable()
  local table = {}
  local senderId, msg, distance = rednet.receive()
  table = textutils.unserialize(msg)
  if table["id"] ~= "TT_TAMA_TABLE" then
	return false
  else
	print("received TamaTable: " .. msg)
	shared.setTamaTable(table)
  end
end

function sendTamaTable()
  msg = textutils.serialize(shared.getTamaTable())
  shared.send(msg)
end

local function sendFuelOutput(fuel)
  if fuel <= 100 then
	if fuel >= 75 then
	  print("Iam a little bit Hungry! FuelLevel: " .. fuel)
	  return true
	elseif fuel >= 50 then
	  print("Iam getting realy Hungry! FuelLevel: " .. fuel)
	  return true
	elseif fuel >= 1 then
	  print("Feed me, or i will die! FuelLevel: " .. fuel)
	  return true
	else
	  print("You did not feed me, now iam Dead!!!")
	  print("Its just your fault!")
	  return true
	end
  end
  return false
end

local function tryToRefuel()
  turtle.select(1)
  if turtle.getItemCount(1) >= 2 then
	turtle.refuel(turtle.getItemCount(1) - 1)
	shared.setTamaIndex("fuel", turtle.getFuelLevel())
	return true
  else
	return false
  end
end

function gameMode()
  changed = false
  print("WARNING: LEGIT FUEL ARE JUST STICKS! - IN FUTURE UPGRADES I WILL CHECK FOR THAT!")

while true do
	
	changed = false
	
	if turtle.getFuelLevel() <= 200 then
	  if tryToRefuel(turtle.getFuelLevel()) then
		changed = true
	  end
	end
	sendFuelOutput(turtle.getFuelLevel())
	
	if turtle.getFuelLevel() == 0 then
	  shared.setTamaIndex("alive", false)
	  print("Score: " .. tostring(shared.getTamaIndex("xp")))
	  print("GAME OVER")
	  print("")
	  print("made: by Syli")
	  print("Demoversion 1.0")
	  changed = true
	  sendTamaTable()
	  return false
	end

	if cMovement.randomMove() then
	  changed = true
	  xp = shared.getTamaIndex("xp") + 1
	  shared.setTamaIndex("xp", xp)
	end
	
	if changed then
	  sendTamaTable()
	end
  end

  os.sleep(120)
  os.shutdown()

end

/disk/tama/cMovement
Spoiler
-- Movement File for the tamaTurtle

local m_coords = {}
m_coords["x"] = 0
m_coords["y"] = 0
m_coords["z"] = 0
m_coords["f"] = 0

function init()
  print("Movement Manager loaded...")
end

local function changeOrientation(side)
  if side == "left" then
	m_coords["f"] = (m_coords["f"] - 1) % 4
  else
	m_coords["f"] = (m_coords["f"] + 1) % 4
  end
end

local function getMovingAxes()
  if m_coords["f"] % 2 == 0 then
	return "y"
  else
	return "x"
  end
end

local function isOnBoarder()
  if m_coords[getMovingAxes()] >= 12 or m_coords[getMovingAxes()] <= -12 then
	return true
  else
	return false
  end
end


local function turnLeft()
  turtle.turnLeft()
  changeOrientation("left")
end

local function turnRight()
  turtle.turnRight()
  changeOrientation("right")
end

local function turn(iSide)
  if iSide == 0 then
	turnRight()
  else
	turnLeft()
  end
  return true
end

local function moveDown()
  turtle.down()
  m_coords["y"] = m_coords["y"] - 1
  return true
end

local function moveUp()
  turtle.up()
  m_coords["y"] = m_coords["y"] + 1
  return true
end

local function tryMoveUp()
  if turtle.detectUp() then
	return false
  end

  if m_coords["y"] >= 6 then
	return false
  end

  moveUp()
  return true
end

local function tryMoveDown()
  if turtle.detectDown() then
	return false
  end

  if m_coords["y"] <= -6 then
	return false
  end

  moveDown()
  return true
end

local function tryMoveUpDown()
  if tryMoveUp() then
	return true
  elseif tryMoveDown() then
	return true
  end

  return false
end

local function moveForward()
  turtle.forward()
  if m_coords["f"] == 0 then
	m_coords["z"] = m_coords["z"] + 1
  elseif m_coords["f"] == 1 then
	m_coords["x"] = m_coords["x"] - 1
  elseif m_coords["f"] == 2 then
	m_coords["z"] = m_coords["z"] - 1
  elseif m_coords["f"] == 3 then
	m_coords["x"] = m_coords["x"] + 1
  else
	return false
  end
  return true
end

local function tryMoveForward(random)
  if isOnBoarder() then
	turn(1)
	return true
  end

  if turtle.detect() then
	if tryMoveUpDown() then
	  return true
	else
	  turn(1)
	  return true
	end
  end

  if random > 90 then
	if m_coords["y"] > 0 then
	  if tryMoveDown() then
		return true
	  end
	end
  end

  if random < 10 then
	if  m_coords["y"] < 0 then
	  if tryMoveUp() then
		return true
	  end
	end
  end

  moveForward()
  return true
end


function randomMove()
  random = math.random(0,100)
  while true do
	if random <= 10 then
	  turnLeft()
	  return true
	elseif random <=  20 then
	  turnRight()
	  return true
	else
	  if tryMoveForward(random) then
		return true
	  else
		print("Error in Movement randomMove(), r= " .. random)
		return false
	  end
	end
  end
end

/disk/tama/server
Spoiler
-- Server File for the TamaTurtle!

function init()
  print("Loading Server Protocols...")
  os.loadAPI(settings.getRootPath() .. "shared")
  shared.init()
  print("Loading Server Protocols done...")
end

function startServerHandshake()
  local run = true
  local notConfirmed = true
  while run do
	local senderId, msg, distance = rednet.receive()
	if msg == "TT_PING" then
	  settings.setPartnerId(senderId)
	  while notConfirmed do
		shared.sendBroadcast("TT_HANDSHAKE")
		local senderId, msg, distance = rednet.receive(15)
		if msg == "TT_HANDSHAKE_CONFIRMED" then
		  run = false
		  notConfirmed = false
		  return true
		end
	  end
	end
  end
end

function createNewTamaTable()
  newTamaTable = {}
  newTamaTable["id"] = "TT_TAMA_TABLE"
  newTamaTable["xp"] = 0
  newTamaTable["alive"] = true
  newTamaTable["fuel"] = 1
  shared.setTamaTable(newTamaTable)
  return true
end

function saveTamaTable()
  text = textutils.serialize(shared.getTamaTable())

  file = fs.open(settings.getRootPath() .. "tamaTable", "w")
  file.write(text)
  file.close()
  print("Received an Update from TamaTurtle, new Update Saved!")
end

function sendLastSavedTamaTable()
  if not fs.exists(settings.getRootPath() .. "tamaTable") then
	if createNewTamaTable() then
	  saveTamaTable()
	end
  end

  msg = ""

  while msg == "" do
	file = fs.open(settings.getRootPath() .. "tamaTable", "r")
	msg = file.readAll()
	file.close()
	
	if msg == "" then
	  if createNewTamaTable() then
		saveTamaTable()
	  end
	end
  end
  shared.send(msg)
end

local function getHighScore()
  if not fs.exists(settings.getRootPath() .. "tamaHighScore") then
	ret = {}
	return ret
  else
	file = fs.open(settings.getRootPath() .. "tamaHighScore", "r")
	sHighscore = ""
	sHighscore = file.readAll()
	file.close()
	return textutils.unserialize(sHighscore)
  end  
end

local function saveHighScore(newHighscore)
  text = textutils.serialize(newHighscore)

  file = fs.open(settings.getRootPath() .. "tamaHighScore", "w")
  file.write(text)
  file.close()
  print("Highscore Saved!")
end

local function isGameOver()
  if shared.getTamaIndex("alive") then
	return false
  else
	return true
  end
end

function receivingMode()
  while true do
	local senderId, msg, distance = rednet.receive()
	if senderId == settings.getPartnerId() then
	  trans = textutils.unserialize(msg)
	  if trans["id"] == "TT_TAMA_TABLE" then
		shared.setTamaTable(trans)
		saveTamaTable()
		
		if isGameOver() then
		  aHighscore = {}
		  aHighScore = getHighScore()
		  table.insert(aHighScore, shared.getTamaIndex("xp"))
		  saveHighScore(aHighScore)
		  if fs.exists(settings.getRootPath() .. "tamaTable") then
			if createNewTamaTable() then
			  saveTamaTable()
			end
		  end
		  return true -- GAME NEEDS A RESTART!
		end
	  end
	end
  end
  os.sleep(120)
  os.reboot()
end

/disk/tama/settings
Spoiler
local m_rootPath = ""
function getRootPath()
  return m_rootPath
end

local m_partnerId = nil
function setPartnerId(value)
  m_commId = value
end
function getPartnerId()
  return m_commId
end



function init(rootPath)
  print("Loading Settings...")
  m_rootPath = rootPath
  print("Settings Loaded...")
end

/disk/tama/shared
Spoiler
local m_modemSide = nil
local m_tamaTable = {}

local function open()
  local bOpen, sFreeSide = false, nil
	for n,sSide in pairs(rs.getSides()) do	
		if peripheral.getType( sSide ) == "modem" then
			sFreeSide = sSide
			m_modemSide = sFreeSide
			if rednet.isOpen( sSide ) then
				bOpen = true
				break
			end
		end
	end
	
	if not bOpen then
		if sFreeSide then
			print( "No modem active. Opening "..sFreeSide.." modem" )
			rednet.open( sFreeSide )
			return true
		else
			print( "No modem attached" )
			return false
		end
	end
	return true
end

function init()
  print("Loading Shared Protocols...")
  open()
  print("Loading Shared Protocols done...")
end

function getTamaTable()
  return m_tamaTable
end

function setTamaIndex(index, value)
  m_tamaTable[index] = value
end

function getTamaIndex(index, value)
  return m_tamaTable[index]
end

function setTamaTable(value)
  m_tamaTable = value
end

function sendBroadcast(msg)
  if rednet.isOpen(m_modemSide) == false then
	open()
  end

  rednet.broadcast(msg)  
end

function send(msg)
  rednet.send(settings.getPartnerId(), msg)
end

/disk/tama/tama
Spoiler
local tArgs = { ... }
local tama = nil

local function occurupted()
  print("System Occurupted, shutting donw in 10 seconds, please Contact Syli")
  os.sleep(10)
  os.shutdown()
end

local function startRedNetServer()
  if not os.loadAPI(settings.getRootPath() .. "server") then
	occurupted()
  end
  server.init()
  print("Start Searching for Tama-Turtle")
  server.startServerHandshake()
  print("Sending last saved data")
  server.sendLastSavedTamaTable()
end

local function startRedNetClient()
  if not os.loadAPI(settings.getRootPath() .. "client") then
	occurupted()
  end
  client.init()
  print("Start Searching for Server")
  client.startClientHandshake()
  print("Waiting for last saved data")
  client.waitForLastSavedTamaTable()
  print("Starting MovementManager")
  os.loadAPI(settings.getRootPath() .. "cMovement")
  cMovement.init()
end

term.clear()
term.setCursorPos(1, 1)

print("Loading Program Files... please wait")
print("")

if #tArgs < 1 then
  occurupted()
end

if not fs.exists(tArgs[1] .. "settings") then
  occurupted()
end

path = tArgs[1]

os.loadAPI(path .. "settings")
settings.init(path)

if turtle then
  startRedNetClient()
else
  startRedNetServer()
end

print("")
print("Loading Complete, have fun!")
os.sleep(1)
print("3..")
os.sleep(1)
print("2..")
os.sleep(1)
print("1..")
os.sleep(1)
term.clear()
term.setCursorPos(1,1)
if turtle then
  client.gameMode()
else
  print("Receiving Mode Enabled...")
  server.receivingMode()
end

/disk/tama/tamaHighScore
Spoiler
{}

/disk/tama/tamaTable
Spoiler
{["xp"]=0,["alive"]=true,["fuel"]=1,["id"]="TT_TAMA_TABLE",}


PS i stole the "open()" function from the GPS script to get started with the whole rednet thing, so credit for that part goes to the wiki, sorry i dont know who wrote it!
Jumbub1 #2
Posted 22 January 2013 - 02:16 AM
Is this project still going on, because I juts got some inspiration to build one, and am going to do a simple one for my first Big project!