Changing a variable based on a user's input - ruby

I am trying to have xpos and ypos change based on the direction the player enters. The program succeeds in asking Where to? but the position does not change. The script also always defaults to the last condition (puts("You're drunk.")).
For example:
> n
0
1
However, my output is:
> n
You're drunk.
0
0
This is my current code:
north = "n"
west = "w"
south = "s"
east = "e"
xpos = 0
ypos = 0
puts("WHERE TO?")
compass = gets
if compass == north
ypos = ypos + 1
elseif compass == west
xpos = xpos - 1
elseif compass == south
ypos = ypos - 1
elseif compass == east
xpos = xpos + 1
else
puts("You're drunk.") #if the player does not submit a proper direction
puts(xpos) #for debugging. prints zero when called showing the player has not moved
puts(ypos)
end

As others have pointed out, it's probably the missing chomp and the elseif.
Just a suggestion, but this cries out for a case statement:
case compass
when 'north'
ypos = ypos + 1
when 'west'
xpos = xpos - 1
when 'south'
ypos = ypos - 1
when 'east'
xpos = xpos + 1
else
puts("You're drunk.") #if the player does not submit a proper direction
puts(xpos)#for debugging. prints zero when called showing the player has not moved
puts(ypos)
end

It looks like you have two main issues, at least that I can see. First, elseif should be elsif. I'm surprised you aren't getting a syntax error on that.
Second, Kernel::gets returns the next line entered, up to and including the linebreak. This means that you have to remove the linebreak at the end, so that comparing with strings that don't have \r\n or \n, depending on your platform, can be compared. This is very simple: Just replace
compass = gets
with
compass = gets.chomp
(String#chomp reference)
Alternatively, if you'd like to get rid of all whitespace before and after, you could use
compass = gets.strip
(String#strip reference)

Related

Label on price scale homemade indicator

I have an indicator which indicate me round numbers on a specific chart in tradingview. For exemple, on US30 or NAS100 chart, the indicator draw horizontal line on round numbers ending by xx000 or xx500. Like 34 000, 34 500, 35 000, etc. My only problem is that the price of the line is not labled in the price scale. first picture is the actual indicator. Second is how I want it to look with the label at the right scale highlighted + the number ending in xx500 in blue + number ending by xx000 in pink.
image #1
image #2
I anybody able to make me the code line to make it work please?
Here is the code in the actual version:
//#version=5
indicator('LVL', overlay=true)
var levels = input(5, title='Number of levels')
var lineColor = input(color.rgb(255, 00, 255), 'Line color')
var lineWidth = input(1, title='Line width')
var spacing = if syminfo.ticker == 'XAUUSD'
25000
else if syminfo.ticker == 'XAGUSD'
250000
else if syminfo.ticker == 'SPX500USD'
500
else if syminfo.ticker == 'NAS100USD'
5000
else if syminfo.ticker == 'US30USD'
5000
else if syminfo.ticker == 'US30'
500
else if syminfo.ticker == 'BTCUSDT'
50000
else if syminfo.ticker == 'ETHUSDT'
25000
else if syminfo.type == 'crypto'
500
else if syminfo.type == 'forex'
500
else if syminfo.ticker == 'USOIL'
1000
else
2500
var step = syminfo.mintick * spacing
if barstate.islast
//label.new(bar_index, low, text=syminfo.type, yloc=yloc.abovebar)
for counter = 0 to levels - 1 by 1
price = if syminfo.type == 'index'
math.ceil(close / 4) * 4
else
close
stepUp = math.ceil(price / step) * step + counter * step
stepDown = math.floor(price / step) * step - counter * step
line.new(bar_index, stepUp, bar_index - 1, stepUp, xloc=xloc.bar_index, extend=extend.both, color=lineColor, width=lineWidth, style=line.style_solid)
line.new(bar_index, stepDown, bar_index - 1, stepDown, xloc=xloc.bar_index, extend=extend.both, color=lineColor, width=lineWidth, style=line.style_solid)
label.new(chart.right_visible_bar_time, levels, str.tostring(levels), xloc=xloc.bar_time)
label.new(chart.right_visible_bar_time, levels, str.tostring(levels), xloc=xloc.bar_time)
I tried with different line like, label for exemple
label.new(chart.right_visible_bar_time, levels, str.tostring(levels), xloc=xloc.bar_time)
label.new(chart.right_visible_bar_time, levels, str.tostring(levels), xloc=xloc.bar_time)
That is unfortunately not possible with lines.
If you can draw your lines with the plot() function, you can do it from your chart settings:

If statement not working in roblox studio

local Frame = script.Parent.Parent.Frame.BackgroundTransparency
local Red = Frame.RedTeam.BackroundTransparency
local Blue = Frame.BlueTeam.BackroundTransparency
local Button = script.Parent
Button.MouseButton1Click:Connect(
if Frame = 1 then
Frame = 0
Red = 0
Blue = 0
end
if Frame = 0 then
Frame = 1
Red = 1
Blue = 1
)
At
if Frame = 1 then
Frame = 0
Red = 0
Blue = 0
end
I get "Expected else when parsing, instead got =".
Also, at the "end" I get "Expected eof, instead got end"
I cant figure this out and nothing is working.
Replace if Frame = 1 then with if Frame == 1 then
If you want to check wether two values are equal you need to use the equality operator ==, not the assignment operator =.
Also your second if statement is missing its closing end.
Further you probably want to think about your logic.
If Frame equals 0 you'll assign 1. But then you'll end up in the next if statement with the condition Frame == 1 and assign 0 again.
So your code basically does nothing useful.
In lua, if statements use operators which are ==, ~=, >, <, >=, and <=.
the '==' statement basically compares if the first argument they get is the same as the second argument they get, which is the case for you here.
So you'll need to change the Frame = 1 and the Frame = 0 to Frame == 1 and the Frame == 0.
and at the end of your function, it is missing an end there. And also at the start it is not calling a new function. And for peak optimization, instead of using 2 if statements, you can just use 1 with an elseif.
Correction:
local Frame = script.Parent.Parent.Frame.BackgroundTransparency
local Red = Frame.RedTeam.BackroundTransparency
local Blue = Frame.BlueTeam.BackroundTransparency
local Button = script.Parent
Button.MouseButton1Click:Connect(function()
if Frame == 1 then
Frame = 0
Red = 0
Blue = 0
elseif Frame == 0 then
Frame = 1
Red = 1
Blue = 1
end
end)

Sign reverse does not work

For some reason when I try to reverse the sign of my current velocity in MATLAB, it just won't do it.
For example, I start off with velocity_x = 3 and velocity_y = 3 (I am drawing circle collisions).
Now inside of checking conditions I need to reverse the sign and I do the following:
% This doesn't work:
velocity_x = -velocity_x;
velocity_y = -velocity_y;
These expressions don't seem to work. Even though in the variable list it still shows as -3, the ball is just twitching and not going in the opposite direction. But when I simply put numbers there, it works fine!
% This works perfectly fine:
velocity_x = -3;
velocity_y = -3;
Here's the whole loop:
velocity_x = 3;
velocity_y = 3;
% While is not commanded to exit the loop
while exit_loop == false
[b1_x_c, b1_y_c] = getCenter(b1);
xMove(b1, velocity_x);
yMove(b1, velocity_y);
if ((b1_x_c + radius + 1) >= WINDOW_WIDTH) || ((b1_y_c + radius + 1) >= WINDOW_HEIGHT)
velocity_x = -1 * velocity_x;
velocity_y = -1 * velocity_y;
elseif ((b1_x_c - radius - 1) <= 0) || ((b1_y_c - radius - 1) <= 0)
velocity_x = (-1) * velocity_x;
velocity_y = (-1) * velocity_y;
end
redraw;
end % of the while loop
When you come in region where if or elseif condition fulfills, sign could change every cycle turn - velocity value 3 -3 3 -3 and so on...
You have to use some flag to indicate that the sign has already been changed and don't change it until that region will be leaved (a kind of hysteresis)

Touch Lua's Draw Library Basics

WARNING: This question is only for Touch Lua users who have purchased and have knowledge of the Draw Library.
PLEASE REFER TO THE BOTTOM PORTION OF THIS QUESTION TO SEE THE FULL PROGRAM. THE SNIPPETS I USE IN THE BEGINNING ARE PART OF THAT PROGRAM (NUMPAD.LUA)
Okay, so now for the questions:
•What's the use of "." between "b" and "x"? Or "b" and "draw"? Etc...
•How does the table set up the button? Please be super specific?
•Why is there a "+", "*", and "(j-1)" in lines 7 and 8?
•What's height and width doing in there? I thought there were only x and y.
function createButtons()
buttons = { }
local c = 1
for i = 1, 4 do
for j = 1, 3 do
local b = { }
b.x = 80 + 60 * (j-1)
b.y = 160 + 60 * (i-1)
b.width = 40
b.height = 40
b.color = draw.blue
b.draw = drawButton
b.action = digitAction
buttons[c] = b
c = c + 1
end
end
buttons[1].title = '7'
buttons[2].title = '8'
buttons[3].title = '9'
buttons[4].title = '4'
buttons[5].title = '5'
buttons[6].title = '6'
buttons[7].title = '1'
buttons[8].title = '2'
buttons[9].title = '3'
buttons[10].title = '0'
buttons[11].title = '.'
buttons[11].action = dotAction
buttons[12].title = 'C'
buttons[12].color = draw.orange
buttons[12].action = clearAction
end
Lastly, referencing the program as a whole...
•How does the button know when you tap on it? Specifically what are the lines of code and how does it work? (I have a very faint understanding of track touches btw)
function digitAction(button)
if string.len(display.title) < 16 then
sys.alert('tock')
if display.started then
display.title = display.title .. button.title
else
if button.title ~= '0' then
display.title = button.title
display.started = true
end
end
else
sys.alert('tink')
end
end
function dotAction(button)
if string.find(display.title, '.', 1, true) then
sys.alert('tink')
else
display.title = display.title .. '.'
display.started = true
sys.alert('tock')
end
end
function clearAction(button)
sys.alert('tock')
display.title = '0'
display.started= false
end
function createDisplay()
display = { }
display.x = 60
display.y = 100
display.width = 200
display.height = 40
display.title = '0'
display.color = draw.red
display.started = false
end
function createButtons()
buttons = { }
local c = 1
for i = 1, 4 do
for j = 1, 3 do
local b = { }
b.x = 80 + 60 * (j-1)
b.y = 160 + 60 * (i-1)
b.width = 40
b.height = 40
b.color = draw.blue
b.draw = drawButton
b.action = digitAction
buttons[c] = b
c = c + 1
end
end
buttons[1].title = '7'
buttons[2].title = '8'
buttons[3].title = '9'
buttons[4].title = '4'
buttons[5].title = '5'
buttons[6].title = '6'
buttons[7].title = '1'
buttons[8].title = '2'
buttons[9].title = '3'
buttons[10].title = '0'
buttons[11].title = '.'
buttons[11].action = dotAction
buttons[12].title = 'C'
buttons[12].color = draw.orange
buttons[12].action = clearAction
end
function drawDisplay()
draw.setfont('Helvetica', 20)
draw.setlinestyle(2, 'butt')
local x1, y1 = display.x, display.y
local x2, y2 = x1 + display.width, y1 + display.height
draw.roundedrect(x1, y1, x2, y2, 10, display.color)
local w, h = draw.stringsize(display.title)
local x = x2 - 10 - w
local y = y1 + (display.height - h)/2
draw.string(display.title, x, y, draw.black)
end
function drawButton(b)
draw.setfont('Helvetica', 18)
draw.setlinestyle(2, 'butt')
local x1, y1 = b.x, b.y
local x2, y2 = x1+b.width, y1+b.height
draw.roundedrect(x1, y1, x2, y2, 10, b.color)
local w, h = draw.stringsize(b.title)
local x = b.x + (b.width - w)/2
local y = b.y + (b.height - h)/2
draw.string(b.title, x, y, draw.black)
end
function drawButtons()
for i = 1, #buttons do
buttons[i].draw(buttons[i])
end
end
function lookupButton(x, y)
for i = 1, #buttons do
local b = buttons[i]
if x > b.x and x < b.x+b.width and y > b.y and y < b.y+b.height then
return b
end
end
return nil
end
function drawScreen()
draw.beginframe()
draw.clear()
drawDisplay()
drawButtons()
draw.endframe()
end
function touchBegan(x, y)
local b = lookupButton(x, y)
if b then
b.action(b)
end
end
function touchMoved(x, y)
end
function touchEnded(x, y)
end
function init()
draw.setscreen(1)
draw.settitle('Num Pad')
draw.clear()
draw.tracktouches (touchBegan, touchMoved, touchEnded)
createButtons()
createDisplay()
end
function mainloop()
while true do
draw.doevents()
drawScreen()
draw.sleep(30)
end
end
function main()
init()
mainloop()
end
-- start program
main()
Thank you so much for any help you can offer! I know this is a lot of questions, but this knowledge can really help propel me forward!
WARNING: This question is only for Touch Lua users who have purchased
and have knowledge of the Draw Library
Since when do you have to purchase something to answer programming questions? All your questions are on absolute Lua basics anyway.
What's the use of "." between "b" and "x"? Or "b" and "draw"? Etc...
The dot operator is used to index table members. So b.x will give you the value that belongs to key "x" in table b. Its syntactic sugar for b["x"].
How does the table set up the button? Please be super specific?
The function createButtons creates an empty table and fills it with buttons represented by a table b that stores various button properties.
Why is there a "+", "*", and "(j-1)" in lines 7 and 8?
Because the author of that program wants to add and multiply. Here the coordinates b.x and b.y are calculated. (j-1) is used because j starts at 1, but he needs it to start at 0 for this calculation.
The 2 for loops will create 4 rows of buttons, each containing 3 buttons as the x coordinate depends on parameter j while y depends on parameter i.
What's height and width doing in there? I thought there were only x
and y.
The button needs dimensions, not only a location. As b is created as a local variable within the for loop all its properties are set here. They may be changed later.
How does the button know when you tap on it? Specifically what are the
lines of code and how does it work?
Your mainloop will call draw.doevents() every cycle. So at some point there will be an event that will cause touchBegan to be called.
The button itself does not know that it was tapped. function touchBegan(x,y) will search if one of the buttons was hit at x,y by calling lookupButton(x,y) and call its action function. action is either one of dotAction, digitAction or clearAction. So if you tap on a digit button digitAction() will be called e.g.
Do yourself a favour and read a book on Lua or at least do a Lua tutorial. Befor diving into third party libraries. If you don't know how to index the most common Lua type or that + and * are arrithmetic operators, you will have a very hard time understanding code and you will not be productive in any way.
This program in particular uses tables to represent buttons, it does this to make it more manageable. The height and width are the same way. If you are new to the draw library, reviewing code like this is only going to confuse you. Most of your questions are actually about OOP honestly
Also this question probably isn't suitable for Stack Overflow right now. If you want help/a small tutorial on the subject feel free to PM me on the Touch Lua forum, my username is warspyking, but as it stands you need to either revise or delete this question.

Game piece movement optimization; given certain rules, find the minimum number of moves

Alright, so this is a fun one. I'm trying to code the movement of a piece in Japanese chess (also called shogi), specifically the silver general. The rules of the piece's movement are as such:
For position (x,y), the piece can move to either (x-1,y+1), (x,y+1), (x+1,y+1), (x-1,y-1), or (x+1,y-1). In other words, the piece can move to any of the spaces directly diagonal to it or to the space directly above it, but cannot move directly left, right, or down.
So I'm defining a function that takes the starting position (sx,sy) and the final position (gx,gy) as arguments and finds the quickest path between the two. Things seem to work for the case in which the starting and ending coordinates lie together on a horizontal or vertical line, but things start to fall apart after that. I don't know if I'm missing a condition, or if there's a better way to do this, but the function needs to work with the given arguments. Does anybody have any advice that might point me in the right direction? My code is as follows:
def minSteps(sx,sy,gx,gy):
count = 0
while [sx,sy] != [gx,gy]:
if (gy != sy and gx == sx):
if gy > sy:
sx = sx
sy += 1
count += 1
else:
sx += 1
sy -= 1
count += 1
elif (gy == sy and gx != sx):
if gx > sx:
sx += 1
sy += 1
count += 1
else:
sx -= 1
sy += 1
count += 1
elif (gy != sy and gx != sx):
if gy > sy:
if gx > sx:
sx += 1
sy += 1
count += 1
else:
sx -= 1
sy += 1
count += 1
if gy < sy:
if gx > sx:
sx += 1
sy -= 1
count += 1
else:
sx -= 1
sy -= 1
count += 1
return count
You might be able to try the A* Search Algorithm which can search the problem space for the minimum number of steps. Given the limited move options, the algorithm may need to be tweaked to specialise for the Shogi-limited movements.
Hope this Helps!
I assume the space is "infinite". So, I'm naming the different moves this way:
A = (x+1,y+1)
B = (x+1,y-1)
C = (x-1,y-1)
D = (x-1,y+1)
E = (x,y+1)
Since the order of these moves doesn't matter, instead of looking for a path, I prefer to count how many As, how many Bs, etc.
If we only consider A, B, C and D moves, then, we would have a grid seen in diagonal.
Points that are not part of this grid can be connected to the grid using an E move.
So, step 1: find x and y relative to the starting point:
x = gx-sx;
y = gy-sy;
Step 2: all counters to zero:
a = 0;
b = 0;
c = 0;
d = 0;
e = 0;
Step 3: if the point is not in "the grid", move it to the grid, using an E move:
if ((x&1) ^ (y&1)) {e=1; y--;}
Step 4: since it is easier for me to operate in positive numbers domain, numbers are mirrored in case of negative:
if (x<0) {hor=1; x=-x;}
else hor=0;
if (y<0) {ver=1; y=-y;}
else ver=0;
Step 5: Once all numbers are positive, I found either B and A counters, or D and A counters:
if (x>y) {b=(x-y)/2; a=y+b;}
else {d=(y-x)/2; a=x+d;}
Step 6: If numbers were mirrored, swap the counters accordingly (right becomes left, up becomes down):
if (hor) {hor=a; a=d; d=hor; c=b; b=0;}
if (ver) {ver=a; a=b; b=ver; ver=c; c=d; d=ver;}
...and that's it. Solution is in a,b,c,d,e counters. If you really need a path, you can derive it from the move counters.
Final note: there are multiple solutions in counters, because you can convert: A + D = 2 E

Resources