I wouldn't say that it'd be strictly impossible, however if it can be done then it would come at a considerable cost to useability, versatility, etc.
One adjacent concept that comes to mind is the use of the :visited
CSS tag to extract a user's browsing habits. I remember seeing a demonstration of this where an "are you human" captcha was shown but the choice of image in each box was controlled by the :visited
tag. I can't find that post, but this medium article demonstrates a similer concept. There are mitigations to this luckily, but a fullproof solution would be to remove the tag's functionality altogether, which would make certain websites (like the one we're on right now!) much more inconvenient to use.
It seems trivial to me for a website to detect user behaviors that indicate the use of an adblocker. For example, if a request for a page is immediately followed by a request for a video on that page, rather than after 5-60 seconds, then they're likey using an adblocker. If there is an ad placed between two paragaphs in an article, but two distant paragraphs are visible at the same time, it is more likely (although not guaranteed) that they are using an adblocker. If a user triggers an abnormal amount of those heuristics then they get flagged as an adblocking user.
I agree pretty strongly with this generally. The farside has a way of having jokes that are so simple on it's face that I'm left thinking "surely I've missed something?" Usually it turns out that no, in fact, I got the joke and was just vastly underwhelmed.
For whatever reason I found this one to be mildly funny. Couldn't tell you why. Perhaps it's the idea that the people who built the atomic bomb weren't that smart after all?
I'm no biologist, but I'm pretty sure that this photo I took a while back has a lot of lichen:
That flakey & coral-looking stuff growing on the branches should be lichen.
I honestly assumed I was colorblind in one eye (I am diagnosed, at least)
The thing that finally got businesses to finally get off IE wasn't from the browser being worse than every other option. Heck, it wasn't even because it was a decrepit piece of software that lost it's former market dominance (and if anything businesses see that as a positive, not a negative).
What finally did that was microsoft saying there won't be any security updates. That's what finally got them off their ass; subtly threatening them with data breaches, exploits, etc. if they continue to use it. I don't see google doing this anytime soon, at least not without a "sequel" like microsoft had with edge.
bottom side of a pcb
Surprised TOEM isn't on your list, given the premise is pretty much exactly what you describe. Last I checked it comes up on the first page or something if you sort steam by highest rated.
Lunacid might also be a good game. I think it fits your criteria for me, but that might just be for me.
I dunno, having two primes sum to a power of two is undeniably powerful in my experience. The number of times a calculation goes from tedious to trivial from this sum is incalculable. The lowest I'd put it is A.
I have mine set up with a bunch of categories that are sorted with a prepended 3-digit number. Allows me to have different sections of category without it getting mixed up. ex:
010 S
011 A+
012 A
013 A-
014 B+
etc...
350 plz play soon
355 wont play
...
800 dont remember buying this
Odin
When I read the problem description I expected the input to also be 2 digit numbers. When I looked at it I just had to say "huh."
Second part I think you definitely have to do in reverse (edit: if you are doing a linear search for the answer), as that allows you to nope out as soon as you find a match, whereas with doing it forward you have to keep checking just in case.
package day5
import "core:fmt"
import "core:strings"
import "core:slice"
import "core:strconv"
Range :: struct {
dest: int,
src: int,
range: int,
}
Mapper :: struct {
ranges: []Range,
}
parse_range :: proc(s: string) -> (ret: Range) {
rest := s
parseLen := -1
destOk: bool
ret.dest, destOk = strconv.parse_int(rest, 10, &parseLen)
rest = strings.trim_left_space(rest[parseLen:])
srcOk: bool
ret.src, srcOk = strconv.parse_int(rest, 10, &parseLen)
rest = strings.trim_left_space(rest[parseLen:])
rangeOk: bool
ret.range, rangeOk = strconv.parse_int(rest, 10, &parseLen)
return
}
parse_mapper :: proc(ss: []string) -> (ret: Mapper) {
ret.ranges = make([]Range, len(ss)-1)
for s, i in ss[1:] {
ret.ranges[i] = parse_range(s)
}
return
}
parse_mappers :: proc(ss: []string) -> []Mapper {
mapsStr := make([dynamic][]string)
defer delete(mapsStr)
restOfLines := ss
isLineEmpty :: proc(s: string)->bool {return len(s)==0}
for i, found := slice.linear_search_proc(restOfLines, isLineEmpty);
found;
i, found = slice.linear_search_proc(restOfLines, isLineEmpty) {
append(&mapsStr, restOfLines[:i])
restOfLines = restOfLines[i+1:]
}
append(&mapsStr, restOfLines[:])
return slice.mapper(mapsStr[1:], parse_mapper)
}
apply_mapper :: proc(mapper: Mapper, num: int) -> int {
for r in mapper.ranges {
if num >= r.src && num - r.src < r.range do return num - r.src + r.dest
}
return num
}
p1 :: proc(input: []string) {
maps := parse_mappers(input)
defer {
for m in maps do delete(m.ranges)
delete(maps)
}
restSeeds := input[0][len("seeds: "):]
min := 0x7fffffff
for len(restSeeds) > 0 {
seedLen := -1
seed, seedOk := strconv.parse_int(restSeeds, 10, &seedLen)
restSeeds = strings.trim_left_space(restSeeds[seedLen:])
fmt.print(seed)
for m in maps {
seed = apply_mapper(m, seed)
fmt.print(" ->", seed)
}
fmt.println()
if seed < min do min = seed
}
fmt.println(min)
}
apply_mapper_reverse :: proc(mapper: Mapper, num: int) -> int {
for r in mapper.ranges {
if num >= r.dest && num - r.dest < r.range do return num - r.dest + r.src
}
return num
}
p2 :: proc(input: []string) {
SeedRange :: struct {
start: int,
len: int,
}
seeds := make([dynamic]SeedRange)
restSeeds := input[0][len("seeds: "):]
for len(restSeeds) > 0 {
seedLen := -1
seedS, seedSOk := strconv.parse_int(restSeeds, 10, &seedLen)
restSeeds = strings.trim_left_space(restSeeds[seedLen:])
seedL, seedLOk := strconv.parse_int(restSeeds, 10, &seedLen)
restSeeds = strings.trim_left_space(restSeeds[seedLen:])
append(&seeds, SeedRange{seedS, seedL})
}
maps := parse_mappers(input)
defer {
for m in maps do delete(m.ranges)
delete(maps)
}
for i := 0; true; i += 1 {
rseed := i
#reverse for m in maps {
rseed = apply_mapper_reverse(m, rseed)
}
found := false
for sr in seeds {
if rseed >= sr.start && rseed < sr.start + sr.len {
found = true
break
}
}
if found {
fmt.println(i)
break
}
}
}
Oh yeah, I misspoke, gonna edit.
hmm, my code keeps getting truncated at for y in ..
, anyone have any idea why? Maybe the "<" right after that confuses a parser somewhere?
Did this in Odin
Here's a tip: if you are using a language / standard library that doesn't have a set, you can mimic it with a map from your key to a nullary (in this case an empty struct)
package day3
import "core:fmt"
import "core:strings"
import "core:unicode"
import "core:strconv"
flood_get_num :: proc(s: string, i: int) -> (parsed: int, pos: int) {
if !unicode.is_digit(rune(s[i])) do return -99999, -1
pos = strings.last_index_proc(s[:i+1], proc(r:rune)->bool{return !unicode.is_digit(r)})
pos += 1
ok: bool
parsed, ok = strconv.parse_int(s[pos:])
return parsed, pos
}
p1 :: proc(input: []string) {
// wow what a gnarly type
foundNumSet := make(map[[2]int]struct{})
defer delete(foundNumSet)
total := 0
for y in 0..
Did mine in Odin. Found this day's to be super easy, most of the challenge was just parsing.
package day2
import "core:fmt"
import "core:strings"
import "core:strconv"
import "core:unicode"
Round :: struct {
red: int,
green: int,
blue: int,
}
parse_round :: proc(s: string) -> Round {
ret: Round
rest := s
for {
nextNumAt := strings.index_proc(rest, unicode.is_digit)
if nextNumAt == -1 do break
rest = rest[nextNumAt:]
numlen: int
num, ok := strconv.parse_int(rest, 10, &numlen)
rest = rest[numlen+len(" "):]
if rest[:3] == "red" {
ret.red = num
} else if rest[:4] == "blue" {
ret.blue = num
} else if rest[:5] == "green" {
ret.green = num
}
}
return ret
}
Game :: struct {
id: int,
rounds: [dynamic]Round,
}
parse_game :: proc(s: string) -> Game {
ret: Game
rest := s[len("Game "):]
idOk: bool
idLen: int
ret.id, idOk = strconv.parse_int(rest, 10, &idLen)
rest = rest[idLen+len(": "):]
for len(rest) > 0 {
endOfRound := strings.index_rune(rest, ';')
if endOfRound == -1 do endOfRound = len(rest)
append(&ret.rounds, parse_round(rest[:endOfRound]))
rest = rest[min(endOfRound+1, len(rest)):]
}
return ret
}
is_game_possible :: proc(game: Game) -> bool {
for round in game.rounds {
if round.red > 12 ||
round.green > 13 ||
round.blue > 14 {
return false
}
}
return true
}
p1 :: proc(input: []string) {
totalIds := 0
for line in input {
game := parse_game(line)
defer delete(game.rounds)
if is_game_possible(game) do totalIds += game.id
}
fmt.println(totalIds)
}
p2 :: proc(input: []string) {
totalPower := 0
for line in input {
game := parse_game(line)
defer delete(game.rounds)
minRed := 0
minGreen := 0
minBlue := 0
for round in game.rounds {
minRed = max(minRed , round.red )
minGreen = max(minGreen, round.green)
minBlue = max(minBlue , round.blue )
}
totalPower += minRed * minGreen * minBlue
}
fmt.println(totalPower)
}
Did this in Odin (very hashed together, especially finding the last number in part 2):
spoiler
package day1
import "core:fmt"
import "core:strings"
import "core:strconv"
import "core:unicode"
p1 :: proc(input: []string) {
total := 0
for line in input {
firstNum := line[strings.index_proc(line, unicode.is_digit):][:1]
lastNum := line[strings.last_index_proc(line, unicode.is_digit):][:1]
calibrationValue := strings.concatenate({firstNum, lastNum})
defer delete(calibrationValue)
num, ok := strconv.parse_int(calibrationValue)
total += num
}
// daggonit thought it was the whole numbers
/*
for line in input {
firstNum := line
fFrom := strings.index_proc(firstNum, unicode.is_digit)
firstNum = firstNum[fFrom:]
fTo := strings.index_proc(firstNum, proc(r:rune)->bool {return !unicode.is_digit(r)})
if fTo == -1 do fTo = len(firstNum)
firstNum = firstNum[:fTo]
lastNum := line
lastNum = lastNum[:strings.last_index_proc(lastNum, unicode.is_digit)+1]
lastNum = lastNum[strings.last_index_proc(lastNum, proc(r:rune)->bool {return !unicode.is_digit(r)})+1:]
calibrationValue := strings.concatenate({firstNum, lastNum})
defer delete(calibrationValue)
num, ok := strconv.parse_int(calibrationValue, 10)
if !ok {
fmt.eprintf("%s could not be parsed from %s", calibrationValue, line)
return
}
total += num;
}
*/
fmt.println(total)
}
p2 :: proc(input: []string) {
parse_wordable :: proc(s: string) -> int {
if len(s) == 1 {
num, ok := strconv.parse_int(s)
return num
} else do switch s {
case "one" : return 1
case "two" : return 2
case "three": return 3
case "four" : return 4
case "five" : return 5
case "six" : return 6
case "seven": return 7
case "eight": return 8
case "nine" : return 9
}
return -1
}
total := 0
for line in input {
firstNumI, firstNumW := strings.index_multi(line, {
"one" , "1",
"two" , "2",
"three", "3",
"four" , "4",
"five" , "5",
"six" , "6",
"seven", "7",
"eight", "8",
"nine" , "9",
})
firstNum := line[firstNumI:][:firstNumW]
// last_index_multi doesn't seem to exist, doing this as backup
lastNumI, lastNumW := -1, -1
for {
nLastNumI, nLastNumW := strings.index_multi(line[lastNumI+1:], {
"one" , "1",
"two" , "2",
"three", "3",
"four" , "4",
"five" , "5",
"six" , "6",
"seven", "7",
"eight", "8",
"nine" , "9",
})
if nLastNumI == -1 do break
lastNumI += nLastNumI+1
lastNumW = nLastNumW
}
lastNum := line[lastNumI:][:lastNumW]
total += parse_wordable(firstNum)*10 + parse_wordable(lastNum)
}
fmt.println(total)
}
Had a ton of trouble with part 1 until I realized I misinterpreted it. Especially annoying because the example was working fine. So paradoxically part 2 was easier than 1.
I don't think this can really be answered until after the fact. Anything that I (and I suspect most) people could say about an artstyle are going to be particular to an instance of that artsyle. If I'd give advice as someone who is neither an artist nor a game designer, what attracts me more than anything is a unique artstyle, which, if I'm gonna give a brutal opinion, starting from a vague category like 'pixel', 'hand drawn' or '3D' probably won't get you there.
I feel like I even struggle to answer your question at face value because it doesn't align well at all with how I conceptualize game art. For example, Cruelty Squad is a game that I don't think I'd have gotten if not for it's artsyle. Like, sure, it's 3D, but it's a lot more like a PilotRedSun animation than it is a game like TF2. Or take a game like Factorio: most of the assets of that game are pre-rendered 3D sprites, so despite being artisticly unique in a way that interests me it doesn't fit into the categories you've asked about. The best I can say is "I dunno", and I don't think anyone else can answer it further than that.
There is the Anno series of games, which are technically RTS games but if I'm honest I find them the most fun when I go out of my way to avoid combat/micromanagement. I've only played 1404, 2070, and 2205, 2070 being the best in my opinion, but it has a bad history with DRM so I'd suggest 1404 (known as "Dawn of Discovery" in the US because us americans are afraid of numbers apparently).
Edit: looking at the steam page it looks like they decided to take 1404 down and made a new page where the game is (mostly) unchanged besides requiring you to jump through all the BS hoops that 2070 did, so I'd say if you're gonna spend money get 1404 on GOG, or if you are willing to do unspeakable things go with 2070.
To be fair, that post specifically asks people who don't have a technical background. It can be used to show that laymen have the capacity to use a federated platform like lemmy, but not that they are a significant portion of the userbase (albeit that post does have a lot of replies).
It's a setting you can change. The default is a "quick generation" mode which looks as similar to the world seed/settings as it can without taking the performance hit of actually generating it. But it can either be changed to generate the chunks genuinely out to the render distance (which would be lag hell for 128 chunks) or to only render already generated chunks (like you suspect). Only the latter works in multiplayer though.