<commit_before>package sim

import (
	"encoding/json"
	"time"

	"github.com/Queens-Hacks/Propagate/sandbox"
	"github.com/Sirupsen/logrus"
)

type MarshalledState struct {
	State []byte
	Diff  []byte
}

// After calling this function it is no longer safe to do anything with s from
// outside of the simulation
func (s *State) StartSimulate() <-chan MarshalledState {
	ch := make(chan MarshalledState)

	go func() {
		// We want to run the thing every 500 milliseconds
		tick := time.NewTicker(time.Millisecond * 500)

		for {
			s.simulateTick()

			if !s.diff.isEmpty() {
				md, err := json.Marshal(s.diff)
				if err != nil {
					logrus.Fatal(err)
				}
				ms, err := json.Marshal(s.state)
				if err != nil {
					logrus.Fatal(err)
				}

				spores := []spore{}
				if s.diff.Spores != nil {
					spores = s.diff.Spores
				}

				s.diff = diff{[]tileDiff{}, map[string]*Plant{}, []string{}, spores}
				ch <- MarshalledState{ms, md}
			}

			<-tick.C
		}
	}()

	return ch
}

func (s *State) mkWorldState(_ *growthRoot) sandbox.WorldState {
	var ws sandbox.WorldState
	ws.Lighting = map[sandbox.Direction]float64{}

	ws.Lighting[sandbox.Left] = 0
	ws.Lighting[sandbox.Right] = 0
	ws.Lighting[sandbox.Up] = 0
	ws.Lighting[sandbox.Down] = 0

	return ws
}

func MoveGrowthNodeToLocation(loc Location, in sandbox.NewState, mh int, mw int) Location {
	new := loc

	if in.Dir == sandbox.Left {
		new.X -= 1
	} else if in.Dir == sandbox.Right {
		new.X += 1
	} else if in.Dir == sandbox.Up {
		new.Y -= 1
	} else if in.Dir == sandbox.Down {
		new.Y += 1
	} else {
		return loc
	}

	// Can't move there, it's out of bounds!
	if new.Y < 0 || new.Y > mh {
		logrus.Info("newY out of bounds", new.Y)
		return loc
	}
	if new.X < 0 || new.X > mw {
		logrus.Info("newY out of bounds")
		return loc
	}

	return new // new looks good!
}

func (s *State) applyChanges(root *growthRoot, in sandbox.NewState) {
	new := root.Loc

	if in.Operation == sandbox.Move {
		new = MoveGrowthNodeToLocation(root.Loc, in, s.Height(), s.Width())
		s.SetTile(new, Tile{PlantTile, &plantInfo{
			PlantId: root.PlantId,
			Parent:  root.Loc,
		}})
	} else if in.Operation == sandbox.Split {
		tmp := MoveGrowthNodeToLocation(root.Loc, in, s.Height(), s.Width())
		s.SetTile(tmp, Tile{PlantTile, &plantInfo{
			PlantId: root.PlantId,
			Parent:  root.Loc,
		}})
		s.SetTile(root.Loc, Tile{PlantTile, &plantInfo{
			PlantId: root.PlantId,
			Parent:  root.Loc,
		}})
	} else if in.Operation == sandbox.Wait {
		// that was easy
		return
	} else {
		return
	}<commit_msg>added bounds checking to tick<commit_after>package sim

import (
	"encoding/json"
	"time"

	"github.com/Queens-Hacks/Propagate/sandbox"
	"github.com/Sirupsen/logrus"
)

type MarshalledState struct {
	State []byte
	Diff  []byte
}

// After calling this function it is no longer safe to do anything with s from
// outside of the simulation
func (s *State) StartSimulate() <-chan MarshalledState {
	ch := make(chan MarshalledState)

	go func() {
		// We want to run the thing every 500 milliseconds
		tick := time.NewTicker(time.Millisecond * 500)

		for {
			s.simulateTick()

			if !s.diff.isEmpty() {
				md, err := json.Marshal(s.diff)
				if err != nil {
					logrus.Fatal(err)
				}
				ms, err := json.Marshal(s.state)
				if err != nil {
					logrus.Fatal(err)
				}

				spores := []spore{}
				if s.diff.Spores != nil {
					spores = s.diff.Spores
				}

				s.diff = diff{[]tileDiff{}, map[string]*Plant{}, []string{}, spores}
				ch <- MarshalledState{ms, md}
			}

			<-tick.C
		}
	}()

	return ch
}

func (s *State) mkWorldState(_ *growthRoot) sandbox.WorldState {
	var ws sandbox.WorldState
	ws.Lighting = map[sandbox.Direction]float64{}

	ws.Lighting[sandbox.Left] = 0
	ws.Lighting[sandbox.Right] = 0
	ws.Lighting[sandbox.Up] = 0
	ws.Lighting[sandbox.Down] = 0

	return ws
}

func boundsCheck(loc Location, mh int, mw int) Location {
	// Can't move there, it's out of bounds!
	if loc.Y < 0 || loc.Y > mh {
		logrus.Info("newY out of bounds", loc.Y)
		return loc
	}

	// loop around loop
	if loc.X < 0 {
		loc.X = mw + loc.X
	} else if loc.X >= mw {
		loc.X = loc.X - mw
	}

	return loc
}

func MoveGrowthNodeToLocation(loc Location, in sandbox.NewState, mh int, mw int) Location {
	new := loc

	if in.Dir == sandbox.Left {
		new.X -= 1
	} else if in.Dir == sandbox.Right {
		new.X += 1
	} else if in.Dir == sandbox.Up {
		new.Y -= 1
	} else if in.Dir == sandbox.Down {
		new.Y += 1
	} else {
		return loc
	}

	new = boundsCheck(new, mh, mw)

	return new // new looks good!
}

func (s *State) applyChanges(root *growthRoot, in sandbox.NewState) {
	new := root.Loc

	if in.Operation == sandbox.Move {
		new = MoveGrowthNodeToLocation(root.Loc, in, s.Height(), s.Width())
		s.SetTile(new, Tile{PlantTile, &plantInfo{
			PlantId: root.PlantId,
			Parent:  root.Loc,
		}})
	} else if in.Operation == sandbox.Split {
		tmp := MoveGrowthNodeToLocation(root.Loc, in, s.Height(), s.Width())
		s.SetTile(tmp, Tile{PlantTile, &plantInfo{
			PlantId: root.PlantId,
			Parent:  root.Loc,
		}})
		s.SetTile(root.Loc, Tile{PlantTile, &plantInfo{
			PlantId: root.PlantId,
			Parent:  root.Loc,
		}})
	} else if in.Operation == sandbox.Wait {
		// that was easy
		return
	} else {
		return
	}
{'fraction_non_alphanumeric': 0.14665391969407265, 'fraction_numerical': 0.006883365200764819, 'mean_word_length': 3.0053598774885146, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1242053', 'n_tokens_mistral': 2287, 'n_tokens_neox': 1995, 'n_words': 509}