After searching for a way to do this I found a script from robertbu that should work for detecting collisions, I am trying to make it so that when this system detects a collision with "Virus" by using other.CompareTag like you would with ontriggerenter(other:collider). Here's the neccesary part of the script.
function Update() {
if (Hit() == true){
if (other.CompareTag("Virus")){
Destroy(other.gameObject);
}
}
}
function Hit() : boolean {
var i = head;
var j = (head - 1);
if (j < 0) j = arv3.Length - 1;
while (j != head) {
if (Physics.Linecast(arv3[i], arv3[j], hit))
return true;
i = i - 1;
if (i < 0) i = arv3.Length - 1;
j = j - 1;
if (j < 0) j = arv3.Length - 1;
}
return false;
}
function Update() {
Hit();
}
function Hit() : boolean {
var i = head;
var j = (head - 1);
if (j < 0) j = arv3.Length - 1;
while (j != head) {
if (Physics.Linecast(arv3[i], arv3[j], hit) && hit.collider.tag == "Virus") {
Destroy(hit.collider.gameObject);
}
i = i - 1;
if (i < 0) i = arv3.Length - 1;
j = j - 1;
if (j < 0) j = arv3.Length - 1;
}
}
it works with this code
Related
Hello I have a connect four game who worked before null safety but I try to make the migration, but I have a problem with scores[i] = null; I can't write like that but without it I have a freeze when CPU is certain to loose
int _compute(Board board, int step, int deepness, List<double> scores) {
for (var i = 0; i < 7; ++i) {
final boardCopy = board.clone();
final target = boardCopy.getColumnTarget(i);
if (target == -1) {
scores[i] = null; // <<<---- HERE I CAN'T USE NULL
continue;
}
final coordinate = Coordinate(i, target);
boardCopy.setBox(coordinate, player);
if (boardCopy.checkWinner(coordinate, player)) {
scores[i] += deepness / (step + 1);
continue;
}
for (var j = 0; j < 7; ++j) {
final target = boardCopy.getColumnTarget(j);
if (target == -1) {
continue;
}
final coordinate = Coordinate(j, target);
boardCopy.setBox(coordinate, otherPlayer);
if (boardCopy.checkWinner(coordinate, otherPlayer)) {
scores[i] -= deepness / (step + 1);
continue;
}
if (step + 1 < deepness) {
_compute(board, step + 1, deepness, scores);
}
}
}
return _getBestScoreIndex(scores);
}
int _getBestScoreIndex(List<double> scores) {
int bestScoreIndex = scores.indexWhere((s) => s != null);
scores.asMap().forEach((index, score) {
if (score != null &&
(score > scores[bestScoreIndex] ||
(score == scores[bestScoreIndex] && _random.nextBool()))) {
bestScoreIndex = index;
}
});
return bestScoreIndex;
}
if I use List<double?>
int _compute(Board board, int step, int deepness, List<double?> scores) {
for (var i = 0; i < 7; ++i) {
final boardCopy = board.clone();
final target = boardCopy.getColumnTarget(i);
if (target == -1) {
scores[i] = null;
continue;
}
final coordinate = Coordinate(i, target);
boardCopy.setBox(coordinate, player);
if (boardCopy.checkWinner(coordinate, player)) {
scores[i] += deepness / (step + 1);//<<<---- HERE I CAN'T USE +=
continue;
}
for (var j = 0; j < 7; ++j) {
final target = boardCopy.getColumnTarget(j);
if (target == -1) {
continue;
}
final coordinate = Coordinate(j, target);
boardCopy.setBox(coordinate, otherPlayer);
if (boardCopy.checkWinner(coordinate, otherPlayer)) {
scores[i] -= deepness / (step + 1); //<<<---- HERE I CAN'T USE -=
continue;
}
if (step + 1 < deepness) {
_compute(board, step + 1, deepness, scores);
}
}
}
return _getBestScoreIndex(scores);
}
int _getBestScoreIndex(List<double?> scores) {
int bestScoreIndex = scores.indexWhere((s) => s != null);
scores.asMap().forEach((index, score) {
if (score != null && // <<<---- HERE I CAN'T USE score !=
(score > scores[bestScoreIndex] || // <<<---- HERE I CAN'T USE score >
(score == scores[bestScoreIndex] && _random.nextBool()))) {
bestScoreIndex = index;
}
});
return bestScoreIndex;
}
The issue with your code is that in the function definition you have defined the data type of score variable as List<double>. Due to which you get an error on assigning score[i] = null. To fix this use data type of score as List<double?>
i believe the param scores is a type-defined value and it has a double, which is a non null value. So you can't assign null to double as it has the type of value assigned.
You can make it double as an optional value, like a List<double?>. but with this, the values in the list will be optional and you need to force unwrap or do null check before using them.
I am implementing a simple genetic algorithm and everything works fine but I found that something is going wrong with the mutation function. I set the weights and biases of the agent's neural network to be identical to the fittest agent in the generation and then applied a mutation but all the agents are moving identically.
You can run my web app for yourself on this online p5 editor sketch: https://editor.p5js.org/aideveloper/sketches/Ot-SA1ulw
Can someone please help me understand what my mutation function is doing wrong?
agent.js:
class Agent {
constructor(args) {
this.x = args.x
this.y = args.y
this.color = args.color
this.weights = []
this.biases = []
this.lost = false
for(let i = 0; i < args.layers.length-1; i++)
this.weights.push([...new Array(args.layers[i+1])].map(() => [...new Array(args.layers[i])].map(() => random(-1, 1))))
for(let i = 0; i < args.layers.length-1; i++)
this.biases.push([...new Array(args.layers[i+1])].map(() => random(-1, 1)))
}
predict(x) {
let y = x
for(let i = 0; i < this.weights.length; i++) {
let hidden = [...new Array(this.weights[i].length)]
for(let j = 0; j < this.weights[i].length; j++) {
hidden[j] = 0
for(let k = 0; k < this.weights[i][j].length; k++)
hidden[j] += this.weights[i][j][k] * y[k]
hidden[j] += this.biases[i][j]
hidden[j] = 1 / (1 + Math.exp(-hidden[j]))
}
y = hidden
}
return y
}
mutate(rate=0.1) {
for(let i = 0; i < this.weights.length; i++) {
for(let j = 0; j < this.weights[i].length; j++) {
if(Math.random() < rate)
this.biases[i][j] += random(-1, 1)
for(let k = 0; k < this.weights[i][j].length; k++) {
if (Math.random() < rate)
this.weights[i][j][k] += random(-1, 1)
}
}
}
}
}
sketch.js:
const speed = 5
const n = 2000
let fittest_agent = null
let agents = []
let generation = 1
function setup() {
createCanvas(window.innerWidth, window.innerHeight)
for (let i = 0; i < n; i++) {
agents.push(new Agent({
x: 20,
y: window.innerHeight/2,
color: color(
Math.random() * 255,
Math.random() * 255,
Math.random() * 255
),
layers: [2, 10, 10, 1]
}))
}
fittest_agent = agents[0]
document.querySelector('#controls button').addEventListener('click', () => {
reproduce()
generation += 1
document.querySelector('#controls h1').textContent = `Generation: #${generation}`
})
}
function draw() {
noStroke()
background(255)
for (let i = 0; i < n; i++) {
fill(agents[i].color)
ellipse(agents[i].x, agents[i].y, 30, 30)
if(!agents[i].lost) {
let a = agents[i].predict([agents[i].x, agents[i].y])
agents[i].x += speed * cos(a * 100000)
agents[i].y += speed * sin(a * 100000)
}
fittest_agent = agents[i].x > fittest_agent.x ? agents[i] : fittest_agent
document.querySelector('#controls div').outerHTML = `<div id="fittest" style="background-color:rgb(${fittest_agent.color.levels[0]},${fittest_agent.color.levels[1]},${fittest_agent.color.levels[2]})"></div>`
document.querySelector('#controls span').textContent = Math.ceil(fittest_agent.x)
if(agents[i].x+15>window.innerWidth/4 && agents[i].x-15<window.innerWidth/4+30 && agents[i].y-15<window.innerHeight*2/3)
agents[i].lost = true
if(agents[i].x+15>window.innerWidth/2 && agents[i].x-15<window.innerWidth/2+30 && agents[i].y+15>window.innerHeight/3)
agents[i].lost = true
if(agents[i].x+15>window.innerWidth*3/4 && agents[i].x+15<window.innerWidth*3/4+30 && agents[i].y-15<window.innerHeight*2/3)
agents[i].lost = true
if(agents[i].x<15)
agents[i].lost = true
if(agents[i].y<15)
agents[i].lost = true
if(agents[i].x+15>window.innerWidth)
agents[i].lost = true
if(agents[i].y+15>window.innerHeight)
agents[i].lost = true
}
fill(135, 206, 235)
rect(window.innerWidth/4, 0, 30, window.innerHeight*2/3)
rect(window.innerWidth/2, window.innerHeight/3, 30, window.innerHeight*2/3)
rect(window.innerWidth*3/4, 0, 30, window.innerHeight*2/3)
}
function reproduce() {
agents.map(agent => {
agent.x = 20
agent.y = window.innerHeight/2
agent.lost = false
agent.weights = fittest_agent.weights
agent.biases = fittest_agent.biases
agent.color = color(random() * 255, random() * 255, random() * 255)
agent.mutate()
return agent
})
}
This is a visual representation of the issue:
The problem is in reproduce() function - you assign a reference to fittest agent's weights/biases array to new agent's weights/biases and all agents finally have same "brain". You should create a deep copy of fittest agent's weights/biases first and then assign it to agent.
function reproduce() {
agents.map(agent => {
// other code
agent.weights = deepCopy(fittest_agent.weights)
agent.biases = deepCopy(fittest_agent.biases)
// other code
}
}
function deepCopy(arr) {
// your implementation
}
You can use for ex. cloneDeep from lodash library.
I'm creating a Gmail script that includes 5 variables, one of which is a due date. I just want it to populate as MM/DD/YYYY, however, it is currently populating as Thu Sep 13 2018 00:00:00 GMT-0400 (EDT).
Is there a way I can do that? I've pasted my code below for your reference. Any assistance is much appreciated.
function getRowsData(sheet, range, columnHeadersRowIndex) {
columnHeadersRowIndex = columnHeadersRowIndex || range.getRowIndex() - 1;
var numColumns = range.getEndColumn() - range.getColumn() + 1;
var headersRange = sheet.getRange(columnHeadersRowIndex, range.getColumn(), 1, numColumns);
var headers = headersRange.getValues()[0];
return getObjects(range.getValues(), normalizeHeaders(headers));
}
function getObjects(data, keys) {
var objects = [];
for (var i = 0; i < data.length; ++i) {
var object = {};
var hasData = false;
for (var j = 0; j < data[i].length; ++j) {
var cellData = data[i][j];
if (isCellEmpty(cellData)) {
continue;
}
object[keys[j]] = cellData;
hasData = true;
}
if (hasData) {
objects.push(object);
}
}
return objects;
}
function normalizeHeaders(headers) {
var keys = [];
for (var i = 0; i < headers.length; ++i) {
var key = normalizeHeader(headers[i]);
if (key.length > 0) {
keys.push(key);
}
}
return keys;
}
function normalizeHeader(header) {
var key = "";
var upperCase = false;
for (var i = 0; i < header.length; ++i) {
var letter = header[i];
if (letter == " " && key.length > 0) {
upperCase = true;
continue;
}
if (!isAlnum(letter)) {
continue;
}
if (key.length == 0 && isDigit(letter)) {
continue;
}
if (upperCase) {
upperCase = false;
key += letter.toUpperCase();
} else {
key += letter.toLowerCase();
}
}
return key;
}
function isCellEmpty(cellData) {
return typeof(cellData) == "string" && cellData == "";
}
function isAlnum(char) {
return char >= 'A' && char <= 'Z' ||
char >= 'a' && char <= 'z' ||
isDigit(char);
}
function isDigit(char) {
return char >= '0' && char <= '9';
I am making a running game that detect the player knee movement and add speed , its working fine but the problem is when I stop running and keep one knee up the game speed do not stop ,I need the speed to be decreased when I stop running even if one knee is still.
if (!player1)
{
player1 = GameObject.Find("player1");
player1State.text = "";
}
if (player1)
{
player1FootRight = player1.transform.Find("KneeRight").gameObject;
player1FootLeft = player1.transform.Find("KneeLeft").gameObject;
player1State.text = "OK";
player1State.color = Color.white;
newPosP1 = player1FootRight.transform.position.y;
oldPosP1 = player1FootLeft.transform.position.y;
if (startRunning) {
if (foot1 && newPosP1 > oldPosP1)
{
float k = newPosP1 - oldPosP1;
if (k > 1 && speed < 100)
{
speed = speed + 7;
if(leftPath.speed < 15)
{
leftPath.speed = leftPath.speed + 3;
}
footOld = foot1;
foot1 = !foot1;
}
else
{
if (speed > 0)
{
speed = speed - 1;
if (leftPath.speed > 0)
{
leftPath.speed = leftPath.speed - 1;
}
}
if (speed < 0)
{
speed = 0;
}
if (leftPath.speed < 0)
{
leftPath.speed = 0;
}
}
}
if (!foot1 && newPosP1 < oldPosP1)
{
float k = oldPosP1 - newPosP1;
if (k > 1 && speed < 100)
{
speed = speed + 7 ;
if (leftPath.speed < 15)
{
leftPath.speed = leftPath.speed + 3;
}
footOld = foot1;
foot1 = !foot1;
}
else
{
if (speed > 0)
{
speed = speed - 1;
if (leftPath.speed > 0)
{
leftPath.speed = leftPath.speed - 1;
}
}
if (speed < 0)
{
speed = 0;
}
if (leftPath.speed < 0)
{
leftPath.speed = 0;
}
}
}
I have the method below, which in my Blackjack app will get the value of the hand which is an NSMutableArray. The problem here is that when 2 Ace's are in a hand, it should be a 12, but because it counts Ace's as 11, it results in being 22, which then makes lowValue returned.
How can I make it so that I can check and see if the for loop has already found an Ace and if it finds another, makes the next Ace worth only 1, not 11?
Thanks!
int getHandValue(NSMutableArray *hand) {
int lowValue = 0;
int highValue = 0;
for (KCCard *aCard in hand) {
if (aCard.value == Ace) {
lowValue+= 1;
highValue+= 11;
} else if (aCard.value == Jack || aCard.value == Queen || aCard.value == King) {
lowValue += 10;
highValue += 10;
} else {
lowValue += aCard.value;
highValue += aCard.value;
}
}
return (highValue > 21) ? lowValue : highValue;
}
Perhaps you can add a boolean value before the for loop setting it initially to NO. When an Ace is found then you can break from the for loop after setting the boolean to YES, that way if you encounter another Ace && your boolean value == YES you can handle the case accordingly.
int getHandValue(NSMutableArray *hand) {
int lowValue = 0;
int highValue = 0;
BOOL isFoundAce = NO;
for (KCCard *aCard in hand) {
if (aCard.value == Ace) {
if (isFoundAce) {
lowValue+= 1;
highValue+= 1;
}
else {
lowValue+= 1;
highValue+= 11;
isFoundAce= YES;
}
} else if (aCard.value == Jack || aCard.value == Queen || aCard.value == King) {
lowValue += 10;
highValue += 10;
} else {
lowValue += aCard.value;
highValue += aCard.value;
}
}
return (highValue > 21) ? lowValue : highValue;
}
My example without a redundant code from zsxwing's example:
int getHandValue(NSMutableArray *hand) {
int cardValue = 0;
int aceCount = 0;
for (KCCard *aCard in hand) {
if (aCard.value == Ace) {
aceCount++;
cardValue += 11;
} else if (aCard.value == Jack || aCard.value == Queen || aCard.value == King) {
cardValue += 10;
} else {
cardValue += aCard.value;
}
}
while ((cardValue > 21) && (aceCount > 0)) {
cardValue -= 10;
aceCount--;
}
return cardValue;
}